From e6c19730584b7999ec2752509df1ec1c7ee019b2 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Fri, 31 Dec 2021 15:33:54 -0500 Subject: [PATCH 1/4] Potential Wishlist schema --- api/shapes/wishlist.ts | 78 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 api/shapes/wishlist.ts diff --git a/api/shapes/wishlist.ts b/api/shapes/wishlist.ts new file mode 100644 index 0000000..386b97a --- /dev/null +++ b/api/shapes/wishlist.ts @@ -0,0 +1,78 @@ +/** Compatible superset of Little Light wishlist format */ + +interface WishList { + name: string; + description: string; + includes: string[]; + // Per-item-hash rolls + data: ItemRoll[]; + // Global rolls that just match plugs, not items + globalRolls: Roll[]; + // Rolls that are specific to whole categories of items rather than specific items. + categoryRolls: CategoryRoll[]; +} + +/** These tags are meant to match the Little Light JSON wishlist tags. */ +type Tag = + | "PVE" + | "PVP" + | "GodPVE" + | "GodPVP" + | "Mouse" + | "Controller" + // Users are free to specify any other tag + | string; +// A "grade" or "tier" of the roll. The idea is we could let people subscribe to a particular subset of tiers. +type Grade = "s" | "a" | "b" | "c" | "d" | "f"; + +// TODO: should we try to reduce the size of this? +interface Roll { + name?: string; // Not used in DIM + description?: string; // e.g. notes + plugs: number[][]; + // Can be used to filter which rolls to show! + tags?: Tag[]; + // These could also be tags? I like having a defined scale though. + grade?: Grade; + trash?: boolean; // Should this just be grade? +} + +interface ItemRoll extends Roll { + hash: number; +} + +interface CategoryRoll extends Roll { + categories: number[]; +} + +/** + * { + "description": "bar", + "name": "foo", + "data": [ + { + "description": "Bazaar?", + "hash": 602618796, + "name": "Fooo?", + "plugs": [ + [ + 4090651448, + 1467527085, + 1840239774 + ], + [ + 3142289711, + 2420895100 + ], + [ + 2946784966 + ] + ], + "tags": [ + "GodPVE", + "Mouse" + ] + } + ] +} + */ From a6ca4c1e36a4739f6248e84430f9908cafeaab8d Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 29 Jan 2022 18:00:18 -0800 Subject: [PATCH 2/4] Round 2 --- api/shapes/wishlist.ts | 110 +++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/api/shapes/wishlist.ts b/api/shapes/wishlist.ts index 386b97a..8d0dd03 100644 --- a/api/shapes/wishlist.ts +++ b/api/shapes/wishlist.ts @@ -1,29 +1,68 @@ /** Compatible superset of Little Light wishlist format */ +import { DestinyItemSubType } from 'bungie-api-ts/destiny2'; + interface WishList { + /** Indicates that this JSON file is in the format described by this file. */ + format: 'DIMv1'; name: string; description: string; + /** URLs of other wish lists that are transitively included into this wishlist. */ includes: string[]; - // Per-item-hash rolls - data: ItemRoll[]; - // Global rolls that just match plugs, not items - globalRolls: Roll[]; - // Rolls that are specific to whole categories of items rather than specific items. + /** UNIX timestamp (milliseconds) representing when this wish list was created. */ + date?: number; + /** + * Per-item-hash rolls - each one specifies one or more rolls that are + * specific to a particular DestinyInventoryItem. + * E.g. "These are the god rolls for The Messenger" + */ + itemRolls: ItemRoll[]; + /** + * Perk rolls match specific plug combinations, but without specifying an item. + * E.g. "Outlaw + Kill Clip is always good" + */ + perkRolls: Roll[]; + /** + * Rolls that apply to any weapons in a specific category. + * E.g. "Shotguns with Shot Package + Slideshot are always good". + * + * If you specify the intrinsic perk hash, you can also specify things like + * "Adaptive Frame Scout Rifles with Surplus + Demolitionist are good" + */ categoryRolls: CategoryRoll[]; } /** These tags are meant to match the Little Light JSON wishlist tags. */ type Tag = - | "PVE" - | "PVP" - | "GodPVE" - | "GodPVP" - | "Mouse" - | "Controller" + /** This roll is intended for use in PVE */ + | 'PVE' + /** This roll is intended for use in PVP */ + | 'PVP' + /** This roll is specifically good for mouse+keyboard users */ + | 'Mouse' + /** This roll is specifically good for controller users */ + | 'Controller' + /** God Roll - "don't you dare throw this away" - not all guns need to have one of these! */ + | 'Godroll' + /** + * Good Roll - "this is worth keeping/trying" - for guns you would tell + * someone to seek out/grind for. if your review of X gun is "you should go + * get Y gun instead", then X gun doesn't need a Good Roll + */ + | 'Good' + /** + * Perk Recommendation - "if you want this gun, here are the perks you should + * use" - if you're a wishlist maker, you should write some of these for each + * gun + */ + | 'Recommended' + /** + * Trash - this sucks, these perks clash - controversial. makes people very + * sad when they see it, but like the roll + */ + | 'Trash' // Users are free to specify any other tag | string; -// A "grade" or "tier" of the roll. The idea is we could let people subscribe to a particular subset of tiers. -type Grade = "s" | "a" | "b" | "c" | "d" | "f"; // TODO: should we try to reduce the size of this? interface Roll { @@ -32,47 +71,20 @@ interface Roll { plugs: number[][]; // Can be used to filter which rolls to show! tags?: Tag[]; - // These could also be tags? I like having a defined scale though. - grade?: Grade; - trash?: boolean; // Should this just be grade? + /** + * UNIX timestamp (milliseconds) representing when this roll was created or + * updated. If not specified, uses the date from the wishlist it's in. + */ + date?: number; } interface ItemRoll extends Roll { + /** Inventory item hash */ hash: number; } interface CategoryRoll extends Roll { - categories: number[]; -} - -/** - * { - "description": "bar", - "name": "foo", - "data": [ - { - "description": "Bazaar?", - "hash": 602618796, - "name": "Fooo?", - "plugs": [ - [ - 4090651448, - 1467527085, - 1840239774 - ], - [ - 3142289711, - 2420895100 - ], - [ - 2946784966 - ] - ], - "tags": [ - "GodPVE", - "Mouse" - ] - } - ] + categories: DestinyItemSubType[]; + /** Optional intrinsic perk hash, used to narrow this to a specific archetype. */ + intrinsic?: number; } - */ From 91e9e6f395680171464e0c324a7bbfb4d6c63f93 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 25 May 2024 12:46:04 -0700 Subject: [PATCH 3/4] Round 3 --- api/shapes/wishlist.ts | 158 ++++++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 35 deletions(-) diff --git a/api/shapes/wishlist.ts b/api/shapes/wishlist.ts index 8d0dd03..b0b7a9e 100644 --- a/api/shapes/wishlist.ts +++ b/api/shapes/wishlist.ts @@ -2,47 +2,87 @@ import { DestinyItemSubType } from 'bungie-api-ts/destiny2'; -interface WishList { - /** Indicates that this JSON file is in the format described by this file. */ - format: 'DIMv1'; +export type ItemHash = number; + +export interface WishList { + /** + * Indicates that this JSON file is in the format described by this schema. If + * the format is changed in a non-backwards-compatible way this string will be + * changed. It otherwise has no semantic meaning. + */ + format: 'wishlist.v1'; + + /** + * The name of the wish list itself, as a plain string. e.g. "Voltron". + */ name: string; + /** The description of the wish list itself, as a plain string. */ description: string; - /** URLs of other wish lists that are transitively included into this wishlist. */ - includes: string[]; - /** UNIX timestamp (milliseconds) representing when this wish list was created. */ - date?: number; + + /** Information about the author(s) of this wish list. */ + authors?: Author[]; + + /** + * URLs of other wish lists that are transitively included into this wishlist. + * This allows wish lists to be composed of other wish lists, which are then + * fetched individually. A wish list may specify multiple includes, and no + * rolls of its own. + */ + include?: string[]; + + /** + * UNIX timestamp (milliseconds) representing when this wish list was first + * created, for display to humans. + */ + createdTime?: number; + /** + * UNIX timestamp (milliseconds) representing when this wish list was last + * updated, for display to humans. This shouldn't be used to manage cache + * freshness - use HTTP headers for that. + */ + updatedTime?: number; + + /* + * Rolls - these are the various rules that match weapons and perks in order to + make recommendations. Multiple rolls may apply to a single weapon, and all + of them will be shown. The order of rolls is not significant. + */ + /** * Per-item-hash rolls - each one specifies one or more rolls that are - * specific to a particular DestinyInventoryItem. - * E.g. "These are the god rolls for The Messenger" + * specific to a particular DestinyInventoryItem. E.g. "These are the god + * rolls for The Messenger" */ - itemRolls: ItemRoll[]; + itemRolls?: ItemRoll[]; /** - * Perk rolls match specific plug combinations, but without specifying an item. - * E.g. "Outlaw + Kill Clip is always good" + * Perk rolls match specific plug combinations, but without specifying an + * item. E.g. "Outlaw + Kill Clip is always good" */ - perkRolls: Roll[]; + perkRolls?: Roll[]; /** - * Rolls that apply to any weapons in a specific category. - * E.g. "Shotguns with Shot Package + Slideshot are always good". + * Rolls that apply to any weapons in a specific category. E.g. "Shotguns with + * Shot Package + Slideshot are always good". * * If you specify the intrinsic perk hash, you can also specify things like * "Adaptive Frame Scout Rifles with Surplus + Demolitionist are good" */ - categoryRolls: CategoryRoll[]; + categoryRolls?: CategoryRoll[]; } /** These tags are meant to match the Little Light JSON wishlist tags. */ type Tag = /** This roll is intended for use in PVE */ - | 'PVE' + | 'PvE' /** This roll is intended for use in PVP */ - | 'PVP' + | 'PvP' /** This roll is specifically good for mouse+keyboard users */ - | 'Mouse' + | 'MnK' /** This roll is specifically good for controller users */ - | 'Controller' - /** God Roll - "don't you dare throw this away" - not all guns need to have one of these! */ + | 'Ctrl' + /** + * God Roll - "don't you dare throw this away" - not all guns need to have one + * of these! + */ | 'Godroll' /** * Good Roll - "this is worth keeping/trying" - for guns you would tell @@ -57,34 +97,82 @@ type Tag = */ | 'Recommended' /** - * Trash - this sucks, these perks clash - controversial. makes people very - * sad when they see it, but like the roll + * Trash - this sucks, these perks clash - controversial. Makes people very + * sad when they see it, but like the roll. Allowing users to uncheck tags + * when importing wish lists may make using this viable. */ | 'Trash' // Users are free to specify any other tag | string; -// TODO: should we try to reduce the size of this? interface Roll { - name?: string; // Not used in DIM + /** + * An explanation about this roll. Usually contains a general explanation of + * the good and bad parts of this weapon. + */ description?: string; // e.g. notes - plugs: number[][]; - // Can be used to filter which rolls to show! - tags?: Tag[]; /** - * UNIX timestamp (milliseconds) representing when this roll was created or - * updated. If not specified, uses the date from the wishlist it's in. + * Describe a combination of perks, which are really plugs for sockets. + * + * ItemHash is the `DestinyInventoryItem` hash for a socket plug. + * + * Each element in the top-level array represents a "group" of perks, which + * means they belong to the same socket (column) in the perk selection UI. + * + * Masterworks, Weapon Mod, Shader, and other non-Perk plugs *should not* be + * included. + * + * The order of perks group is not specified. Do not include empty groups. + * + * For hash in the same group, their relation is OR. For different groups, + * their relation is AND. (e.g. `[[1, 2], [3, 4]]` means `(1 OR 2) AND (3 OR + * 4)`) + * + * e.g. For `"Randy's Throwing Knife" <3292795429>`, + * - `[[247725512, 2387244414]]` is a valid value meaning "the weapon must + * have plug 247725512 or 2387244414 available on it". + * - Implementers should iterate the groups in `socketEntries`'s `plugSet` + * info to determine the actual socket. (Recommended) + * - `[[247725512], [2387244414]]` is a valid value meaning "the weapon must + * have plug 247725512 and 2387244414 available on it on different sockets". + * + * Implementers must ignore any invalid combination they can't match. + */ + plugs: ItemHash[][]; + + /** + * Tag for the current combination. This can be used to show special flair on + * the item, as a search filter, or to allow users to select which types of + * tags they want to import from a wishlist. + * + * All tags that are not ReservedTags should be treated as user-defined tags. */ - date?: number; + tags?: Tag[]; } interface ItemRoll extends Roll { - /** Inventory item hash */ - hash: number; + /** Inventory item hash this roll applies to. */ + hash: ItemHash; } interface CategoryRoll extends Roll { + /** + * The subtypes of items this roll applies to. This allows targeting rolls to + * "Shotguns" for example. + */ categories: DestinyItemSubType[]; - /** Optional intrinsic perk hash, used to narrow this to a specific archetype. */ - intrinsic?: number; + /** + * Optional intrinsic perk hash, used to narrow this to a specific archetype. + * + * If you specify the intrinsic perk hash, you can also specify things like + * "Adaptive Frame Scout Rifles with Surplus + Demolitionist are good". + */ + intrinsic?: ItemHash; +} + +interface Author { + /** The name of one of the authors of this wish list. */ + name: string; + /** An optional URL to a public profile or home page for the author. */ + url?: string; } From 65b58b5300da8f848ded58874c34f3fa2d3ea7e5 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Sat, 25 May 2024 21:13:46 -0700 Subject: [PATCH 4/4] Add masterwork hashes --- api/shapes/wishlist.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/shapes/wishlist.ts b/api/shapes/wishlist.ts index b0b7a9e..83f1671 100644 --- a/api/shapes/wishlist.ts +++ b/api/shapes/wishlist.ts @@ -3,6 +3,7 @@ import { DestinyItemSubType } from 'bungie-api-ts/destiny2'; export type ItemHash = number; +export type StatHash = number; export interface WishList { /** @@ -140,6 +141,13 @@ interface Roll { */ plugs: ItemHash[][]; + /** + * Optionally, one or more masterwork stats can be chosen which must also be + * present for this roll to match. This is more convenient than having to + * specify 10 plug hashes per masterwork stat. + */ + masterworkStats?: StatHash[]; + /** * Tag for the current combination. This can be used to show special flair on * the item, as a search filter, or to allow users to select which types of