sock encoding build.encode started, bitvec append allow appending bitvecs started

This commit is contained in:
ferricles 2022-07-21 16:24:03 -07:00
parent 99d2b8273a
commit c65da33ccd
2 changed files with 94 additions and 49 deletions

View file

@ -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;
}
}

View file

@ -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");
}