Compare commits

..

110 commits
v0.4.0 ... main

Author SHA1 Message Date
44ab8f1f9c use actual match statement with actually clear comments and all that 2025-01-11 01:16:58 +00:00
2490c77bbb ACTUAL fmt fix 2025-01-11 00:58:36 +00:00
9066e96a7c cargo fmt 2025-01-11 00:45:41 +00:00
385a0af747 disable the fn definition param newliner for cargo fmt 2025-01-11 00:44:50 +00:00
3d00b8306a Move all encode functions into an impl for FuncParams 2025-01-11 00:43:10 +00:00
bde76d6548 test 2025-01-11 00:31:44 +00:00
3b11775582 fix unused Return value 2025-01-11 00:22:49 +00:00
fb2a5e8c02 Add return Result<(),Errorfr> for everything just for the sake of future proofing 2025-01-11 00:20:37 +00:00
281ff67005 update idmangler lib ver 2025-01-08 00:30:15 +00:00
69d0964b9b remove shiny stats from the repo (idk why it was committed tbh) 2025-01-07 23:00:32 +00:00
6f706c62bd assim tome 2025-01-05 23:29:55 +00:00
55e5242f6f NameAfter support 2025-01-04 01:02:27 +00:00
d98f24812d make everything & 2025-01-04 00:49:55 +00:00
cd3261c9b4 i screwed up borrowing fr 2025-01-04 00:43:35 +00:00
ef9aa2d8cb fix error message capitalisation to be easier for laymen 2025-01-03 23:25:51 +00:00
e11c54cae5 cargo fmt 2025-01-03 23:24:47 +00:00
e90124c4df fix the early return 2025-01-03 23:23:19 +00:00
e6fe118201 fix a debug check 2025-01-03 23:03:09 +00:00
f21aaee514 add a lot of debug prints 2025-01-03 22:57:47 +00:00
9c2771ad1f remove unused imports from the ide 2025-01-03 22:40:04 +00:00
910658cf4c fr 2025-01-03 22:39:24 +00:00
7615c17b60 CraftedGear and CraftedConsu RequirementData (2/2) 2025-01-03 20:14:12 +00:00
02b5cabcb9 reqdata part 1 2025-01-03 16:04:40 +00:00
4a3ee91d9b squash question mark 2025-01-03 15:12:56 +00:00
e2b188c982 clippy autofix 2025-01-03 15:12:26 +00:00
658b9b758e clippy stuff 2025-01-03 15:12:14 +00:00
e5455fddd8 implement DurabilityData 2025-01-02 20:25:59 +00:00
5c17f1c21e change encode function names to be consistent 2025-01-02 18:34:23 +00:00
655cbda1c9 proper error handling for CraftedType. Also, more matches 2025-01-02 18:22:09 +00:00
e3278243c0 crafted types gaming 2025-01-02 17:51:13 +00:00
a29295d878 shenanigans 2025-01-02 13:48:36 +00:00
9459b6adb9 cargo fmt 2025-01-02 12:25:49 +00:00
bc063bae6e redivision 2025-01-02 12:24:55 +00:00
e066263704 format everything into a bunch of seperate files 2025-01-02 12:23:03 +00:00
85eb199939 fmt 2025-01-02 12:13:26 +00:00
f4cdf669cf fmt stuff 2025-01-02 12:10:28 +00:00
f678b418a8 make the thing not print if there is an error 2025-01-02 12:08:39 +00:00
1cf1701579 dont print the string if err 2025-01-02 12:07:47 +00:00
6313b56064 make NAME field non-optional for Gear, Tome, Charm 2025-01-02 12:06:52 +00:00
84e696bea2 remove Tier from example configs Powders arrays 2025-01-01 21:00:59 +00:00
4fcba6b7be bump version to 0.4.3 2025-01-01 20:52:35 +00:00
4324f68f65 wrong way round, its allow not deny 2025-01-01 20:52:00 +00:00
062cc18be1 disable Single Match lint from clippy 2025-01-01 20:51:23 +00:00
d7793c200a fixing clippy stuff 2025-01-01 20:49:16 +00:00
f6a78a95a5 cargo fmt 2025-01-01 20:47:16 +00:00
ead3d77f0c remove unused cargo.toml deps 2025-01-01 20:47:08 +00:00
c030081f6b update docs for Item Type, because it now actually supports gear, tome, charm items 2025-01-01 20:38:44 +00:00
3bc00f3389 remove missing Powder Limit warning 2025-01-01 20:32:27 +00:00
700f40fba7 add in type checks for existing blocks 2025-01-01 20:20:27 +00:00
a2c6317474 remove some line breaks 2025-01-01 19:55:57 +00:00
0a06bc80e4 make each modular encode function use one general struct of {out, debug_mode, ver} 2025-01-01 18:23:26 +00:00
13e4eb76a9 modular mode hellyeah 2025-01-01 18:07:46 +00:00
366f5b5a64 move stuff to ENCODE functions 2025-01-01 17:36:27 +00:00
321a5b302f make powder vec happen as seperate function 2025-01-01 16:16:18 +00:00
a8b3b63a0a remove powder tier, because wynntils literally doesn't use anything but t6 2025-01-01 14:35:39 +00:00
aca07977b0 update thiserror dependency to v2 2025-01-01 14:32:20 +00:00
9aba8d2bc1 remove powder limit from examples 2025-01-01 14:23:38 +00:00
2fe769e08d remove powderlimit from docs 2025-01-01 14:23:04 +00:00
9835e9f9d2 powder limit is min of 255 and current powders amount 2025-01-01 14:22:10 +00:00
b4f61b9eb1 remove powderlimit field entirely and make it automatically find based on num of powders (it's useless anyway) 2025-01-01 14:21:10 +00:00
501bacc7f3 make all the ACTUALLY non essential blocks Optional. Also powder limit is necessary if you have powders 2025-01-01 13:40:58 +00:00
6c50e01549 update build script for x64, to remove config.md 2025-01-01 00:10:05 +00:00
22983ae8e0 bumpity bump bump 2025-01-01 00:05:25 +00:00
5667364165 bump version yep 2025-01-01 00:05:11 +00:00
33c4d64b92 fucking clippy man 2025-01-01 00:04:30 +00:00
8d46acb705 remove comments. also cargo fmt 2025-01-01 00:03:23 +00:00
ebeb57b3fa fix the issue with displaying the json borked issue 2024-12-31 23:58:11 +00:00
8d5341f3e2 add json5 support (first function is broken??? 2024-12-31 23:43:20 +00:00
0403ecb8ce add examples and all that 2024-12-31 23:36:30 +00:00
1933cb1d12 add all the unlisted item types into the general config doc, but disclaimer NOT IMPLEMENTED YET 2024-12-31 21:21:20 +00:00
468a6d29f1 finish doc migration 2024-12-31 21:14:07 +00:00
f6d9feacec docs bigger refactor 2024-12-31 17:27:56 +00:00
fa9a50b60e cargo fmt 2024-12-31 16:27:33 +00:00
41610c51ca fix clippy stuff 2024-12-31 16:27:21 +00:00
db78cdaf30 reformatting fr 2024-12-31 16:20:13 +00:00
5e55c04d22 docs bigger update 2024-12-31 15:54:45 +00:00
88092f1456 some refactoring 2024-12-31 15:40:33 +00:00
522a92f864 docs update 2024-12-31 15:39:55 +00:00
c5a30d0d46 remove debug print 2024-12-31 15:08:08 +00:00
78b6e9ddcc better method of loading files, because this is necessary for implementing other item types 2024-12-31 00:06:08 +00:00
7cd826a735 video guide for windows user 2024-12-29 21:54:05 +00:00
a7506faef8 unindent 3rd section of USAGE in readme 2024-12-29 20:23:33 +00:00
95223cbbda update the hanafubuki to add item_type field (i forgot) 2024-12-29 20:15:40 +00:00
6180a5009b update readme to tell people to chmod the linux binary 2024-12-29 20:06:21 +00:00
d5927ae125 update build script 2024-12-29 20:05:30 +00:00
2f581abe65 make config path optional yep 2024-12-29 19:59:39 +00:00
415677b41f readme update 2024-12-29 19:57:40 +00:00
e39660db44 bump version in cargo.lock i think 2024-12-29 19:38:21 +00:00
d4058321b3 Bump version for update 2024-12-29 19:30:10 +00:00
deb174f338 fix a bug where its looking for ShinyStats.json instead of shiny_stats.json (blame clion refactoring) 2024-12-29 19:28:50 +00:00
041dc62684 fix the shiny stats json detection 2024-12-29 15:30:36 +00:00
33df7335e3 Revert "test global vars (this is pain)"
This reverts commit 73e0a94cc2.
2024-12-25 14:45:15 +00:00
73e0a94cc2 test global vars (this is pain) 2024-12-25 14:44:52 +00:00
6efad16944 cargo clippy --fix 2024-12-25 00:32:37 +00:00
a6e56b4519 a 2024-12-25 00:32:15 +00:00
5dd7966761 fixed every linter warning 2024-12-25 00:30:38 +00:00
e2868aed8c remove fancypanic as its redundant now. 2024-12-25 00:24:09 +00:00
66fd2ce14e added multiline errors 2024-12-25 00:23:05 +00:00
515c0d4c60 set the help message to appear if no args sent 2024-12-25 00:15:12 +00:00
142c548057 download jsons function for ease of use 2024-12-24 23:37:50 +00:00
5cdfcfeca2 crafted support (1/?) (unfinished) 2024-12-24 18:49:30 +00:00
a2b82ccf22 bit of cleaning up 2024-12-23 23:17:30 +00:00
3220d21e73 add crafted bool for crafted support 2024-12-23 22:56:04 +00:00
a204a37843 make it so it looks for config jsons in the executable dir, NOT the working dir 2024-12-23 22:55:15 +00:00
2ee0b85b69 add license and description lines to the cargo.toml 2024-12-23 19:36:04 +00:00
a9d28aecc3 publish for crates.io 2024-12-23 19:35:11 +00:00
b2744bb6f7 rename debugmode parameter to debug and remove the now redundant dbg!(powderamount) 2024-11-06 17:25:57 +00:00
f2cb7ab9c7 fix borrow errors using dbg! 2024-11-06 17:23:44 +00:00
7a6af25bc2 change debug print location for powder adding and element 2024-11-06 17:21:49 +00:00
fc4e92ed34 use dbg! for debug prints 2024-11-06 17:20:39 +00:00
38 changed files with 3393 additions and 960 deletions

1557
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,16 @@
[package] [package]
name = "idmangler-cli" name = "idmangler-cli"
version = "0.4.0" authors = ["endernon"]
version = "0.4.3"
edition = "2021" edition = "2021"
readme = "README.md"
license = "MIT"
description = "A cli tool to generate fake wynntils items"
[dependencies] [dependencies]
base64 = "0.22.1"
clap = { version = "4.5.20", features = ["derive"] } clap = { version = "4.5.20", features = ["derive"] }
idmangler-lib = "0.4.0" idmangler-lib = { version = "0.5.0", features = ["serde"] }
reqwest = { version = "0.12.9", features = ["blocking", "json"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json5 = "0.1.0"
thiserror = "1.0.68" thiserror = "2.0.9"

View file

@ -4,6 +4,6 @@ Copyright (c) 2024 endernon
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in All copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,7 +1,7 @@
# idmangler-cli # idmangler-cli
Basically this generates fake items by loading from a json. Effectively a wrapper for [zatzou's idmangler-lib](https://github.com/Zatzou/idmangler-lib). Basically this generates fake items by loading from a json. Effectively a wrapper for [zatzou's idmangler-lib](https://github.com/Zatzou/idmangler-lib).
Any bugs? DM endernon on discord. A video guide for Windows users can be found [HERE](https://www.youtube.com/watch?v=AvEUhs_6rEc).
## How to get the program ## How to get the program
@ -9,16 +9,39 @@ Any bugs? DM endernon on discord.
Go to the [releases tab](https://git.frfrnocap.men/endernon/idmangler-cli/releases) Go to the [releases tab](https://git.frfrnocap.men/endernon/idmangler-cli/releases)
### Option 2: compile yourself ### Option 2: compile yourself
requirements: rust, cargo requirements: rust, cargo
use cargo run --release to build and run. use `cargo run --release` to build and run.
### Option 3: get from crates.io
Requirements: rust-lang
run `cargo install idmangler-cli`.
## Usage ## Usage
### 1) Setting up
- #### 1a) Linux:
- Open your preferred terminal emulator, and make sure the working directory is the directory with idmangler-cli extracted inside.
- Otherwise, if it's the wrong directory, run `cd PATH_TO_IDMANGLER_CLI_DIR` where `PATH_TO_IDMANGLER_CLI_DIR` is where idmangler-cli is stored.
- Run `chmod +x idmangler-cli` because by default it doesn't have executable permissions.
- #### 1b) Windows:
- Open the folder where idmangler-cli is extracted to in Windows File Explorer.
- Then, click the empty space in the top bar (it shows the path e.g. "This PC > Downloads") and type `cmd` and press enter.
- This should open a Command Prompt.
- At the start of the line displayed, it should say the path to the folder where File Explorer is open (e.g. "This PC > Downloads").
### 2) Getting necessary information files / Updating the necessary information files
- These files are from wynntils, and are data files necessary to the operation of the program.
- There are two methods of getting these information files.
- #### 1) Automatic download
- Windows: run `idmangler-cli.exe --download all`
- Linux: run `idmangler-cli --download all`
- #### 2) Manual download
- Move the program to some folder along with config.json . Download these three files and place them next to the program: - Move the program to some folder along with config.json . Download these three files and place them next to the program:
- https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json - https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json
- https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json - https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json
### 3) Actually generating an item
- Open a terminal (Windows: use cmd or Powershell , Linux: use your preferred Terminal Emulator) - Read through the provided `config.md` document. You can get the web version [HERE](docs/config.md).
- Use the command "cd DIRECTORY" (where DIRECTORY is where the program is stored) - Once you have read through it, use one of the provided json files to create your own json.
- read the provided config markdown file to understand how to edit config.json - Run the program with it.
- Windows: run `idmangler-cli.exe --config CONFIG_FILE_PATH`
- Linux: run `idmangler-cli --config CONFIG_FILE_PATH`
- Where CONFIG_FILE_PATH is the actual path to the file.
- Now, what happens is there should be an output line that has the encoded file.
- Copy the whole line and paste it into minecraft chat or whatever.

View file

@ -3,18 +3,18 @@ cargo build --target x86_64-pc-windows-gnu --package idmangler-cli --bin idmangl
mkdir -p product mkdir -p product
cp ./target/x86_64-pc-windows-gnu/release/idmangler-cli.exe ./product/idmangler-cli-windows-x64.exe cp ./target/x86_64-pc-windows-gnu/release/idmangler-cli.exe ./product/idmangler-cli.exe
cp ./target/x86_64-unknown-linux-gnu/release/idmangler-cli ./product/idmangler-cli-linux-x64 cp ./target/x86_64-unknown-linux-gnu/release/idmangler-cli ./product/idmangler-cli
cp -u -p ./{config.json,config_hanafupookie.json,config_singu.json,config.md} ./product/ cp -u -p ./{config.json,config_hanafupookie.json,config_singu.json} ./product/
pkgversion=$(cargo metadata --format-version=1 --no-deps | jq '.packages[] | select(.name == "idmangler-cli") | .version') pkgversion=$(cargo metadata --format-version=1 --no-deps | jq '.packages[] | select(.name == "idmangler-cli") | .version')
echo "package version is:" echo "package version is:"
echo $pkgversion echo "$pkgversion"
balls=${pkgversion::-1} balls=${pkgversion::-1}
balls2=${balls:1} balls2=${balls:1}
echo $balls2 echo "$balls2"
cd product cd product
zip "idmangler-windows-x64-${balls2}.zip" config.json config_hanafupookie.json config_singu.json config.md idmangler-cli-windows-x64.exe zip "idmangler-windows-x64-${balls2}.zip" config.json config_hanafupookie.json config_singu.json idmangler-cli.exe
zip "idmangler-linux-x64-${balls2}.zip" config.json config_hanafupookie.json config_singu.json config.md idmangler-cli-linux-x64 zip "idmangler-linux-x64-${balls2}.zip" config.json config_hanafupookie.json config_singu.json idmangler-cli

View file

@ -4,6 +4,7 @@
"There are also some values you cannot increase beyond a limit." "There are also some values you cannot increase beyond a limit."
], ],
"name":"Singularity", "name":"Singularity",
"item_type": "Gear",
"shiny": { "shiny": {
"key": "playersKilled", "key": "playersKilled",
"value": 9223372036854775807 "value": 9223372036854775807
@ -18,263 +19,262 @@
{"id": "rawSpellDamage", "base":222 , "roll":130 }, {"id": "rawSpellDamage", "base":222 , "roll":130 },
{"id": "spellDamage", "base":10 , "roll":130 } {"id": "spellDamage", "base":10 , "roll":130 }
], ],
"powder_limit": 255,
"powders": [ "powders": [
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6} {"type":"A"}
], ],
"rerolls": 255 "rerolls": 255

View file

@ -1,62 +0,0 @@
# Values Guide
## Name
**Name** is stored as a String. It must be a valid Wynncraft item for it to display as intended.
## Shiny ID
Inside the Shiny{} list, there will be two elements: "key" and "value".
The potential keys for any shiny value are listed here: https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json
The value is the shown amount.
## 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 > identifications > IDENTIFICATIONNAME > 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.
However, if the value is negative it will be between 70%-130%.
# Current issues
Crafteds are not implemented

277
config_crafted.json Normal file
View file

@ -0,0 +1,277 @@
{
"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",
"item_type": "craftedgear",
"crafted_type": "spear",
"requirements": {
"level": 69,
"class": "Mage"
},
"durability": {
"effect_strength": 100,
"dura_cur": 50,
"dura_max": 100
},
"powders": [
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"},
{"type":"E"},
{"type":"T"},
{"type":"W"},
{"type":"F"},
{"type":"A"}
],
"rerolls": 255
}

View file

@ -4,6 +4,7 @@
"There are also some values you cannot increase beyond a limit." "There are also some values you cannot increase beyond a limit."
], ],
"name":"Hanafubuki", "name":"Hanafubuki",
"item_type": "Gear",
"shiny": { "shiny": {
"key": "playersKilled", "key": "playersKilled",
"value": 9223372036854775807 "value": 9223372036854775807
@ -16,7 +17,6 @@
{"id": "jumpHeight", "base":3, "roll":130 }, {"id": "jumpHeight", "base":3, "roll":130 },
{"id": "rawStrength", "base":15} {"id": "rawStrength", "base":15}
], ],
"powder_limit": 255,
"powders": [ "powders": [

17
config_medallion.json Normal file
View file

@ -0,0 +1,17 @@
{
"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":"Outlandish Replica Face Mask of Legendary Victory",
"item_type": "Gear",
"shiny": {
"key": "MobsKilled",
"value": 9223372036854775807
},
"ids": [
],
"powders": [
],
"rerolls": 255
}

View file

@ -4,6 +4,7 @@
"There are also some values you cannot increase beyond a limit." "There are also some values you cannot increase beyond a limit."
], ],
"name":"Singularity", "name":"Singularity",
"item_type": "Gear",
"shiny": { "shiny": {
"key": "playersKilled", "key": "playersKilled",
"value": 9223372036854775807 "value": 9223372036854775807
@ -18,263 +19,262 @@
{"id": "rawSpellDamage", "base":222 , "roll":130 }, {"id": "rawSpellDamage", "base":222 , "roll":130 },
{"id": "spellDamage", "base":10 , "roll":130 } {"id": "spellDamage", "base":10 , "roll":130 }
], ],
"powder_limit": 255,
"powders": [ "powders": [
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6}, {"type":"A"},
{"type":"E", "tier":6}, {"type":"E"},
{"type":"T", "tier":6}, {"type":"T"},
{"type":"W", "tier":6}, {"type":"W"},
{"type":"F", "tier":6}, {"type":"F"},
{"type":"A", "tier":6} {"type":"A"}
], ],
"rerolls": 255 "rerolls": 255

9
config_tome.json Normal file
View file

@ -0,0 +1,9 @@
{
"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":"Assimilator's Tome of Allegiance",
"item_type": "tome",
"rerolls": 255
}

View file

View file

0
docs/blocks/damage.md Normal file
View file

0
docs/blocks/defense.md Normal file
View file

View file

0
docs/blocks/effects.md Normal file
View file

View file

@ -0,0 +1,44 @@
# Identifications
- This data block encodes for identifications on Gear-type items.
- Not to be confused with [Custom Identifications](identificationscustom.md).
- Field name: `ids`
- Field type: `Array[id, base, roll]`
- Example: `"id":"1stSpellCost","base":69,"roll":30`
- # Id
- This is the ID that is used. It corresponds to the Wynntils internal name for an identification.
- See [HERE](https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json) for a list.
- Field name: `id`
- Field type: `String`
- Example: `"id":"1stSpellCost"`
- # Base
- This is the base value. This value defines the range for 0% to 100% of any stat on any item.
- It is defined for any item in [THIS](https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/gear.json) data file. Use a json beautifier, then look for `ITEMNAME > identifications > IDENTIFICATION_NAME > raw` for the base value.
- Field name: `base`
- Field type: `Signed 32-bit Integer`
- Field range: `2147483648` to `2147483647`
- Example: `"base":69`
- # Roll (OPTIONAL)
- This is the roll value. It defines the actual roll percent for the identification.
- The formula for the final shown percentage on the final item is `BASE * ROLL / 100`.
- Positive values are in the range 30-130 due to how Wynncraft handles many Identifications as `(0.3 <-> 1.3) x baseStat`.
- If you are trying to find the ROLL value, try your desired roll VALUE **(NOT the roll percentage)** divided by the BASE STAT then round it to the nearest integer.
- This value is optional, BUT you should only exclude it when it is a fixed value and not a range, e.g. Skill Points are always fixed.
- Field name: `roll`
- Field type: `Unsigned 8-bit Integer`
- Field range: `0` to `255`
- ...But for it to be a valid item, `30` to `130` (positive base stat) and `70` to `130` (negative base stat).
- Example: `"roll":30`
## Example Identifications for a perfect Singularity:
```json
"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 }
],
```

View file

8
docs/blocks/name.md Normal file
View file

@ -0,0 +1,8 @@
# Name
This data block encodes for the name of an item.
- Field name: `name`
- Field type: `String`
- Example: `"name":"Singularity"`
- **NOTES FOR GEAR TYPE ITEMS**:
- It must be a valid Wynncraft item name for it to display as intended.
- in game, the name has a limit of 48 characters. That means that the final tier Legendary Island item, "Outlandish Replica Face Mask of Legendary Victory", only encodes up to "Victor". Thus, it does not work in game. ![frfr.png](../images/outlandish_mask.png)

0
docs/blocks/nameafter.md Normal file
View file

41
docs/blocks/powders.md Normal file
View file

@ -0,0 +1,41 @@
# Powders
- This data block encodes for powders present on the item.
- Field name: `powders`
- Field type: `Array[type, tier, amount]`
- Field range: `0` to `255` powders total.
- ## Type
- This is the type of powder that is present.
- These values represent Earth, Thunder, Water, Fire, and Air.
- Field name: `type`
- Field type: `Char`
- Field potential values: `E`,`T`,`W`,`F`,`A`
- Field fallback value (if invalid): `T`
- Example: `"type":"E"`
- ## Tier
- This is the powder tier, although it really doesn't do anything as by default Wynntils only encodes to and accepts Tier 6.
- Field name: `tier`
- Field type: `Unsigned 8-bit Integer`
- Field range: `1` to `6`
- Example: `"tier":6`
- ## Amount (OPTIONAL)
- For each entry in the `powders` array, this is the amount of powders encoded.
- It is optional, as it's just used to make encoding lots of the same powder easier.
- For example, you could repeat `{"type":"E", "tier":6}` six times, or just do `{"type":"E", "tier":6, "amount":6}` and both would be the same.
- Field name: `amount`
- Field type: `Unsigned 8-bit Integer`
- Field range: `1` to `255`
- Field fallback value (if not provided): `1`
- Example: `"amount":6`
## EXAMPLE of the Powders array
```
"powders": [
{"type":"T", "tier":6, "amount":5},
{"type":"e", "tier":1, "amount":5},
{"type":"F", "tier":3, "amount":1},
{"type":"w", "tier":6}
]
```
## 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.

View file

6
docs/blocks/reroll.md Normal file
View file

@ -0,0 +1,6 @@
## Rerolls (OPTIONAL)
- This data block encodes the number of rerolls.
- Field name: `rerolls`
- Field type: `Unsigned 8-bit Integer`
- Field range: `0` to `255`
- Example: `"rerolls":"125"`

17
docs/blocks/shiny.md Normal file
View file

@ -0,0 +1,17 @@
# Shiny
This data block encodes for Shiny data present on gear items.
- Field name: `shiny`
- Field type: `{key, value}`
- Example: `"shiny": {"key": "playersKilled","value": 20}`
- ## Key
- This is the type of the shiny stat present.
- The potential keys for any shiny value are listed [HERE](https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json).
- Field name: `key`
- Field type: `String`
- Example: `"key": "playersKilled"`
- ## Value
- This is the value of the shiny stat present.
- Field name: `value`
- Field type: `Signed 64-bit Integer`
- Field range: `-9,223,372,036,854,775,808` to `9,223,372,036,854,775,807`
- Example: `"value":"20"`

8
docs/blocks/type.md Normal file
View file

@ -0,0 +1,8 @@
# Item type
- This data block encodes for the type of the item that's being encoded.
- This will support crafteds in the future, but for now it only supports non crafted types.
- If you input a crafted value, literally nothing will happen, I think.
- Field name: `item_type`
- Field type: `String`
- Field potential values: `"Gear"`, `"Tome"`, `"Charm"`
- Example: `"item_type": "Gear"`

43
docs/config.md Normal file
View file

@ -0,0 +1,43 @@
# Config Guide
## The required blocks
According to the [Wynntils Artemis encoding proposal Github Issue](https://github.com/Wynntils/Wynntils/issues/2246),
the allowed blocks should look like this:
![An image of the original encoding proposal table, present on GitHub](images/encodingproposaltable.png)
However, it's inaccurate. This is what it SHOULD look like:
##### Key to Type Mapping Table
| Key | Type | Required blocks | Optional blocks |
|-----|--------------------------|--------------------------------------------|-------------------------------------------------------------|
| `0` | Gear Item | Name | Identifications, Powders, Shiny, Reroll |
| `1` | Tome Item | Name | Identifications, Reroll |
| `2` | Charm Item | Name | Identifications, Reroll |
| `3` | Crafted Gear Item | Custom Gear Type, Durability, Requirements | NameAfter, Damage, Defense, Custom Identifications, Powders |
| `4` | Crafted Consumable Item | Custom Consumable Type, Uses, Requirements | Effects, NameAfter, Custom Identifications |
| `5` | Crafted Item from Recipe | TODO | TODO |
## Documentation for each block:
- [Item type](blocks/type.md)
- [Custom Gear Type (NOT IMPLEMENTED YET)](blocks/customgeartype.md)
- [Custom Consumable Type (NOT IMPLEMENTED YET)](blocks/customconsumtype.md)
- [Durability (NOT IMPLEMENTED YET)](blocks/durability.md)
- [Requirements (NOT IMPLEMENTED YET)](blocks/requirements.md)
- [Name](blocks/name.md)
- [NameAfter (NOT IMPLEMENTED YET)](blocks/nameafter.md)
- [Shiny](blocks/shiny.md)
- [Identifications](blocks/identifications.md)
- [Damage (NOT IMPLEMENTED YET)](blocks/damage.md)
- [Defense (NOT IMPLEMENTED YET)](blocks/defense.md)
- [Effects (NOT IMPLEMENTED YET)](blocks/effects.md)
- [Powders](blocks/powders.md)
- [Custom Identifications (NOT IMPLEMENTED YET)](blocks/identifications.md)
- [Reroll](blocks/reroll.md)
# Current issues
Crafteds are not implemented

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

1
rustfmt.toml Normal file
View file

@ -0,0 +1 @@
fn_params_layout = "Compressed"

290
src/encode.rs Normal file
View file

@ -0,0 +1,290 @@
use crate::errorfr::Errorfr;
use crate::jsonstruct::{
CraftedTypesFr, Durability, FuncParams, Identificationer, ItemTypeDeser, PowderFr,
RequirementsDeser, Shinyjson, Shinystruct,
};
use idmangler_lib::encoding::DataEncoder;
use idmangler_lib::{
block::{
CraftedConsumableTypeData, CraftedGearTypeData, DurabilityData, EndData,
IdentificationData, NameData, PowderData, RequirementsData, RerollData, ShinyData,
StartData, TypeData,
},
types::{ClassType, Element, ItemType, Powder, RollType, SkillType, Stat},
};
use std::collections::HashMap;
impl FuncParams<'_> {
pub fn encode_startdata(&mut self) -> Result<(), Errorfr> {
if *self.fr_debug_mode {
println!("Encoding StartData")
}
// ENCODE: StartData
StartData(self.fr_ver)
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_typedata(&mut self, item_type_deser: ItemTypeDeser) -> Result<(), Errorfr> {
if *self.fr_debug_mode {
println!("Encoding TypeData: {:?}", item_type_deser);
}
// ENCODE: TypeData
TypeData(ItemType::from(item_type_deser))
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_typedata_custom(&mut self, crafted_type: &str) -> Result<(), Errorfr> {
let frfr_type = CraftedTypesFr::try_from(crafted_type)?;
match frfr_type {
CraftedTypesFr::Gear(a) => {
if *self.fr_debug_mode {
println!("Encoding CustomTypeData: Gear");
}
CraftedGearTypeData(a)
.encode(self.fr_ver, self.fr_out)
.unwrap()
}
CraftedTypesFr::Consu(a) => {
if *self.fr_debug_mode {
println!("Encoding CustomTypeData: Consumable");
}
CraftedConsumableTypeData(a)
.encode(self.fr_ver, self.fr_out)
.unwrap()
}
}
Ok(())
}
pub fn encode_duradata(&mut self, real_dura: &Durability) -> Result<(), Errorfr> {
let effect_strength_fr: u8; // but actually it should be 0 to 100, not 0 to 255. But i dunno how to use u7 data type.
if let Some(effstr) = real_dura.effect_strength {
if *self.fr_debug_mode {
println!("Encoding DurabilityData: Defined");
}
effect_strength_fr = effstr
} else {
let current_percentage = real_dura.dura_cur / real_dura.dura_max; // percentage of max durability
// see this answer from Stackoverflow for transcribing range
// https://stackoverflow.com/a/929107
match current_percentage {
50..=100 => {
// dura more than or equal to 50%
// dura less than 100%
// effectiveness 100%
effect_strength_fr = 100
},
10..50 => {
// dura more than or equal to 10%
// dura less than 50%
// effectiveness scales from 100% to 50%
// old range is 50-10 = 40
let old_range = 40;
// new range is 100-50 = 50
let new_range = 50;
// NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
effect_strength_fr =
((((current_percentage - 10) * new_range) / old_range) + 50) as u8
},
0..10 => {
// dura more than or equal to 0%
// dura less than 10%
// effectiveness scales from 50% to 10%
// old range is 10-0 = 10
let old_range = 10;
// new range is 50-10 = 40
let new_range = 40;
// NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
effect_strength_fr = ((((current_percentage) * new_range) / old_range) + 10) as u8
},
_ => return Err(Errorfr::JsonDuraOutOfRange) // only get this if current durability is <0 or >100
}
}
if *self.fr_debug_mode {
println!(
"Encoding DurabilityData.effect_strenght: {}",
effect_strength_fr
);
println!("Encoding DurabilityData.current: {}", real_dura.dura_cur);
println!("Encoding DurabilityData.current: {}", real_dura.dura_max);
}
DurabilityData {
effect_strenght: effect_strength_fr,
current: real_dura.dura_cur,
max: real_dura.dura_max,
}
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_reqdata(&mut self, real_reqdata: RequirementsDeser) -> Result<(), Errorfr> {
if *self.fr_debug_mode {
println!(
"Encoding RequirementData.Level: {:?}",
real_reqdata.level.clone()
)
}
let mut fr_class: Option<ClassType> = None;
if let Some(actualclass) = real_reqdata.class {
fr_class = Some(ClassType::from(actualclass));
if *self.fr_debug_mode {
println!("Encoding RequirementData.Class: {:?}", actualclass.clone())
}
} else if *self.fr_debug_mode {
println!("Encoding RequirementData.Class: Undefined");
}
let spvec: Vec<(SkillType, i32)> = match real_reqdata.sp {
Some(real_sp) => Vec::<(SkillType, i32)>::from(real_sp),
None => Vec::new(),
};
if *self.fr_debug_mode {
println!("Encoding RequirementData.Skills: {:?}", spvec.clone())
}
RequirementsData {
level: real_reqdata.level,
class: fr_class,
skills: spvec,
}
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_namedata(&mut self, real_name: &str) -> Result<(), Errorfr> {
// ENCODE: NameData
if *self.fr_debug_mode {
println!("Encoding NameData: {:?}", &real_name)
}
NameData(real_name.trim().to_string())
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_iddata(
&mut self, real_ids: &Vec<Identificationer>, idsmap: HashMap<String, u8>,
) -> Result<(), Errorfr> {
let mut idvec = Vec::new();
for eachid in real_ids {
let id_id = idsmap.get(eachid.id.trim());
let id_base = eachid.base;
let id_roll = eachid.roll;
idvec.push(
Stat {
kind: match id_id {
Some(ide) => *ide,
None => std::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)
}
if *self.fr_debug_mode {
println!("Encoding IdentificationData: {:?}", &idvec)
}
// ENCODE: IdentificationsData
IdentificationData {
identifications: idvec,
extended_encoding: true,
}
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_powderdata(&mut self, real_powders: &Vec<PowderFr>) -> Result<(), Errorfr> {
let mut powdervec = Vec::new();
for eachpowder in real_powders {
let powderamount: u8 = eachpowder.amount.unwrap_or(1);
// match for the powder type
for _ in 0..powderamount {
let eletype = match eachpowder.r#type.to_ascii_lowercase() {
'e' => Element::Earth,
't' => Element::Thunder,
'w' => Element::Water,
'f' => Element::Fire,
'a' => Element::Air,
_ => return Err(Errorfr::JsonUnknownPowderElement),
};
if *self.fr_debug_mode {
dbg!(eletype);
}
powdervec
.push(Powder::new(eletype, 6).map_err(|_| Errorfr::JsonUnknownPowderTier)?);
// 6 is the tier. Wynntils ONLY really uses tier 6 so theres no point keeping others.
}
}
if *self.fr_debug_mode {
dbg!(&powdervec);
}
let powderlimitfr: u8 = powdervec.len() as u8; // min of the current number of powders and 255 (if you have over 255 powders stuff breaks)
// ENCODE: PowderData
// only occurs if the powders array is present and the powder limit is also present
//
PowderData {
powder_slots: powderlimitfr,
powders: powdervec,
}
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_rerolldata(&mut self, rerollcount: u8) -> Result<(), Errorfr> {
if rerollcount != 0 {
// ENCODE: RerollData if applicable
RerollData(rerollcount)
.encode(self.fr_ver, self.fr_out)
.unwrap();
if *self.fr_debug_mode {
dbg!(rerollcount);
}
}
Ok(())
}
pub fn encode_shinydata(
&mut self, shiny: &Shinyjson, json_shiny: &Vec<Shinystruct>,
) -> Result<(), Errorfr> {
let mut realshinykey: u8;
let _shinykey = &shiny.key;
let shinyvalue = shiny.value;
realshinykey = 1;
for i in json_shiny {
if i.key == shiny.key {
realshinykey = i.id;
if *self.fr_debug_mode {
dbg!(&shiny.key);
}
}
}
if *self.fr_debug_mode {
dbg!(&realshinykey);
dbg!(&shinyvalue);
}
// ENCODE: ShinyData (if applicable)
ShinyData {
id: realshinykey,
val: shinyvalue,
}
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
pub fn encode_enddata(&mut self) -> Result<(), Errorfr> {
if *self.fr_debug_mode {
println!("Encoding EndData")
}
// ENCODE: EndData
EndData.encode(self.fr_ver, self.fr_out).unwrap();
Ok(())
}
}

81
src/errorfr.rs Normal file
View file

@ -0,0 +1,81 @@
use thiserror::Error;
/// Errors yep
#[derive(Error, Debug)]
pub enum Errorfr {
/// item config json is missing
#[error("Error 1.1: item config json is missing.")]
ItemJsonMissing,
/// item config json is corrupt
#[error("Error 1.2: item config json is invalid. \nReread config.md.\n{0}")]
ItemJsonCorrupt(serde_json5::Error),
/// idmap is missing
#[error("Error 1.3: id_keys.json is missing. \nYou should run \"--download id_keys\" or \"--download All\".")]
IDMapJsonMissing,
/// idmap is corrupt
#[error("Error 2.1: id_keys.json is corrupt. \nYou should run \"--download id_keys\" or \"--download All\".")]
IDMapJsonCorrupt,
/// shiny data json is missing
#[error("Error 2.2: shiny_stats.json is missing. \nYou should run \"--download ShinyStats\" or \"--download All\".")]
ShinyJsonMissing,
/// shiny data json is corrupt
#[error("Error 2.3: shiny_stats.json is corrupt. \nYou should run \"--download ShinyStats\" or \"--download All\".")]
ShinyJsonCorrupt,
/// could not download the file
#[error("Error 3.1: Download request failed. Check your network settings.")]
JsonDlReqFail,
/// invalid body response after downloading
#[error("Error 3.2: Download body is invalid. Something is broken.")]
JsonDlReqBodyInvalid,
/// unable to create file after download
#[error("Error 3.3: Download successful, but unable to actually create the file.")]
JsonDlReqFileCreateFail,
/// unable to copy (write in) file content
#[error("Error 3.4: Download successful, but unable to write to file.")]
JsonDlReqFileWriteFail,
/// Name value was not found in json
#[error(
"Error 4.1: \"name\" field was not found in the json (required for Gear, Tome, Charm)."
)]
JsonNotFoundName,
/// unable to find the crafted_type field
#[error("Error 4.2: Missing \"crafted_type\" field")]
JsonNotFoundCraftedType,
/// invalid crafted_type field
#[error("Error 4.3: Invalid \"crafted_type\" value")]
JsonInvalidCraftedType,
/// Durability is out of allowed range (0 to 100)
#[error("Error 4.4: \"durability\" percentage is out of range (Should be between 0 and 100)")]
JsonDuraOutOfRange,
/// Durability was not found but is necessary
#[error("Error 4.5: \"durability\" was not found (necessary for Crafted Gear item type)")]
JsonNotFoundDura,
/// Requirements not found but is necessary
#[error(
"Error 4.6: \"requirements\" was not found (necessary for Crafted Gear / Consumable items)"
)]
JsonNotFoundReqs,
/// Unrecognisable Powder tier
#[error("Error 4.7: Unknown powder tier")]
JsonUnknownPowderTier,
/// Unrecognisable Powder element
#[error("Error 4.8: Unknown powder element")]
JsonUnknownPowderElement,
}

View file

@ -1,29 +0,0 @@
use thiserror::Error;
/// Errors yep
#[derive(Error, Debug)]
pub enum Errorfr {
/// item config json is missing
#[error("Error 1: item config json is missing")]
ItemJsonMissing,
/// item config json is corrupt
#[error("Error 2: item config json is corrupt, Reread config.md\n{0}")]
ItemJsonCorrupt(serde_json::Error),
/// idmap is missing
#[error("Error 3: id_keys.json is missing")]
IDMapJsonMissing,
/// idmap is corrupt
#[error("Error 4: id_keys.json is corrupt")]
IDMapJsonCorrupt,
/// shiny data json is missing
#[error("Error 5: shiny_stats.json is missing.")]
ShinyJsonMissing,
/// shiny data json is corrupt
#[error("Error 6: shiny_stats.json is corrupt.")]
ShinyJsonCorrupt
}

80
src/jsondl.rs Normal file
View file

@ -0,0 +1,80 @@
use crate::dl_json;
use crate::errorfr::Errorfr;
use crate::jsonstruct::Shinystruct;
use serde::Deserialize;
use std::collections::HashMap;
use std::fs;
pub fn load_idkeys(executable_path: &str) -> Result<HashMap<String, u8>, Errorfr> {
// id_keys.json
serde_json5::from_reader(
&mut fs::File::open(executable_path.to_owned() + "/id_keys.json")
.map_err(|_| Errorfr::IDMapJsonMissing)?,
)
.map_err(|_| Errorfr::IDMapJsonCorrupt)
}
pub fn load_shinystats(executable_path: &str) -> Result<Vec<Shinystruct>, Errorfr> {
// shiny_stats.json
serde_json5::from_reader(
&mut fs::File::open(executable_path.to_owned() + "/shiny_stats.json")
.map_err(|_| Errorfr::ShinyJsonMissing)?,
)
.map_err(|_| Errorfr::ShinyJsonCorrupt)
}
pub fn dl_json_fr(dlvalue: &String, executable_path: &str) {
let jsons = DownloadJsons::from(dlvalue.clone());
if jsons == DownloadJsons::All || jsons == DownloadJsons::ShinyStats {
if let Err(e) = dl_json(
"https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json".parse().unwrap(),
format!("{}{}", executable_path, "/shiny_stats.json"),
) { // error handling below
println!("{} Filename: {}",e,dlvalue)
}
}
if jsons == DownloadJsons::All || jsons == DownloadJsons::IdKeys {
if let Err(e) = dl_json(
"https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json"
.parse()
.unwrap(),
format!("{}{}", executable_path, "/id_keys.json"),
) {
// error handling below
println!("{} Filename: {}", e, dlvalue)
}
}
}
// stuff for the bit for downloading data jsons for ease of use
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug, Deserialize)]
pub enum DownloadJsons {
None,
IdKeys,
ShinyStats,
All,
}
impl From<String> for DownloadJsons {
fn from(value: String) -> Self {
match value.to_lowercase().as_str().trim() {
"none" => {
println!("download NONE");
DownloadJsons::None
}
"id_keys" | "idkeys" | "idkeys.json" | "id_keys.json" => {
println!("download ID_KEYS");
DownloadJsons::IdKeys
}
"shiny_stats" | "shinystats" | "shiny_stats.json" | "shinystats.json" => {
println!("download SHINY_STATS");
DownloadJsons::ShinyStats
}
"all" | "everything" | "both" => {
println!("download BOTH");
DownloadJsons::All
}
_ => {
println!("Could not understand what Jsons to download, sorry.");
DownloadJsons::None
}
}
}
}

210
src/jsonstruct.rs Normal file
View file

@ -0,0 +1,210 @@
use crate::errorfr::Errorfr;
use crate::jsonstruct::CraftedTypesFr::{Consu, Gear};
use idmangler_lib::types::{ClassType, ConsumableType::*, CraftedGearType::*, SkillType};
use idmangler_lib::types::{ConsumableType, CraftedGearType, EncodingVersion, ItemType};
use serde::Deserialize;
use std::fs;
// structs for the json parsing
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Jsonconfig {
pub debug: Option<bool>, // not a thing to be encoded, this just toggles debug prints. Also settable using --debug
// Item Types (Gear, Tome, Charm, Crafted Gear, Crafted Consum)
pub item_type: ItemTypeDeser,
// Crafted type for Crafted item types (
pub crafted_type: Option<String>,
// name of item
pub name: Option<String>,
// durability data (Crafted Gear)
pub durability: Option<Durability>,
// requirements data (Crafted Gear, Crafted
pub requirements: Option<RequirementsDeser>,
// shiny data
pub shiny: Option<Shinyjson>,
// identifications
pub ids: Option<Vec<Identificationer>>,
pub powders: Option<Vec<PowderFr>>,
pub rerolls: Option<u8>,
}
// reimplementing this because it doesnt have Deserialize.
// Also, changing the SkillPoint stuff into NOT a vec.
// This avoids confusing end user.
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
pub struct RequirementsDeser {
pub level: u8,
pub class: Option<ClassDeser>,
pub sp: Option<SkillPointDeser>,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
pub enum ClassDeser {
Archer,
Warrior,
Assassin,
Mage,
Shaman,
}
impl From<ClassDeser> for ClassType {
fn from(value: ClassDeser) -> Self {
match value {
ClassDeser::Archer => ClassType::Archer,
ClassDeser::Warrior => ClassType::Warrior,
ClassDeser::Assassin => ClassType::Assasin,
ClassDeser::Mage => ClassType::Mage,
ClassDeser::Shaman => ClassType::Shaman,
}
}
}
#[derive(Deserialize, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct SkillPointDeser {
#[serde(alias = "Str")]
#[serde(alias = "str")]
#[serde(alias = "strength")]
pub strength: Option<i32>,
#[serde(alias = "Dex")]
#[serde(alias = "dex")]
#[serde(alias = "dexterity")]
pub dexterity: Option<i32>,
#[serde(alias = "Def")]
#[serde(alias = "def")]
#[serde(alias = "defense")]
pub defense: Option<i32>,
#[serde(alias = "Int")]
#[serde(alias = "int")]
#[serde(alias = "intelligence")]
pub intelligence: Option<i32>,
#[serde(alias = "Agi")]
#[serde(alias = "agi")]
#[serde(alias = "agility")]
pub agility: Option<i32>,
}
impl From<SkillPointDeser> for Vec<(SkillType, i32)> {
fn from(value: SkillPointDeser) -> Self {
let mut returnedvec: Vec<(SkillType, i32)> = Vec::new();
if let Some(fr_str) = value.strength {
returnedvec.push((SkillType::Strength, fr_str))
}
if let Some(fr_dex) = value.dexterity {
returnedvec.push((SkillType::Dexterity, fr_dex))
}
if let Some(fr_int) = value.intelligence {
returnedvec.push((SkillType::Intelligence, fr_int))
}
if let Some(fr_def) = value.defense {
returnedvec.push((SkillType::Defence, fr_def))
}
if let Some(fr_agi) = value.agility {
returnedvec.push((SkillType::Agility, fr_agi))
}
returnedvec
}
}
#[derive(PartialEq, Eq, Hash, Debug)]
pub enum CraftedTypesFr {
Gear(CraftedGearType),
Consu(ConsumableType),
}
impl TryFrom<&str> for CraftedTypesFr {
type Error = Errorfr;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value.to_lowercase().as_str() {
// consu types
"potion" | "pot" | "potions" => Ok(Consu(Potion)),
"food" | "meal" | "foods" | "meals" => Ok(Consu(Food)),
"scroll" | "paper" => Ok(Consu(Scroll)),
// 5 weapon types
"spear" => Ok(Gear(Spear)),
"wand" => Ok(Gear(Wand)),
"dagger" => Ok(Gear(Dagger)),
"bow" => Ok(Gear(Bow)),
"relik" => Ok(Gear(Relik)),
// 4 armour types
"helmet" | "hat" => Ok(Gear(Helmet)),
"chestplate" | "shirt" | "chest" | "cp" => Ok(Gear(Chestplate)),
"leggings" | "legs" | "pants" | "trousers" => Ok(Gear(Leggings)),
"boots" | "shoes" => Ok(Gear(Boots)),
// 4 accessory types
"ring" => Ok(Gear(Ring)),
"bracelet" | "brace" => Ok(Gear(Bracelet)),
"necklace" => Ok(Gear(Necklace)),
// General gear types (FALLBACK) (don't use these if not necessary)
"weapon" => Ok(Gear(Weapon)),
"accessory" => Ok(Gear(Accessory)),
// fallback error return
_ => Err(Errorfr::JsonInvalidCraftedType),
}
}
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Durability {
pub effect_strength: Option<u8>,
pub dura_cur: i32,
pub dura_max: i32,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Shinystruct {
pub id: u8,
pub key: String,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Identificationer {
pub id: String,
pub base: i32,
pub roll: Option<u8>,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct PowderFr {
pub r#type: char,
pub amount: Option<u8>,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Shinyjson {
pub key: String,
pub value: i64,
}
// struct for general parameters for most encode functions
#[derive(PartialEq, Eq, Hash, Debug)]
pub struct FuncParams<'a> {
pub fr_out: &'a mut Vec<u8>,
pub fr_debug_mode: &'a bool,
pub fr_ver: EncodingVersion,
}
// I had to clone this and add Deserialize because the original idmangler_lib::types::ItemType does not
#[repr(u8)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug, Deserialize)]
pub enum ItemTypeDeser {
#[serde(alias = "gear")]
Gear = 0,
#[serde(alias = "tome")]
Tome = 1,
#[serde(alias = "charm")]
Charm = 2,
#[serde(alias = "craftedgear")]
#[serde(alias = "cgear")]
#[serde(alias = "CGear")]
CraftedGear = 3,
#[serde(alias = "craftedconsu")]
#[serde(alias = "cconsu")]
#[serde(alias = "CConsu")]
CraftedConsu = 4,
}
impl From<ItemTypeDeser> for ItemType {
fn from(value: ItemTypeDeser) -> ItemType {
match value {
ItemTypeDeser::Gear => ItemType::Gear,
ItemTypeDeser::Tome => ItemType::Tome,
ItemTypeDeser::Charm => ItemType::Charm,
ItemTypeDeser::CraftedConsu => ItemType::CraftedConsu,
ItemTypeDeser::CraftedGear => ItemType::CraftedGear,
}
}
}
pub fn load_jsonconfig(path: &String) -> Result<Jsonconfig, Errorfr> {
serde_json5::from_reader(&mut fs::File::open(path).map_err(|_| Errorfr::ItemJsonMissing)?)
.map_err(Errorfr::ItemJsonCorrupt)
}

View file

@ -1,276 +1,233 @@
use idmangler_lib::{ #![allow(clippy::single_match)]
encoding::encode_string,
types::{
ItemType, TransformVersion, {RollType, Stat}, Element
},
DataEncoder, EndData, IdentificationData, NameData, PowderData, RerollData, ShinyData,
StartData, TypeData,
};
use std::collections::HashMap; use idmangler_lib::{encoding::string::encode_string, types::EncodingVersion};
use std::fs;
use std::panic; use std::{collections::HashMap, env, fs, io, path::PathBuf};
mod structures;
use crate::structures::*; mod encode;
mod errorfr; mod errorfr;
mod jsondl;
mod jsonstruct;
use crate::errorfr::Errorfr; use crate::errorfr::Errorfr;
use crate::jsondl::*;
use crate::jsonstruct::*;
use crate::errorfr::Errorfr::JsonNotFoundCraftedType;
use clap::Parser; use clap::Parser;
use reqwest::Url;
#[derive(Parser, Debug)] #[derive(Parser, Debug, Clone)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None, arg_required_else_help(true))]
struct Args { struct Args {
/// Path for config path /// Path for config path
#[arg(short, long)] #[arg(short, long)]
config: Option<String>, config: Option<String>,
/// Enable debug mode /// Enable debug mode
#[arg(short, long, default_value_t = false)] #[arg(long, default_value_t = false)]
debugmode: bool, debug: bool,
/// Download jsons (for ease of use)
#[arg(short, long)]
download: Option<String>,
} }
// const fallbackconfigpath: String = "config.json".to_owned(); fn dl_json(url: Url, savename: String) -> Result<(), Errorfr> {
let resp = reqwest::blocking::get(url).map_err(|_| Errorfr::JsonDlReqFail)?;
let body = resp.text().map_err(|_| Errorfr::JsonDlReqBodyInvalid)?;
let savepath = savename.to_string();
println!("Downloading file to {savepath}");
let mut out = fs::File::create(savepath).map_err(|_| Errorfr::JsonDlReqFileCreateFail)?;
io::copy(&mut body.as_bytes(), &mut out).map_err(|_| Errorfr::JsonDlReqFileWriteFail)?;
Ok(())
}
fn main() { fn main() {
if let Err(e) = cook() {
println!("{}",e);
}
}
fn cook() -> Result<(), Errorfr> {
// enable fancypanic when building for release
// fancypanic();
let args = Args::parse(); let args = Args::parse();
let mut executable_path = env::current_exe().unwrap();
PathBuf::pop(&mut executable_path);
let executable_path = executable_path.to_str().unwrap();
let mut debug_mode = false; let mut debug_mode = false;
if args.debugmode == true { if args.debug {
debug_mode = true; debug_mode = true;
println!("Debug mode enabled"); println!("Debug mode enabled");
}; };
let mut config: String = String::from("config.json");
if let Some(configpathargs) = args.config { // download jsons if necessary
config = configpathargs; if let Some(dlvalue) = &args.download {
dl_json_fr(dlvalue, executable_path)
};
// check if files load properly and all that
if let Some(t) = &args.config {
match load_idkeys(executable_path) {
Ok(loaded_idkeys) => {
match load_shinystats(executable_path) {
Ok(loaded_shinystats) => {
match load_jsonconfig(t) {
Ok(loaded_config) => {
// debug mode on if in the loaded config
if let Some(debugconfig) = loaded_config.debug {
if debugconfig {
debug_mode = true
} }
}
// load configs // main program everything starts here fr
let json_config: Jsonconfig = serde_json::from_reader(fs::File::open(config) let mut out: Vec<u8> = Vec::new();
.map_err(|_| Errorfr::ItemJsonMissing)?)
.map_err(|e| Errorfr::ItemJsonCorrupt(e))?;
let idsmap: HashMap<String, u8> = serde_json::from_reader(fs::File::open("id_keys.json")
.map_err(|_| Errorfr::IDMapJsonMissing)?)
.map_err(|_| Errorfr::IDMapJsonCorrupt)?;
let json_shiny: Vec<Shinystruct> = serde_json::from_reader(fs::File::open("shiny_stats.json")
.map_err(|_| Errorfr::ShinyJsonMissing)?)
.map_err(|_| Errorfr::ShinyJsonCorrupt)?;
// println!("{:?}",idsmap.get("airDamage"));
// create necessary variables // create necessary variables
let mut out = Vec::new(); let ver = EncodingVersion::Version1;
let ver = TransformVersion::Version1;
StartData(ver) let loaded_config_borrow = &loaded_config;
.encode(ver, &mut out) // ENCODE: ALotOfStuff
.unwrap(); // Also print any mapped errors
let cooking = cook(
TypeData(ItemType::Gear) &mut out,
.encode(ver, &mut out) &debug_mode,
.unwrap(); ver,
loaded_config_borrow,
NameData(String::from(format!("{}", json_config.name.trim()))) loaded_idkeys,
.encode(ver, &mut out) loaded_shinystats,
.unwrap();
// 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: 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
}
}
); );
if let Err(e) = cooking {
println!("{}", e); // print error if there is an error
} else {
// final string print if there is no error
// println!("{:?} {:?} {:?}",id_id,id_base,id_roll) println!("{}", cooking.unwrap())
} }
}
IdentificationData { Err(e) => println!("{}", e),
identifications: idvec, }
extended_encoding: true, }
} Err(e) => println!("{}", e),
.encode(ver, &mut out) }
.unwrap(); }
Err(e) => println!("{}", e),
// 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 = eachpowder.amount.unwrap_or_else(|| 1);
// match for the powder type
for _ in 0..powderamount {
let eletype = match eachpowder.r#type.to_ascii_lowercase() {
'e' => {
if debug_mode {
println!("Powder type: Earth");
}
Element::Earth
}
't' => {
if debug_mode {
println!("Powder type: Thunder");
}
Element::Thunder
}
'w' => {
if debug_mode {
println!("Powder type: Water");
}
Element::Water
}
'f' => {
if debug_mode {
println!("Powder type: Fire");
}
Element::Fire
}
'a' => {
if debug_mode {
println!("Powder type: Air");
}
Element::Air
}
_ => {
if debug_mode {
println!("Powder type: Broken, fallback Thunder");
}
Element::Thunder
}
};
powdervec.push(Some((eletype,powdertier)));
if debug_mode {
println!("Powder tier: {}", powdertier);
println!("Powder amount: {}", powderamount);
} }
fn cook(
out: &mut Vec<u8>, debug_mode: &bool, ver: EncodingVersion, json_config: &Jsonconfig,
idsmap: HashMap<String, u8>, json_shiny: Vec<Shinystruct>,
) -> Result<String, Errorfr> {
let mut fr_params = FuncParams {
fr_out: out,
fr_debug_mode: debug_mode,
fr_ver: ver,
}; };
// ENCODE: StartData and TypeData, ALWAYS
fr_params.encode_startdata()?;
fr_params.encode_typedata(json_config.item_type)?;
// ENCODE: CustomGearTypeData / CustomConsumableTypeData
match json_config.item_type {
} ItemTypeDeser::CraftedGear | ItemTypeDeser::CraftedConsu => {
if debug_mode { if let Some(real_crafted_type) = &json_config.crafted_type {
println!("Powders Vec: {:?}", powdervec); fr_params.encode_typedata_custom(real_crafted_type)?;
} } else {
return Err(JsonNotFoundCraftedType);
// 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();
if debug_mode {
println!("Rerolls: {}", i)
} }
} }
} _ => {}
None => pass(),
} }
let mut realshinykey: u8; // ENCODE: NameData, if ItemType is Gear, Tome, Charm
if let Some(shiny) = json_config.shiny { match json_config.item_type {
if let ref _shinykey = shiny.key { ItemTypeDeser::Gear | ItemTypeDeser::Tome | ItemTypeDeser::Charm => {
if let shinyvalue = shiny.value { if let Some(real_name) = &json_config.name {
fr_params.encode_namedata(real_name)?
realshinykey = 1; } else {
for i in json_shiny { return Err(Errorfr::JsonNotFoundName);
if i.key == shiny.key {
realshinykey = i.id;
if debug_mode {
println!("shiny key {}", shiny.key);
} }
} }
} _ => {}
if debug_mode {
dbg!(&realshinykey);
dbg!(&shinyvalue);
} }
ShinyData { // ENCODE: IdentificationData
id: realshinykey, match json_config.item_type {
val: shinyvalue as i64, //- 0b0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000, ItemTypeDeser::Gear | ItemTypeDeser::Tome | ItemTypeDeser::Charm => {
// u16::MAX is the max value of unsigned 16bit value if let Some(real_ids) = &json_config.ids {
} fr_params.encode_iddata(real_ids, idsmap)?
.encode(ver, &mut out)
.unwrap();
} }
} }
_ => {}
} }
// prints (Water,6) 255 times // ENCODE: DurabilityData (REQUIRED for CraftedGear)
// println!("{:?}",vec![(Powders::WATER, 6); 255]); match json_config.item_type {
ItemTypeDeser::CraftedGear => {
EndData.encode(ver, &mut out).unwrap(); if let Some(real_dura) = &json_config.durability {
fr_params.encode_duradata(real_dura)?;
// final string print } else {
println!("{}", encode_string(&out)); return Err(Errorfr::JsonNotFoundDura);
}
// 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);
Ok(())
} }
fn fancypanic() { // ENCODE: RequirementsData if ItemType is CraftedGear, CraftedConsu
panic::set_hook(Box::new(|panic_info| { match json_config.item_type {
let panic_msg = format!("{panic_info}"); ItemTypeDeser::CraftedGear | ItemTypeDeser::CraftedConsu => {
println!( if let Some(real_reqs) = json_config.requirements {
"{}", fr_params.encode_reqdata(real_reqs)?
panic_msg } else {
.lines() return Err(Errorfr::JsonNotFoundReqs);
.nth(1) }
.unwrap_or("HOW DID YOU BREAK THE PANIC HANDLER???") }
); _ => {}
}));
} }
fn pass() {} // ENCODE: PowderData if ItemType is Gear, CraftedGear
match json_config.item_type {
ItemTypeDeser::Gear | ItemTypeDeser::CraftedGear => {
if let Some(real_powders) = &json_config.powders {
fr_params.encode_powderdata(real_powders)?
}
}
_ => {}
}
const ERROR: [&'static str; 7] = [ // ENCODE: RerollData if ItemType is Gear, Tome, Charm
"Error 0: what did you even do to get this? ", match json_config.item_type {
"Error 1: json config json is missing, obtain it from https://git.frfrnocap.men/endernon/idmangler-cli/raw/branch/main/config.json and move it to this directory. ", ItemTypeDeser::Gear | ItemTypeDeser::Tome | ItemTypeDeser::Charm => {
"Error 2: json config json is corrupt. Reread config.md or reobtain it from https://git.frfrnocap.men/endernon/idmangler-cli/raw/branch/main/config.json and move it to this diirectory. ", if let Some(rerollcount) = json_config.rerolls {
"Error 3: Identifications hashmap is missing. Get it from https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json and move it to this directory. ", // rerolldata
"Error 4: Identifications hashmap is corrupt. Reobtain it from https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/id_keys.json and move it to this directory. ", fr_params.encode_rerolldata(rerollcount)?
"Error 5: Shiny data json is missing. Get it from https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json and move it to this directory. ", }
"Error 6: Shiny data json is corrupt. Get it from https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Data-Storage/shiny_stats.json and move it to this directory. " }
]; _ => {}
}
// ENCODE: ShinyData if ItemType is Gear
match json_config.item_type {
ItemTypeDeser::Gear => {
if let Some(shiny) = &json_config.shiny {
fr_params.encode_shinydata(shiny, &json_shiny)?
}
}
_ => {}
}
// ENCODE: EndData, ALWAYS
fr_params.encode_enddata()?;
let mut final_string: String = encode_string(out);
// add NameAfter
match json_config.item_type {
ItemTypeDeser::CraftedGear | ItemTypeDeser::CraftedConsu => {
if let Some(real_name) = &json_config.name {
final_string = format!("{} \"{}\"", final_string, real_name)
} else {
return Err(Errorfr::JsonNotFoundName);
}
}
_ => {}
}
Ok(final_string)
}

View file

@ -1,35 +0,0 @@
use serde::Deserialize;
// structs
#[derive(Deserialize)]
pub struct Powder {
pub r#type: char,
pub tier: u8,
pub amount: Option<u8>,
}
#[derive(Deserialize)]
pub struct Identificationer {
pub id: String,
pub base: i32,
pub roll: Option<u8>,
}
#[derive(Deserialize)]
pub struct Jsonconfig {
pub debug: Option<bool>,
pub name: String,
pub shiny: Option<Shinyjson>,
pub ids: Vec<Identificationer>,
pub powder_limit: u8,
pub powders: Vec<Powder>,
pub rerolls: Option<u8>,
}
#[derive(Deserialize)]
pub struct Shinystruct {
pub id: u8,
pub key: String,
}
#[derive(Deserialize)]
pub struct Shinyjson {
pub key: String,
pub value: i64,
}