From c65da33ccd4e20f45a385bfe5665dc4b25f7c846 Mon Sep 17 00:00:00 2001 From: ferricles Date: Thu, 21 Jul 2022 16:24:03 -0700 Subject: [PATCH] sock encoding build.encode started, bitvec append allow appending bitvecs started --- js/build_encode_decode.js | 131 ++++++++++++++++++++++++-------------- js/utils.js | 12 +++- 2 files changed, 94 insertions(+), 49 deletions(-) diff --git a/js/build_encode_decode.js b/js/build_encode_decode.js index a5f88d0..ffb2c7f 100644 --- a/js/build_encode_decode.js +++ b/js/build_encode_decode.js @@ -125,7 +125,7 @@ function decodeBuild(url_tag) { info[1] = res[1]; } // Tomes. - if (version >= 6) { + if (version >= 6 && version < 8) { //tome values do not appear in anything before v6. for (let i in tomes) { let tome_str = info[1].charAt(i); @@ -135,7 +135,7 @@ function decodeBuild(url_tag) { info[1] = info[1].slice(7); } - if (version >= 7) { + if (version == 7) { // ugly af. only works since its the last thing. will be fixed with binary decode atree_data = new BitVector(info[1]); } @@ -155,63 +155,100 @@ function decodeBuild(url_tag) { /* Stores the entire build in a string using B64 encoding and adds it to the URL. */ function encodeBuild(build, powders, skillpoints, atree, atree_state) { - + //currently on version 8 - a unified version for all build types using bit-level encoding if (build) { - let build_string; - - //V6 encoding - Tomes - //V7 encoding - ATree - build_version = 5; - build_string = ""; - tome_string = ""; + //final link will be [build_vers]_[len_string]_[build_string] + build_version = 8; + let len_string = ""; + let build_string = ""; + let build_bits = new BitVector(0, 0); + //ITEMS for (const item of build.items) { - if (item.statMap.get("custom")) { - let custom = "CI-"+encodeCustom(item, true); - build_string += Base64.fromIntN(custom.length, 3) + custom; - build_version = Math.max(build_version, 5); + if (item.statMap.get("NONE") && item.statMap.get("NONE") === true) { + build_bits.append(0, 2); //00 + } else if (item.statMap.get("custom")) { + build_bits.append(3, 2); //11 + //BitVector CI encoding TODO + + // let custom = "CI-"+encodeCustom(item, true); + // build_string += Base64.fromIntN(custom.length, 3) + custom; + // build_version = Math.max(build_version, 5); } else if (item.statMap.get("crafted")) { - build_string += "CR-"+encodeCraft(item); - } else if (item.statMap.get("category") === "tome") { - let tome_id = item.statMap.get("id"); - if (tome_id <= 60) { - // valid normal tome. ID 61-63 is for NONE tomes. - build_version = Math.max(build_version, 6); - } - tome_string += Base64.fromIntN(tome_id, 1); + build_bits.append(2, 2); //10 + //BitVector CR encoding TODO + + // build_string += "CR-"+encodeCraft(item); } else { - build_string += Base64.fromIntN(item.statMap.get("id"), 3); - } - } + if (item.statMap.get("category") === "tome") { + //we will encode tomes later + continue; + } else { + build_bits.append(1, 2); //01 + build_bits.append(item.statMap.get("id"), 13); - for (const skp of skillpoints) { - build_string += Base64.fromIntN(skp, 2); // Maximum skillpoints: 2048 - } - build_string += Base64.fromIntN(build.level, 2); - for (const _powderset of powders) { - let n_bits = Math.ceil(_powderset.length / 6); - build_string += Base64.fromIntN(n_bits, 1); // Hard cap of 378 powders. - // Slice copy. - let powderset = _powderset.slice(); - while (powderset.length != 0) { - let firstSix = powderset.slice(0,6).reverse(); - let powder_hash = 0; - for (const powder of firstSix) { - powder_hash = (powder_hash << 5) + 1 + powder; // LSB will be extracted first. + //powderable + if (powderable_keys.includes(item.statMap.get("type"))) { + if (item.statMap.get("powders") && item.statMap.get("powders").length !== 0) { + //has powders + build_bits.append(1, 1); + + //num of powders in 8 bits, then each powder (6 bits) + //Having more than 256 powders on a vanilla item is NOT HANDLED. + build_bits.append(item.statMap.get("powders").length, 8); + for (const powder of item.statMap.get("powders")) { + build_bits.append(powder, 6); + } + } else { + //no powders + build_bits.append(0, 1); + } + } } - build_string += Base64.fromIntN(powder_hash, 5); - powderset = powderset.slice(6); } } - build_string += tome_string; - if (atree.length > 0 && atree_state.get(atree[0].ability.id).active) { - build_version = Math.max(build_version, 7); - const bitvec = encode_atree(atree, atree_state); - build_string += bitvec.toB64(); + //SKILL POINTS + + //the original schema included a flag to indicate whether or not skill points are included. + //any reason for having a flag isn't implemented yet, so for now every build will have the skill point flag set. + build_bits.append(1, 1); + + for (const skp of build.base_skillpoints) { + build_bits.append(skp, 8); // Maximum skillpoints: 255 (allows for manual assign up to 150) } - return build_version.toString() + "_" + build_string; + //BUILD LEVEL + + // [flag to indicate if level is not 106 (0/1)] + // [else: level (7 bits, allows for lv 1->127)] + if (player_build.level != 106) { + build_bits.append(1, 1); + build_bits.append(player_build.level, 7); + } else { + build_bits.append(0, 1); + } + + // TOMES + + // [flag to indicate if tomes are included (0/1)] + // [if set: 7 sequential tome IDs, each 6 bits unsigned] + + + // ATREE + + // [flag to indicate if atree data is present] + // [atree data: see existing encoding impl] //idk the impl + if (atree.length > 0 && atree_state.get(atree[0].ability.id).active) { + build_bits.append(1, 1); + const atree_bitvec = encode_atree(atree, atree_state); + build_bits.append(atree_bitvec); + } else { + build_bits.append(0, 1); + } + + //compute length and return final build hash + return build_version.toString() + "_" + len_string + "_" + build_string; } } diff --git a/js/utils.js b/js/utils.js index 9bd8090..de6d781 100644 --- a/js/utils.js +++ b/js/utils.js @@ -204,7 +204,7 @@ Base64 = (function () { /** Returns an integer value (if possible) made from the range of bits [start, end). Undefined behavior if the range to read is too big. * - * @param {Number} start - The index to start slicing from. Inclusive. + * @param {Number} start - The index to start slicing from. Inclusive. * @param {Number} end - The index to end slicing at. Exclusive. * * @returns An integer representation of the sliced bits. @@ -307,7 +307,7 @@ Base64 = (function () { /** Appends data to the BitVector. * - * @param {Number | String} data - The data to append. + * @param {Number | String | BitVector} data - The data to append. * @param {Number} length - The length, in bits, of the new data. This is ignored if data is a string. Defaults to 32 for numbers. */ append(data, length = 32) { @@ -318,6 +318,8 @@ Base64 = (function () { //actual new data length is needed for resizing purposes if (typeof data === "string") { length = data.length * 6; + } else if (data instanceof BitVector) { + length = data.length; } let new_length = this.length + length; @@ -369,6 +371,12 @@ Base64 = (function () { if (((this.length - 1) % 32 + 1) + length > 32) { this.bits[curr_idx + 1] = (int >>> (32 - this.length)); } + } else if (data instanceof BitVector) { + //fill to end of curr int of existing bv + + //fill full ints + + //fill from "rest of" length/bv } else { throw new TypeError("BitVector must be appended with a Number or a B64 String"); }