From 0484bdfee3ad2190734263c62f8da953a502b37f Mon Sep 17 00:00:00 2001
From: ferricles
- We use a Base 64 encode/decode system in most shareable links. It would be quite clunky to put a + We use a Base 64 (B64) encode/decode system in most shareable links. It would be quite clunky to put a bunch of numbers (the data we save and read) into one link. To save some space, we compress the - base 10 numerical alphabet into a custom base 64 alphabet. + base 10 numerical alphabet into a custom B64 alphabet.
-- The Wynnbuilder Base 64 character table: + The Wynnbuilder B64 character table:
-
- 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-
-
+ +0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+- +^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ +| | | | | | | | | | | | | +0 5 10 15 20 25 30 35 40 45 50 55 60
- The Base 64 encoding of a number (in the 0 to 63 range) is equal to the character at the index + The B64 encoding of a number (in the 0 to 63 range) is equal to the character at the index within the above string.
For example, if we have a set of items with id numbers in the range [0Kv
:
+ 0Kv
:
, 0
,
K
, and v
.
- Decoding is a little different. We can either interpret the base 64 string as a signed or unsigned number (signed: using 2s complement binary). + Decoding is a little different. We can either interpret the B64 string as a signed or unsigned number (signed: using 2s complement binary).
Things that should be interpreted as signed are: @@ -103,7 +105,7 @@
- Now that we understand the base 64 system, we can move on to the way builds, crafted items, and custom items are stored in links. + Now that we understand the B64 system, we can move on to the way builds, crafted items, and custom items are stored in links.
@@ -124,14 +126,14 @@ similar idea is used for skill points and powders. However, we know how many different skills there are already (5), so we can encode the user's assignment of skill points in 5 numbers. With powders, it's a little different. There are 31 "states" of powder: 1 for no powder and then 5 elements with 6 tiers of powder for each element. We will know how many available powder slots we have based on our - equipment. We can then put all of these numbers in a specific order (after running Base 64 encoding) to get our build link. --> + equipment. We can then put all of these numbers in a specific order (after running B64 encoding) to get our build link. -->
For items, you can download the item DB here: clean.json. Each item has an id value that can be put in a map. The NoneItem ID numbers start at 10000 in the canonical order: [helmet, chestplate, leggings, boots, ring 1, ring 2, bracelet, necklace, weapon] (No Weapon has an id of 10008).
- For tomes, you can download the tome DB here: tome_map.json. The NoneTome ID numbers start at 61 in the order [no weapon tome, no armor tome, no guild tome] so that we can store tome IDs in 1 Base 64 character. + For tomes, you can download the tome DB here: tome_map.json. The NoneTome ID numbers start at 61 in the order [no weapon tome, no armor tome, no guild tome] so that we can store tome IDs in 1 B64 character.
For powders: id numbers
idMap
(idMap
(06W
,
2SH
,
0D4
,
@@ -167,7 +169,7 @@
0Qi
19
,
1V
,
-E
,
@@ -175,20 +177,20 @@
2C
1g
0
s (Base 64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
+ Since there are 4 0
s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
1
(Base 64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
+ Then, we have 1
(B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
00nZ6
in binary is 30 binary bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.
- http://hppeng-wynn.github.io/builder/#5_06W00mCI-10000JCustom%20Chestplate0220510G020Fe0M0201a0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6zz++++-
+ https://hppeng-wynn.github.io/builder/#5_06W00mCI-10000JCustom%20Chestplate0220510G020Fe0M0201a0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6zz++++-
Build Hash format:
idMap
(idMap
(06W
,
- CI-10000JCustom%20Chestplate0220510G020Fe0M0201a
,
+ 00m
(with the custom item CI-10000JCustom%20Chestplate0220510G020Fe0M0201a
),
0D4
,
0Qq
,
2SK
,
@@ -232,13 +234,14 @@
0og
,
0Qi
19
,
1V
,
-E
,
@@ -246,20 +249,20 @@
2C
1g
0
s (Base 64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
+ Since there are 4 0
s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
1
(Base 64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
+ Then, we have 1
(B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
00nZ6
in binary is 30 binary bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.
- http://hppeng-wynn.github.io/builder/#4_06W2SH0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6zz++++-
+ https://hppeng-wynn.github.io/builder/#4_06W2SH0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6zz++++-
Build Hash format:
idMap
(idMap
(06W
,
2SH
,
0D4
,
@@ -300,7 +303,7 @@
0Qi
19
,
1V
,
-E
,
@@ -308,20 +311,20 @@
2C
1g
0
s (Base 64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
+ Since there are 4 0
s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
1
(Base 64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
+ Then, we have 1
(B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
00nZ6
in binary is 30 binary bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.idMap
(idMap
(06W
,
CR-1628i8v8v94948f21
,
0D4
,
@@ -351,12 +354,12 @@
0Qi
19
,
1V
,
-E
,
@@ -364,20 +367,20 @@
2C
1g
0
s (Base 64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
+ Since there are 4 0
s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
1
(Base 64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
+ Then, we have 1
(B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
00nZ6
in binary is 30 binary bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.idMap
(idMap
(06W
,
2SH
,
0D4
,
@@ -415,7 +418,7 @@
0Qi
19
,
1V
,
-E
,
@@ -423,20 +426,20 @@
2C
1g
0
s (Base 64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
+ Since there are 4 0
s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
1
(Base 64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
+ Then, we have 1
(B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
00nZ6
in binary is 30 binary bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.idMap
(idMap
(06W
,
2SH
,
0D4
,
@@ -471,7 +474,7 @@
0Qi
19
,
1V
,
-E
,
@@ -479,16 +482,16 @@
2C
0
s (Base 64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
+ Since there are 4 0
s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
1
(Base 64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
+ Then, we have 1
(B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
00nZ6
in binary is 30 binary bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.idMap
(idMap
(06W
,
2SH
,
0D4
,
@@ -523,16 +526,16 @@
0Qi
0
s (Base 64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
+ Since there are 4 0
s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
1
(Base 64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
+ Then, we have 1
(B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is 00nZ6
.
00nZ6
in binary is 30 binary bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.- For ingredients, you can download the ingredient DB here: ing_map.json. The ID number for No Ingredient is 4000. + For ingredients, you can download the ingredient id map here: ing_map.json. The ID number for No Ingredient is 4000.
- For recipes, you can download the recipe DB here: recipe_map.json. + For recipes, you can download the recipe id map here: recipe_map.json or the recipe DB here: recipes_clean.json.
- This is the first version of crafted item encoding. Crafted Items are always stored in a constant number of base 64 characters. + This is the first version of crafted item encoding. Crafted Items are always stored in a constant number of B64 characters.
@@ -589,7 +592,7 @@
CR-
(always)1
62
,
8i
,
8v
,
@@ -597,25 +600,28 @@
94
,
94
8f
8f
2
1
1
maps to the unsigned integer 1
maps to the unsigned integer - You may need to parse a crafted item from a wynnbuilder link with a crafted item. + You may need to parse a crafted item from a wynnbuilder crafter link.
- http://hppeng-wynn.github.io/crafter/#1628i8v8v94948f21
+ https://hppeng-wynn.github.io/crafter/#1628i8v8v94948f21
We can simply take the string after the octothorpe/hash tag (#), tack on "CR-" in front of this string, and arrive at the full hash for the crafted item in question. Decode using the same logic as the previous example. @@ -632,17 +638,262 @@
Custom items always start with "CI-" so that they are, as an entire category, distinguishable from item pool items. The stats and values that make up the custom item are stored in the rest of the "hash".
-- http://localhost:8000/builder/#5_06W02hCI-10000HMeta%20Chestplate010Gbest%20in%20slot0240401030510G0302SG0H020Fe0I020Fe0J020Fe0K020Fe0L020Fe0M0201Y0i0200U220z0204iKK150200U22160200U22170200U22180200U22190200U220D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6zz++++- -
+This is the first version of custom item encoding and decoding.
+You will need the full array of item identification saving order and all non-rolled identifications (ex: name). View them below.
+ ID saving order: ci_save_order = ["name", "lore", "tier", "set", "slots", "type", "material", "drop", "quest", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq","str", "dex", "int", "agi", "def", "id", "skillpoints", "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "majorIds", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd","durability","duration","charges"];
Non-rolled string IDs: nonRolled_strings = ["name", "lore", "tier", "set", "type", "material", "drop", "quest", "majorIds", "classReq", "atkSpd", "displayName", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "durability", "duration"];
Rolled IDs: rolledIDs = ["hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd"];
Non-rolled IDs: nonRolledIDs = ["name", "lore", "displayName", "tier", "set", "slots", "type", "material", "drop", "quest", "restrict", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq", "str", "dex", "int", "agi", "def", "fixID", "category", "id", "skillpoints", "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "majorIds"];
Tiers: tiers = ["Normal", "Unique", "Rare", "Legendary", "Fabled", "Mythic", "Set", "Crafted"]
Types: types = [ "helmet", "chestplate", "leggings", "boots", "ring", "bracelet", "necklace", "wand", "spear", "bow", "dagger", "relik", "potion", "scroll", "food"];
Attack Speeds: attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"];
Class Requirements: classes = ["Warrior", "Assassin", "Mage", "Archer", "Shaman"]
+ Here's an example of a custom item hash. +
+
+ CI-10000HMeta%20Chestplate010Gbest%20in%20slot0240401030510G0302SG0H020Fe0I020Fe0J020Fe0K020Fe0L020Fe0M0201Y0i0200U220z0204iKK150200U22160200U22170200U22180200U22190200U22
+
+ + Given a custom item hash, we will in general continue to parse through many identifications and their values until we reach the end of the custom item hash. +
++ Custom item hash format: +
+1
0
. (0 for no fixed IDs, 1 for fixed IDs)tier
, type
, atkSpd
, and classReq
, there is no string used. They are encoded as a numerical value representing an index in a pre-defined array (check the Important Arrays section above). They also do not use the earlier-specified 2 characters to store length; instead, they each use only 1 B64 character to store their index in their corresponding arrays.1
0
(non-fixed IDs)000HMeta%20Chestplate
+ 00
("name")0H
(Meta%20Chestplate
("Meta Chestplate")010Gbest%20in%20slot
+ 01
("lore")0G
(best%20in%20slot
("best in slot")024
+ 02
("tier")4
(tiers[4] = "Fabled")040103
+ 04
("slots")01
(0
(positive)3
(051
+ 05
("type")1
(types[1] = "chestplate")0G0302SG
+ 0G
("hp")03
(0
(positive)2SG
(0H020Fe
+ 0H
("fDef")02
(0
(positive)Fe
(0I020Fe
+ 0I
("wDef")02
(0
(positive)Fe
(0J020Fe
+ 0J
("aDef")02
(0
(positive)Fe
(0K020Fe
+ 0K
("tDef")02
(0
(positive)Fe
(0L020Fe
+ 0L
("eDef")02
(0
(positive)Fe
(0M0201Y
+ 0M
("lvl")02
(0
(positive)1Y
(0i0200U22
+ 0i
("hprPct")02
(0
(both positive)0U
(22
(0z0204iKK
+ 0z
("hprRaw")02
(0
(both positive)4i
(KK
(0z0204iKK
+ 0z
("hprRaw")02
(0
(both positive)4i
(KK
(150200U22
+ 15
("fDefPct")02
(0
(both positive)0U
(22
(160200U22
+ 16
("wDefPct")02
(0
(both positive)0U
(22
(170200U22
+ 17
("aDefPct")02
(0
(both positive)0U
(22
(180200U22
+ 18
("tDefPct")02
(0
(both positive)0U
(22
(190200U22
+ 19
("eDefPct")02
(0
(both positive)0U
(22
(+ You may need to parse a custom item from a Wynnbuilder customizer link. +
+
+ hppeng-wynn.github.io/custom/#10000HMeta%20Chestplate010Gbest%20in%20slot0240401030510G0302SG0H020Fe0I020Fe0J020Fe0K020Fe0L020Fe0M0201Y0i0200U220z0204iKK150200U22160200U22170200U22180200U22190200U22
+
+ + Similar to crafted items, the part of the link after the "#" is the rest of the custom item after the "CI-" constant portion. You may need to convert all "%20" to spaces manually. +
++ Details on reading custom items in build links are provided in the Decoding WB links > Builds section. +
+- Last updated: 25 May 2022 + Last updated: 30 May 2022