Init commit
This commit is contained in:
parent
2d877cdf07
commit
61c0cf2eb0
24 changed files with 1407 additions and 2 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -5,7 +5,6 @@ target/
|
|||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
@ -18,4 +17,6 @@ Cargo.lock
|
|||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
.idea/
|
||||
|
||||
releases
|
108
Cargo.lock
generated
Normal file
108
Cargo.lock
generated
Normal file
|
@ -0,0 +1,108 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "idlib"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "newestidmangler"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"idlib",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "newestidmangler"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22.1"
|
||||
idlib = { path = "./idlib" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
59
config.md
Normal file
59
config.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
# Values Guide
|
||||
## Name
|
||||
**Name** is stored as a String. It must be a valid Wynncraft item for it to display as intended.
|
||||
## Shiny ID
|
||||
not yet implemented
|
||||
## Powders
|
||||
|
||||
### Powder Limit
|
||||
Powder limit cannot be increased beyond 255. This is because the powder count is stored as a byte.
|
||||
Potential value range: 0<->255.
|
||||
|
||||
### Format
|
||||
Inside the "powders":[ ] array, set it up in the following structure.
|
||||
**{ "type":"$TYPE", "tier":$TIER, "amount": $AMOUNT }**
|
||||
**TYPE** is stored as a single character.
|
||||
Potential Values: "E" "T" "W" "F" "A" . These represent Earth, Thunder, Wind, Fire, Air.
|
||||
**TIER** is stored as a single digit integer.
|
||||
Potential value range: 1<->6.
|
||||
**AMOUNT** is stored as an integer. It is optional. If not provided it falls back to 1.
|
||||
Potential value range: 1<->255.
|
||||
#### Other things about powder format:
|
||||
Each value in the array must have a comma at the end except the last.
|
||||
The use of spaces is optional, as well as letter case for the $TYPE value.
|
||||
The keys ("type" "tier" "amount") must all be lowercase.
|
||||
If type is invalid, it will default back to being Thunder powder.
|
||||
#### Powders Example
|
||||
```js
|
||||
"powders": [
|
||||
{ "type":"T", "tier":6, "amount":5 },
|
||||
{"type":"e","tier":1,"amount":5},
|
||||
{"type":"F", "tier":3,"amount":1},
|
||||
{ "type" : "w" , "tier":6 }
|
||||
],
|
||||
```
|
||||
Note that the last powder block in array has no comma at the end.
|
||||
### Which items can have powders?
|
||||
Powders can only be encoded on an item that originally supported powders in the first place.
|
||||
Unfortunately you can't add powders to an item that didn't originally have them.
|
||||
e.g. can't put powder on depressing shears, as depressing weapons don't have powder slot.
|
||||
|
||||
## Identifications
|
||||
### Format
|
||||
Inside the "ids":[] array, set it up in the following structure.
|
||||
**{"id": "$ID","base": $BASE,"roll": $ROLL}**
|
||||
**ID** is stored as a string corresponding to the Wynntils internal ID string of any roll. See here for a list: https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json .
|
||||
**BASE** is the base roll. The default base data is defined in (WARNING: EXTREMELY MASSIVE TEXT FILE) https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/gear.json .
|
||||
Beautify it then look for `ITEMNAME > base > IDENTIFICATION > raw` for default value. This base value defines the listed ID ranges.
|
||||
**ROLL** defines the actual rolled value for the Identification. The formula is `BASE * ROLL / 100`. Most values are in the range 30-130 due to how Wynncraft handles many Identifications as 30-130 percent of a base stat. Thus, if you are trying to find the ROLL value, try your desired roll **(NOT the roll percentage 1-100)** divided by the BASE then round it to the nearest integer. This value is optional, and you should only exclude it when it is a fixed value e.g. Skill Points.
|
||||
|
||||
## Rerolls
|
||||
Optional single value, i8. Stores number of rerolls. If missing or is 0, rerolls are not encoded.
|
||||
Potential range: 0<->255.
|
||||
|
||||
### Other things about this
|
||||
The format obeys the same json rules as the powders.
|
||||
If you are trying to get the 100% or 0% roll and the value you calculated is close to 130 or 30, change it to 130 or 30 because that is the real value.
|
||||
|
||||
# Current issues
|
||||
Crafteds are not implemented
|
115
id_keys.json
Normal file
115
id_keys.json
Normal file
|
@ -0,0 +1,115 @@
|
|||
{
|
||||
"1stSpellCost": 0,
|
||||
"2ndSpellCost": 1,
|
||||
"3rdSpellCost": 2,
|
||||
"4thSpellCost": 3,
|
||||
"airDamage": 4,
|
||||
"airDefence": 5,
|
||||
"airMainAttackDamage": 6,
|
||||
"airSpellDamage": 7,
|
||||
"damageFromMobs": 8,
|
||||
"earthDamage": 9,
|
||||
"earthDefence": 10,
|
||||
"earthMainAttackDamage": 11,
|
||||
"earthSpellDamage": 12,
|
||||
"elementalDamage": 13,
|
||||
"elementalDefence": 14,
|
||||
"elementalDefense": 15,
|
||||
"elementalSpellDamage": 16,
|
||||
"exploding": 17,
|
||||
"fireDamage": 18,
|
||||
"fireDefence": 19,
|
||||
"fireSpellDamage": 20,
|
||||
"gatherSpeed": 21,
|
||||
"gatherXpBonus": 22,
|
||||
"healingEfficiency": 23,
|
||||
"healthRegen": 24,
|
||||
"healthRegenRaw": 25,
|
||||
"jumpHeight": 26,
|
||||
"knockback": 27,
|
||||
"leveledLootBonus": 28,
|
||||
"leveledXpBonus": 29,
|
||||
"lifeSteal": 30,
|
||||
"lootBonus": 31,
|
||||
"lootQuality": 32,
|
||||
"mainAttackDamage": 33,
|
||||
"manaRegen": 34,
|
||||
"manaSteal": 35,
|
||||
"poison": 36,
|
||||
"raw1stSpellCost": 37,
|
||||
"raw2ndSpellCost": 38,
|
||||
"raw3rdSpellCost": 39,
|
||||
"raw4thSpellCost": 40,
|
||||
"rawAgility": 41,
|
||||
"rawAirDamage": 42,
|
||||
"rawAirMainAttackDamage": 43,
|
||||
"rawAirSpellDamage": 44,
|
||||
"rawAttackSpeed": 45,
|
||||
"rawDefence": 46,
|
||||
"rawDexterity": 47,
|
||||
"rawEarthDamage": 48,
|
||||
"rawEarthSpellDamage": 49,
|
||||
"rawElementalDamage": 50,
|
||||
"rawElementalMainAttackDamage": 51,
|
||||
"rawElementalSpellDamage": 52,
|
||||
"rawFireDamage": 53,
|
||||
"rawFireMainAttackDamage": 54,
|
||||
"rawFireSpellDamage": 55,
|
||||
"rawHealth": 56,
|
||||
"rawIntelligence": 57,
|
||||
"rawMainAttackDamage": 58,
|
||||
"rawNeutralDamage": 59,
|
||||
"rawNeutralSpellDamage": 60,
|
||||
"rawSpellDamage": 61,
|
||||
"rawStrength": 62,
|
||||
"rawThunderDamage": 63,
|
||||
"rawThunderMainAttackDamage": 64,
|
||||
"rawThunderSpellDamage": 65,
|
||||
"rawWaterDamage": 66,
|
||||
"rawWaterMainAttackDamage": 67,
|
||||
"rawWaterSpellDamage": 68,
|
||||
"reflection": 69,
|
||||
"slowEnemy": 70,
|
||||
"soulPointRegen": 71,
|
||||
"spellDamage": 72,
|
||||
"sprint": 73,
|
||||
"sprintRegen": 74,
|
||||
"stealing": 75,
|
||||
"thorns": 76,
|
||||
"thunderDamage": 77,
|
||||
"thunderDefence": 78,
|
||||
"thunderMainAttackDamage": 79,
|
||||
"thunderSpellDamage": 80,
|
||||
"walkSpeed": 81,
|
||||
"waterDamage": 82,
|
||||
"waterDefence": 83,
|
||||
"waterSpellDamage": 84,
|
||||
"weakenEnemy": 85,
|
||||
"xpBonus": 86,
|
||||
"healing": 87,
|
||||
"rawEarthMainAttackDamage": 88,
|
||||
"agility": 89,
|
||||
"baseAirDamage": 90,
|
||||
"baseAirDefence": 91,
|
||||
"baseDamage": 92,
|
||||
"baseEarthDamage": 93,
|
||||
"baseEarthDefence": 94,
|
||||
"baseFireDamage": 95,
|
||||
"baseFireDefence": 96,
|
||||
"baseHealth": 97,
|
||||
"baseThunderDamage": 98,
|
||||
"baseThunderDefence": 99,
|
||||
"baseWaterDamage": 100,
|
||||
"baseWaterDefence": 101,
|
||||
"damage": 102,
|
||||
"defence": 103,
|
||||
"dexterity": 104,
|
||||
"elementalMainAttackDamage": 105,
|
||||
"fireMainAttackDamage": 106,
|
||||
"intelligence": 107,
|
||||
"neutralDamage": 108,
|
||||
"neutralMainAttackDamage": 109,
|
||||
"rawDamage": 110,
|
||||
"rawNeutralMainAttackDamage": 111,
|
||||
"strength": 112
|
||||
}
|
6
idlib/Cargo.toml
Normal file
6
idlib/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "idlib"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
36
idlib/src/data_transformer/enddata.rs
Normal file
36
idlib/src/data_transformer/enddata.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use crate::types::transform::TransformVersion;
|
||||
|
||||
use super::{DataDecoder, DataEncoder, DataTransformerTypes, TransformId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EndData;
|
||||
|
||||
impl TransformId for EndData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::EndDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for EndData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
_ver: TransformVersion,
|
||||
_out: &mut Vec<u8>,
|
||||
) -> Result<(), super::DataTransformError> {
|
||||
// end data is always empty
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Iterator<Item = u8>> DataDecoder<B> for EndData {
|
||||
fn decode_data(
|
||||
_bytes: &mut B,
|
||||
_ver: TransformVersion,
|
||||
) -> Result<Self, super::DataTransformError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
// end data is always empty
|
||||
return Ok(Self);
|
||||
}
|
||||
}
|
175
idlib/src/data_transformer/identdata.rs
Normal file
175
idlib/src/data_transformer/identdata.rs
Normal file
|
@ -0,0 +1,175 @@
|
|||
use crate::{
|
||||
data_transformer::DataTransformError,
|
||||
encoding::{decode_varint, encode_varint},
|
||||
types::{
|
||||
stat::{RollType, Stat, StatId},
|
||||
transform::TransformVersion,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{DataDecoder, DataEncoder, DataTransformerTypes, TransformId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IdentificationData {
|
||||
pub identifications: Vec<Stat>,
|
||||
pub extended_encoding: bool,
|
||||
}
|
||||
|
||||
impl TransformId for IdentificationData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::IdentificationDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for IdentificationData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), super::DataTransformError> {
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
if self.identifications.len() > 255 {
|
||||
return Err(DataTransformError::TooManyIdentifications);
|
||||
}
|
||||
|
||||
let encoded_id_count: u8 = self
|
||||
.identifications
|
||||
.iter()
|
||||
.filter(|id| !id.pre_identified())
|
||||
.count() as u8;
|
||||
|
||||
out.push(encoded_id_count);
|
||||
out.push(self.extended_encoding as u8);
|
||||
|
||||
self.encode_individual_idents(out)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn should_encode_data(&self, ver: TransformVersion) -> bool {
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
if self.extended_encoding {
|
||||
return self.identifications.len() != 0;
|
||||
} else {
|
||||
return self
|
||||
.identifications
|
||||
.iter()
|
||||
.any(|id: &Stat| !id.pre_identified());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IdentificationData {
|
||||
fn encode_individual_idents(&self, bytes: &mut Vec<u8>) -> Result<(), DataTransformError> {
|
||||
// encode the static values if extended encoding is used
|
||||
if self.extended_encoding {
|
||||
let preid_stats: Vec<_> = self
|
||||
.identifications
|
||||
.iter()
|
||||
.filter(|id| id.pre_identified())
|
||||
.collect();
|
||||
|
||||
bytes.push(preid_stats.len() as u8);
|
||||
|
||||
for stat in preid_stats {
|
||||
// first add the id of the ident
|
||||
bytes.push(stat.kind.0);
|
||||
|
||||
// then add the basevalue
|
||||
bytes.append(&mut encode_varint(
|
||||
stat.base.ok_or(DataTransformError::NoBasevalueForIdent)? as i64,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
for ident in self.identifications.iter() {
|
||||
// only handle non preids since preids are encoded using the earlier system
|
||||
if let RollType::Value(roll_val) = ident.roll {
|
||||
// add id of the ident
|
||||
bytes.push(ident.kind.0);
|
||||
|
||||
if self.extended_encoding {
|
||||
// push the baseval
|
||||
bytes.append(&mut encode_varint(
|
||||
ident.base.ok_or(DataTransformError::NoBasevalueForIdent)? as i64,
|
||||
));
|
||||
}
|
||||
|
||||
bytes.push(roll_val);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Iterator<Item = u8>> DataDecoder<B> for IdentificationData {
|
||||
fn decode_data(bytes: &mut B, ver: TransformVersion) -> Result<Self, super::DataTransformError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
let mut idents = Vec::new();
|
||||
|
||||
// first byte is the number of identifications
|
||||
let ident_count = bytes.next().unwrap();
|
||||
|
||||
// second byte is whether or not extended coding is used
|
||||
let extended_encoding = bytes.next().unwrap() == 1;
|
||||
|
||||
let mut preid_count = 0;
|
||||
if extended_encoding {
|
||||
// count of preid idents
|
||||
preid_count = bytes.next().unwrap();
|
||||
}
|
||||
|
||||
for i in 0..(ident_count + preid_count) {
|
||||
// id of the ident
|
||||
let id = bytes.next().unwrap();
|
||||
|
||||
let preid = i < preid_count;
|
||||
|
||||
// decode the possible baseval if using extended coding
|
||||
let baseval = if extended_encoding {
|
||||
Some(decode_varint(bytes) as i32)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// if preid skip decoding the value
|
||||
if preid {
|
||||
idents.push(Stat {
|
||||
kind: StatId(id),
|
||||
base: baseval,
|
||||
roll: RollType::PreIdentified,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
// decode the roll
|
||||
let introll = bytes.next().unwrap();
|
||||
|
||||
idents.push(Stat {
|
||||
kind: StatId(id),
|
||||
base: baseval,
|
||||
roll: RollType::Value(introll),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
identifications: idents,
|
||||
extended_encoding,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
130
idlib/src/data_transformer/mod.rs
Normal file
130
idlib/src/data_transformer/mod.rs
Normal file
|
@ -0,0 +1,130 @@
|
|||
use enddata::EndData;
|
||||
use identdata::IdentificationData;
|
||||
use namedata::NameData;
|
||||
use powderdata::PowderData;
|
||||
use rerolldata::RerollData;
|
||||
use startdata::StartData;
|
||||
use typedata::TypeData;
|
||||
|
||||
use crate::types::transform::TransformVersion;
|
||||
|
||||
pub mod enddata;
|
||||
pub mod identdata;
|
||||
pub mod namedata;
|
||||
pub mod powderdata;
|
||||
pub mod rerolldata;
|
||||
pub mod shinydata;
|
||||
pub mod startdata;
|
||||
pub mod typedata;
|
||||
|
||||
pub trait TransformId {
|
||||
fn get_id() -> u8;
|
||||
}
|
||||
|
||||
pub trait DataEncoder: TransformId {
|
||||
fn encode(&self, ver: TransformVersion, out: &mut Vec<u8>) -> Result<(), DataTransformError> {
|
||||
// skip encoding data which should not be encoded
|
||||
if !self.should_encode_data(ver) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// encode the id
|
||||
out.push(Self::get_id());
|
||||
|
||||
// encode the data
|
||||
self.encode_data(ver, out)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), DataTransformError>;
|
||||
|
||||
fn should_encode_data(&self, _ver: TransformVersion) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DataDecoder<B: Iterator<Item = u8>>: TransformId {
|
||||
fn decode_data(bytes: &mut B, ver: TransformVersion) -> Result<Self, DataTransformError>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub fn decode<B: Iterator<Item = u8>>(bytes: &mut B) -> Result<Vec<AnyData>, DataTransformError> {
|
||||
let mut out = Vec::new();
|
||||
|
||||
// decode the start byte and version
|
||||
let ver = StartData::decode_start_bytes(bytes)?;
|
||||
|
||||
while let Some(id) = bytes.next() {
|
||||
match id {
|
||||
0 => return Err(DataTransformError::StartReparse),
|
||||
1 => out.push(AnyData::TypeData(TypeData::decode_data(bytes, ver)?)),
|
||||
2 => out.push(AnyData::NameData(NameData::decode_data(bytes, ver)?)),
|
||||
3 => out.push(AnyData::IdentificationData(
|
||||
IdentificationData::decode_data(bytes, ver)?,
|
||||
)),
|
||||
// TODO
|
||||
255 => out.push(AnyData::EndData(EndData::decode_data(bytes, ver)?)),
|
||||
_ => return Err(DataTransformError::UnknownTransformer(id)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DataTransformError {
|
||||
NoStartBlock,
|
||||
UnknownVersion(u8),
|
||||
/// Attempt to parse start data. Start data is specially handled.
|
||||
StartReparse,
|
||||
|
||||
InvalidTypeError,
|
||||
|
||||
BadString,
|
||||
|
||||
TooManyIdentifications,
|
||||
NoBasevalueForIdent,
|
||||
NoPotentialValuesForIdent,
|
||||
InvalidIntRoll,
|
||||
|
||||
UnexpectedEndOfBytes,
|
||||
UnknownTransformer(u8),
|
||||
}
|
||||
|
||||
pub enum DataTransformerTypes {
|
||||
StartDataTransformer = 0,
|
||||
TypeDataTransformer = 1,
|
||||
NameDataTransformer = 2,
|
||||
IdentificationDataTransformer = 3,
|
||||
PowderDataTransformer = 4,
|
||||
RerollDataTransformer = 5,
|
||||
ShinyDataTransformer = 6,
|
||||
CustomGearTypeTransformer = 7,
|
||||
DurabilityDataTransformer = 8,
|
||||
RequirementsDataTransformer = 9,
|
||||
DamageDataTransformer = 10,
|
||||
DefenseDataTransformer = 11,
|
||||
CustomIdentificationDataTransformer = 12,
|
||||
CustomConsumableTypeDataTransformer = 13,
|
||||
UsesDataTransformer = 14,
|
||||
EffectsDataTransformer = 15,
|
||||
EndDataTransformer = 255,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AnyData {
|
||||
StartData(StartData),
|
||||
TypeData(TypeData),
|
||||
NameData(NameData),
|
||||
IdentificationData(IdentificationData),
|
||||
PowderData(PowderData),
|
||||
RerollData(RerollData),
|
||||
// TODO
|
||||
EndData(EndData),
|
||||
}
|
54
idlib/src/data_transformer/namedata.rs
Normal file
54
idlib/src/data_transformer/namedata.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use crate::{data_transformer::DataTransformError, types::transform::TransformVersion};
|
||||
|
||||
use super::{DataDecoder, DataEncoder, DataTransformerTypes, TransformId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NameData(pub String);
|
||||
|
||||
impl TransformId for NameData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::NameDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for NameData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), super::DataTransformError> {
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
// check that the string is valid ascii
|
||||
if self.0.chars().any(|c| !c.is_ascii()) {
|
||||
return Err(DataTransformError::BadString);
|
||||
}
|
||||
|
||||
// push the bytes
|
||||
out.extend_from_slice(self.0.as_bytes());
|
||||
// push the null terminator
|
||||
out.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Iterator<Item = u8>> DataDecoder<B> for NameData {
|
||||
fn decode_data(bytes: &mut B, ver: TransformVersion) -> Result<Self, super::DataTransformError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
let b: Vec<u8> = bytes.take_while(|b| *b != 0).collect();
|
||||
|
||||
// UTF-8 and ASCII share the same set of characters
|
||||
Ok(NameData(
|
||||
String::from_utf8(b).map_err(|_| DataTransformError::BadString)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
59
idlib/src/data_transformer/powderdata.rs
Normal file
59
idlib/src/data_transformer/powderdata.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
use crate::types::{powder::Powders, transform::TransformVersion};
|
||||
|
||||
use super::{DataEncoder, DataTransformerTypes, TransformId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PowderData {
|
||||
pub powder_slots: u8,
|
||||
pub powders: Vec<(Powders, u8)>,
|
||||
}
|
||||
|
||||
impl TransformId for PowderData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::PowderDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for PowderData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), super::DataTransformError> {
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
let bits_needed = self.powders.len() * 5;
|
||||
let total_bits = (bits_needed + 7) / 8;
|
||||
|
||||
let mut powder_data = vec![0u8; total_bits];
|
||||
|
||||
for (i, pow) in self.powders.iter().enumerate() {
|
||||
let elem = pow.0 as u8;
|
||||
// TODO: figure out if wynntils fixes this and make the tier be encoded correctly
|
||||
let tier = 0; //pow.1;
|
||||
|
||||
// calculate the 5 bit powder value
|
||||
let powder_num = (elem * 6 + tier) & 0b00011111;
|
||||
|
||||
// bit position where this specific powder starts
|
||||
let powder_idx = i * 5;
|
||||
|
||||
// set the values
|
||||
for j in 0..5 {
|
||||
// calculate the bit position of this bit
|
||||
let idx = powder_idx + j;
|
||||
let bit = (powder_num >> (4 - j)) & 0b1;
|
||||
powder_data[idx / 8] |= bit << (7 - (idx % 8));
|
||||
}
|
||||
}
|
||||
|
||||
out.push(self.powder_slots);
|
||||
out.push(self.powders.len() as u8);
|
||||
|
||||
out.append(&mut powder_data);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
41
idlib/src/data_transformer/rerolldata.rs
Normal file
41
idlib/src/data_transformer/rerolldata.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use crate::types::transform::TransformVersion;
|
||||
|
||||
use super::{DataDecoder, DataEncoder, DataTransformError, DataTransformerTypes, TransformId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RerollData(pub u8);
|
||||
|
||||
impl TransformId for RerollData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::RerollDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for RerollData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: crate::types::transform::TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), super::DataTransformError> {
|
||||
match ver {
|
||||
TransformVersion::Version1 => out.push(self.0),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Iterator<Item = u8>> DataDecoder<B> for RerollData {
|
||||
fn decode_data(bytes: &mut B, ver: TransformVersion) -> Result<Self, super::DataTransformError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match ver {
|
||||
TransformVersion::Version1 => Ok(Self(
|
||||
bytes
|
||||
.next()
|
||||
.ok_or(DataTransformError::UnexpectedEndOfBytes)?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
31
idlib/src/data_transformer/shinydata.rs
Normal file
31
idlib/src/data_transformer/shinydata.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use crate::{encoding::encode_varint, types::transform::TransformVersion};
|
||||
|
||||
use super::{DataEncoder, DataTransformerTypes, TransformId};
|
||||
|
||||
pub struct ShinyData {
|
||||
pub id: u8,
|
||||
pub val: i64,
|
||||
}
|
||||
|
||||
impl TransformId for ShinyData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::ShinyDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for ShinyData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: crate::types::transform::TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), super::DataTransformError> {
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
out.push(self.id);
|
||||
out.append(&mut encode_varint(self.val));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
42
idlib/src/data_transformer/startdata.rs
Normal file
42
idlib/src/data_transformer/startdata.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use crate::types::transform::TransformVersion;
|
||||
|
||||
use super::{DataEncoder, DataTransformError, DataTransformerTypes, TransformId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StartData(pub TransformVersion);
|
||||
|
||||
impl TransformId for StartData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::StartDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for StartData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), DataTransformError> {
|
||||
match ver {
|
||||
TransformVersion::Version1 => out.push(self.0.version()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl StartData {
|
||||
/// Special case function for parsing the start bytes
|
||||
pub(crate) fn decode_start_bytes<B: Iterator<Item = u8>>(
|
||||
bytes: &mut B,
|
||||
) -> Result<TransformVersion, DataTransformError> {
|
||||
let idbyte = bytes.next().unwrap();
|
||||
if idbyte != DataTransformerTypes::StartDataTransformer as u8 {
|
||||
return Err(DataTransformError::NoStartBlock);
|
||||
}
|
||||
|
||||
let verbyte = bytes.next().unwrap();
|
||||
|
||||
TransformVersion::from_u8(verbyte).map_err(|_| DataTransformError::UnknownVersion(verbyte))
|
||||
}
|
||||
}
|
43
idlib/src/data_transformer/typedata.rs
Normal file
43
idlib/src/data_transformer/typedata.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use crate::types::{itemtype::ItemType, transform::TransformVersion};
|
||||
|
||||
use super::{DataDecoder, DataEncoder, DataTransformError, DataTransformerTypes, TransformId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeData(pub ItemType);
|
||||
|
||||
impl TransformId for TypeData {
|
||||
fn get_id() -> u8 {
|
||||
DataTransformerTypes::TypeDataTransformer as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DataEncoder for TypeData {
|
||||
fn encode_data(
|
||||
&self,
|
||||
ver: TransformVersion,
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), super::DataTransformError> {
|
||||
match ver {
|
||||
TransformVersion::Version1 => out.push(self.0.into()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Iterator<Item = u8>> DataDecoder<B> for TypeData {
|
||||
fn decode_data(bytes: &mut B, ver: TransformVersion) -> Result<Self, super::DataTransformError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match ver {
|
||||
TransformVersion::Version1 => {
|
||||
let b = bytes.next().unwrap();
|
||||
|
||||
Ok(Self(
|
||||
ItemType::try_from(b).map_err(|_| DataTransformError::InvalidTypeError)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
112
idlib/src/encoding.rs
Normal file
112
idlib/src/encoding.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
/// Encode bytes into a string using the wynntils byte encoding scheme
|
||||
///
|
||||
/// https://github.com/Wynntils/Wynntils/blob/main/common/src/main/java/com/wynntils/utils/EncodedByteBuffer.java#L87
|
||||
pub fn encode_string(data: &[u8]) -> String {
|
||||
let mut out = String::new();
|
||||
|
||||
for d in data.chunks(2) {
|
||||
if d.len() == 2 {
|
||||
if d[0] == 255 && d[1] >= 254 {
|
||||
out.push(char::from_u32(0x100000 + ((d[1] - 254) as u32)).unwrap());
|
||||
} else {
|
||||
out.push(char::from_u32(0xF0000 + ((d[0] as u32) << 8) + d[1] as u32).unwrap());
|
||||
}
|
||||
} else {
|
||||
// encode leftover singular bits with the seperate encoding
|
||||
out.push(char::from_u32(0x100000 + ((d[0] as u32) << 8) + 0xEE).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
/// Decodes the bytes of a wynntils private area encoded string
|
||||
///
|
||||
/// This function does not check whether or not the encoded data is valid
|
||||
///
|
||||
/// https://github.com/Wynntils/Wynntils/blob/main/common/src/main/java/com/wynntils/utils/EncodedByteBuffer.java#L33
|
||||
pub fn decode_string(data: &str) -> Vec<u8> {
|
||||
let mut out = Vec::new();
|
||||
|
||||
for c in data.chars() {
|
||||
let n: u32 = c.into();
|
||||
|
||||
// special case Private use area B
|
||||
if n > 0x100000 {
|
||||
// single byte
|
||||
if n & 0xFF == 0xEE {
|
||||
out.push(((n & 0xFF00) >> 8) as u8);
|
||||
|
||||
assert!(((n & 0xFF00) >> 8) <= 255, "Invalid codepoint: {n:06X}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// two bytes
|
||||
|
||||
out.push(255);
|
||||
out.push((254 + (n & 0xFF)) as u8);
|
||||
|
||||
// Only 0x100000-0x100001 are used
|
||||
assert!(n < 0x100002, "Invalid codepoint: {n:06X}");
|
||||
continue;
|
||||
}
|
||||
|
||||
out.push(((n & 0xFF00) >> 8) as u8);
|
||||
out.push((n & 0x00FF) as u8);
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
pub fn encode_varint(value: i64) -> Vec<u8> {
|
||||
// zigzag encoding magic
|
||||
// removes sign bit so values are only positive
|
||||
let value = ((value << 1) ^ (value >> 63)) as u64;
|
||||
|
||||
// 7 bits per byte
|
||||
// highest bit is used to indicate end of encoding
|
||||
|
||||
// calulate number of bytes needed
|
||||
let mut numofbytes = 1;
|
||||
let mut temp = value >> 7;
|
||||
while temp != 0 {
|
||||
// println!("{temp}");
|
||||
numofbytes += 1;
|
||||
temp >>= 7;
|
||||
}
|
||||
|
||||
let mut outbytes = Vec::new();
|
||||
for i in 0..numofbytes {
|
||||
let mut next = (value >> (7 * i)) as u8 & 0x7F;
|
||||
|
||||
// indicate that we are **not** done by setting the highest bit
|
||||
if i < numofbytes - 1 {
|
||||
next |= 0b10000000;
|
||||
}
|
||||
|
||||
outbytes.push(next);
|
||||
}
|
||||
|
||||
outbytes
|
||||
}
|
||||
|
||||
pub fn decode_varint<B: Iterator<Item = u8>>(bytes: &mut B) -> i64 {
|
||||
let mut value = 0;
|
||||
|
||||
let mut data = Vec::new();
|
||||
loop {
|
||||
let b = bytes.next().unwrap();
|
||||
|
||||
data.push(b);
|
||||
|
||||
if (b & 0b10000000) == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i, n) in data.into_iter().enumerate() {
|
||||
value |= ((n & 0b01111111) as i64) << (7 * i);
|
||||
}
|
||||
|
||||
return (value >> 1) ^ -(value & 1);
|
||||
}
|
3
idlib/src/lib.rs
Normal file
3
idlib/src/lib.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod data_transformer;
|
||||
pub mod encoding;
|
||||
pub mod types;
|
31
idlib/src/types/itemtype.rs
Normal file
31
idlib/src/types/itemtype.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ItemType {
|
||||
Gear = 0,
|
||||
Tome = 1,
|
||||
Charm = 2,
|
||||
CraftedGear = 3,
|
||||
CraftedConsu = 4,
|
||||
}
|
||||
|
||||
impl Into<u8> for ItemType {
|
||||
fn into(self) -> u8 {
|
||||
self as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for ItemType {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
0 => Ok(Self::Gear),
|
||||
1 => Ok(Self::Tome),
|
||||
2 => Ok(Self::Charm),
|
||||
3 => Ok(Self::CraftedGear),
|
||||
4 => Ok(Self::CraftedConsu),
|
||||
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
4
idlib/src/types/mod.rs
Normal file
4
idlib/src/types/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
pub mod itemtype;
|
||||
pub mod powder;
|
||||
pub mod stat;
|
||||
pub mod transform;
|
9
idlib/src/types/powder.rs
Normal file
9
idlib/src/types/powder.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
/// Powder types
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum Powders {
|
||||
EARTH = 1,
|
||||
THUNDER = 2,
|
||||
WATER = 3,
|
||||
FIRE = 4,
|
||||
AIR = 5,
|
||||
}
|
24
idlib/src/types/stat.rs
Normal file
24
idlib/src/types/stat.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
#[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)]
|
||||
pub struct StatId(pub u8);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Stat {
|
||||
pub kind: StatId,
|
||||
pub base: Option<i32>,
|
||||
pub roll: RollType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RollType {
|
||||
Value(u8),
|
||||
PreIdentified,
|
||||
}
|
||||
|
||||
impl Stat {
|
||||
pub fn pre_identified(&self) -> bool {
|
||||
match self.roll {
|
||||
RollType::Value(_) => false,
|
||||
RollType::PreIdentified => true,
|
||||
}
|
||||
}
|
||||
}
|
17
idlib/src/types/transform.rs
Normal file
17
idlib/src/types/transform.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TransformVersion {
|
||||
Version1 = 0,
|
||||
}
|
||||
|
||||
impl TransformVersion {
|
||||
pub fn version(&self) -> u8 {
|
||||
*self as u8
|
||||
}
|
||||
|
||||
pub fn from_u8(byte: u8) -> Result<Self, ()> {
|
||||
match byte {
|
||||
0 => Ok(Self::Version1),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
269
src/main.rs
Normal file
269
src/main.rs
Normal file
|
@ -0,0 +1,269 @@
|
|||
use idlib::{
|
||||
data_transformer::{
|
||||
decode, enddata::EndData, identdata::IdentificationData, namedata::NameData,
|
||||
powderdata::PowderData, rerolldata::RerollData, shinydata::ShinyData, startdata::StartData,
|
||||
typedata::TypeData, DataEncoder,
|
||||
},
|
||||
encoding::{decode_string, encode_string},
|
||||
types::{
|
||||
itemtype::ItemType,
|
||||
powder::Powders,
|
||||
stat::{RollType, Stat, StatId},
|
||||
transform::TransformVersion,
|
||||
},
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::panic;
|
||||
use std::env;
|
||||
use serde_json;
|
||||
use serde::Deserialize;
|
||||
use base64::engine::{general_purpose, Engine};
|
||||
|
||||
// structs
|
||||
#[derive(Deserialize)]
|
||||
struct Powder {
|
||||
r#type: char,
|
||||
tier: u8,
|
||||
amount: Option<u8>
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct Identificationer {
|
||||
id: String,
|
||||
base: i32,
|
||||
roll: Option<u8>
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct jsonconfig {
|
||||
name: String,
|
||||
ids: Vec<Identificationer>,
|
||||
powder_limit: u8,
|
||||
powders: Vec<Powder>,
|
||||
rerolls:Option<u8>
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// enable fancypanic when building for release
|
||||
fancypanic();
|
||||
|
||||
// newest json reading code
|
||||
let json_config: jsonconfig = serde_json::from_reader(
|
||||
fs::File::open("values.json").expect(ERROR[1]))
|
||||
.expect(ERROR[2]);
|
||||
let idsmap: HashMap<String, u8> = serde_json::from_reader(fs::File::open("id_keys.json").expect(ERROR[3]))
|
||||
.expect(ERROR[4]);
|
||||
// println!("{:?}",idsmap.get("airDamage"));
|
||||
// below is no longer needed as ive merged it
|
||||
//let imported2: jsoned = serde_json::from_reader(importedjson)
|
||||
// .expect("this json sucks");
|
||||
|
||||
// read the file and stuff
|
||||
// thanks to https://stackoverflow.com/a/52964674
|
||||
// obselete do not use
|
||||
//let file = fs::File::open("values.json")
|
||||
// .expect("where file?");
|
||||
//let thejson: serde_json::Value = serde_json::from_reader(file)
|
||||
// .expect("where proper json format?");
|
||||
//let powders = thejson.get("powders").expect("e").get("a");
|
||||
//let powders2 = serde_json::json!(powders);
|
||||
//println!("powders: {:?}",powders);
|
||||
//println!("powders2: {}",powders2);
|
||||
//println!("name is {}", thejson);
|
||||
|
||||
// let fuy = thejson.get("a");
|
||||
// println!("{:#?}",fuy);
|
||||
|
||||
|
||||
|
||||
let mut out = Vec::new();
|
||||
let ver = TransformVersion::Version1;
|
||||
|
||||
StartData(ver).encode(ver, &mut out).unwrap();
|
||||
|
||||
TypeData(ItemType::Gear).encode(ver, &mut out).unwrap();
|
||||
|
||||
NameData(String::from(format!("{}", json_config.name.trim()) ))
|
||||
.encode(ver, &mut out)
|
||||
.unwrap();
|
||||
|
||||
let w1 = "aWRtYW5nbGVyLXJld3JpdGUgUHJlLVJlbGVhc2UgdjE=";
|
||||
let w2 = "KEMpIFpBVFpPVSBhbmQgRU5ERVJOT04gMjAyNA==";
|
||||
|
||||
let l1 = String::from_utf8(general_purpose::STANDARD.decode(w1).unwrap()).unwrap();
|
||||
let l2 = String::from_utf8(general_purpose::STANDARD.decode(w2).unwrap()).unwrap();
|
||||
println!("{l1}");
|
||||
println!("{l2}");
|
||||
|
||||
// json identification data handling
|
||||
let mut idvec = Vec::new();
|
||||
for eachid in json_config.ids {
|
||||
let id_id = idsmap.get(eachid.id.trim());
|
||||
let id_base = eachid.base as i32;
|
||||
let id_roll = eachid.roll;
|
||||
|
||||
idvec.push(
|
||||
(
|
||||
Stat {
|
||||
kind: StatId(match id_id {
|
||||
Some(ide) => *ide,
|
||||
None => panic!("There is a mismatched ID, and this message has replaced where the line is meant to be")
|
||||
}),
|
||||
base: Some(id_base),
|
||||
roll: match id_roll{
|
||||
Some(rolle) => RollType::Value(rolle),
|
||||
None => RollType::PreIdentified
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// println!("{:?} {:?} {:?}",id_id,id_base,id_roll)
|
||||
}
|
||||
|
||||
IdentificationData {
|
||||
identifications: idvec,
|
||||
extended_encoding: true,
|
||||
}
|
||||
.encode(ver, &mut out)
|
||||
.unwrap();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// json powder data handling
|
||||
let mut powdervec = Vec::new();
|
||||
for eachpowder in json_config.powders {
|
||||
let powdertier = eachpowder.tier; // get the powder tier
|
||||
let powderamount:u8 = match eachpowder.amount { // get amount of powder if exists, otherwise 1
|
||||
Some(amount) => {
|
||||
amount
|
||||
},// good,
|
||||
None => {
|
||||
1
|
||||
}// bad,
|
||||
};
|
||||
// match for the powder type
|
||||
// no need to return to variable or i'll need to rematch AGAIN
|
||||
match eachpowder.r#type {
|
||||
'E' | 'e' => {
|
||||
for i in 0..powderamount {
|
||||
powdervec.push((Powders::EARTH,powdertier))
|
||||
}
|
||||
},
|
||||
'T' | 't' => {
|
||||
for i in 0..powderamount {
|
||||
powdervec.push((Powders::THUNDER,powdertier))
|
||||
}
|
||||
},
|
||||
'W' | 'w' => {
|
||||
for i in 0..powderamount {
|
||||
powdervec.push((Powders::WATER,powdertier))
|
||||
}
|
||||
},
|
||||
'F' | 'f' => {
|
||||
for i in 0..powderamount {
|
||||
powdervec.push((Powders::FIRE,powdertier))
|
||||
}
|
||||
},
|
||||
'A' | 'a' => {
|
||||
for i in 0..powderamount {
|
||||
powdervec.push((Powders::AIR,powdertier))
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
for i in 0..powderamount {
|
||||
powdervec.push((Powders::THUNDER,powdertier))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// println!("tier {}",powdertier);
|
||||
// println!("amount {}",powderamount);
|
||||
}
|
||||
// println!("{:?}",powdervec);
|
||||
|
||||
|
||||
|
||||
|
||||
// old powder data encode kinda, takes data from new encode
|
||||
PowderData {
|
||||
powder_slots: json_config.powder_limit,
|
||||
powders: powdervec,
|
||||
}
|
||||
.encode(ver, &mut out)
|
||||
.unwrap();
|
||||
|
||||
|
||||
match json_config.rerolls {
|
||||
Some(i) => {
|
||||
if i != 0 {
|
||||
RerollData(i).encode(ver, &mut out).unwrap();
|
||||
}
|
||||
},
|
||||
None => pass()
|
||||
}
|
||||
|
||||
|
||||
|
||||
ShinyData {
|
||||
id: 2,
|
||||
val: i64::MAX as i64, //- 0b0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000,
|
||||
// u16::MAX is the max value of unsigned 16bit value
|
||||
}
|
||||
.encode(ver, &mut out)
|
||||
.unwrap();
|
||||
|
||||
|
||||
// prints (Water,6) 255 times
|
||||
// println!("{:?}",vec![(Powders::WATER, 6); 255]);
|
||||
|
||||
EndData.encode(ver, &mut out).unwrap();
|
||||
|
||||
|
||||
|
||||
// final string print
|
||||
println!("{}", encode_string(&out));
|
||||
|
||||
// I don't even know what the fuck this does
|
||||
//for b in out {
|
||||
// print!("{:02X}", b);
|
||||
//}
|
||||
|
||||
// println!();
|
||||
|
||||
// decode test
|
||||
let input = "";
|
||||
let bytes = decode_string(&input);
|
||||
let mut bytes_iter = bytes.into_iter();
|
||||
|
||||
let out = decode(&mut bytes_iter).unwrap();
|
||||
|
||||
// println!("{:#?}", out);
|
||||
}
|
||||
|
||||
|
||||
fn fancypanic() {
|
||||
panic::set_hook(Box::new(|panic_info| {
|
||||
let panic_msg = format!("{panic_info}");
|
||||
println!("{}", panic_msg.lines().skip(1).next().unwrap_or("HOW DID YOU BREAK THE PANIC HANDLER???"));
|
||||
}));
|
||||
}
|
||||
|
||||
fn pass() {
|
||||
|
||||
}
|
||||
|
||||
const ERROR: [&'static str; 5] = [
|
||||
"Error 0: what did you even do to get this? ",
|
||||
"Error 1: json config file is missing, reobtain it from the values.json I have sent you. ",
|
||||
"Error 2: json config is broken. Reread the example data or reobtain it from the values.json I have sent you. ",
|
||||
"Error 3: Identifications hashmap not found. Get it from https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json and move it to this directory.",
|
||||
"Error 4: Identifications hashhmap is corrupt. Reobtain it from https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json and move it to this directory."
|
||||
];
|
||||
const _BOIL: [&'static str; 3] = [
|
||||
"0",
|
||||
"reobtain it from the values.json I have sent you. ",
|
||||
"Get it from https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json and move it to this directory."
|
||||
];
|
26
values.json
Normal file
26
values.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"READMEFIRST": [
|
||||
"Refer to config.md to understand how to apply the data shown here.",
|
||||
"There are also some values you cannot increase beyond a limit."
|
||||
],
|
||||
"name":"Singularity",
|
||||
|
||||
"ids": [
|
||||
{"id": "mainAttackDamage","base": 320,"roll": 69},
|
||||
{"id": "healthRegenRaw", "base":250 , "roll":130 },
|
||||
{"id": "rawDexterity", "base":35 },
|
||||
{"id": "walkSpeed", "base":-40 , "roll":69},
|
||||
{"id": "mainAttackDamage", "base":15, "roll":130 },
|
||||
{"id": "rawMainAttackDamage", "base":444 , "roll":130 },
|
||||
{"id": "rawSpellDamage", "base":222 , "roll":130 },
|
||||
{"id": "spellDamage", "base":10 , "roll":130 }
|
||||
],
|
||||
"powder_limit": 255,
|
||||
"powders": [
|
||||
{ "type":"T", "tier":6, "amount":5 },
|
||||
{"type":"e","tier":6,"amount":5},
|
||||
{"type":"f", "tier":6,"amount":1},
|
||||
{ "type" : "f" , "tier":6 }
|
||||
],
|
||||
"rerolls": 0
|
||||
}
|
Loading…
Reference in a new issue