Compare commits

...

68 commits
v0.4.3 ... main

Author SHA1 Message Date
446951ea0f major cleanup 2025-01-18 13:18:55 +00:00
03b87c64f6 do the build script 2025-01-17 22:36:22 +00:00
638fc44b23 bump cargo.toml 2025-01-17 22:33:12 +00:00
315a345009 add the exception for Spell Costs (fuck you wynncraft) 2025-01-17 22:31:46 +00:00
3d2d96f86e Perfect flag implementation 2025-01-17 21:26:50 +00:00
afa7971f17 perfect flag 2025-01-17 20:59:25 +00:00
8d2e685957 printlnl removal 2025-01-14 22:53:31 +00:00
477532580c fix path for cache 2025-01-14 22:39:06 +00:00
3f91f62047 crazy optimization 2025-01-14 22:30:32 +00:00
192765a3ec truly cool tree 2025-01-14 21:29:54 +00:00
862ee83356 cool tree 2025-01-14 20:08:26 +00:00
116fd90232 remove redundant 2025-01-14 18:30:39 +00:00
22f5f06e5c upper limit 2025-01-14 18:22:41 +00:00
7d4dcfa2b9 let me cook 2025-01-14 18:19:16 +00:00
fe7ec985f2 frfr 2025-01-14 18:14:35 +00:00
2a3fcd5820 fr 2025-01-14 18:13:54 +00:00
24bab0fb18 make perfect set name for now 2025-01-14 18:09:49 +00:00
76108fa49f example configs stuff 2025-01-11 22:37:51 +00:00
7446de3741 fr cargo 2025-01-11 22:32:20 +00:00
a3533aa7e9 test change 2025-01-11 22:31:41 +00:00
1034ab46f4 fr 2025-01-11 20:45:19 +00:00
d59ccdcd8a reorganising 2025-01-11 20:42:43 +00:00
cb04dc166c git is cooking smth but idk what 2025-01-11 20:29:20 +00:00
6984d9cabc oopsy forgot this one 2025-01-11 20:12:06 +00:00
25b29da736 compress alias definitions 2025-01-11 20:00:49 +00:00
0588b2a6a3 placeholder for dmg encode 2025-01-11 19:51:37 +00:00
38fad624a8 add a bunch of aliases to struct 2025-01-11 19:46:55 +00:00
9d34436d3f comment reorganise 2025-01-11 16:10:06 +00:00
56d11b3534 cargo fmt gaming 2025-01-11 16:07:10 +00:00
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
21 changed files with 1417 additions and 574 deletions

1
.gitignore vendored
View file

@ -23,3 +23,4 @@ product/
releases
id_keys.json
shiny_stats.json
data

234
Cargo.lock generated
View file

@ -19,9 +19,9 @@ checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "anstream"
version = "0.6.15"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
@ -34,36 +34,37 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.8"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.5"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.1"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.4"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
"once_cell",
"windows-sys 0.59.0",
]
[[package]]
@ -101,9 +102,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "2.6.0"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "block-buffer"
@ -128,9 +129,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
[[package]]
name = "cc"
version = "1.2.5"
version = "1.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229"
dependencies = [
"shlex",
]
@ -143,9 +144,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.20"
version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
dependencies = [
"clap_builder",
"clap_derive",
@ -153,9 +154,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.20"
version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
dependencies = [
"anstream",
"anstyle",
@ -165,9 +166,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.18"
version = "4.5.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
dependencies = [
"heck",
"proc-macro2",
@ -177,15 +178,15 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.2"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "colorchoice"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "core-foundation"
@ -644,23 +645,25 @@ dependencies = [
[[package]]
name = "idmangler-cli"
version = "0.4.3"
version = "0.5.0"
dependencies = [
"clap",
"idmangler-lib",
"reqwest",
"serde",
"serde_json",
"serde_json5",
"thiserror 2.0.9",
"thiserror",
]
[[package]]
name = "idmangler-lib"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0395df40b27e5b44d89befbf479c06df7554c0af28674fa663aebd8e0d8f400c"
checksum = "b3289c6bd14bc60ec34cebb05292f1bbf369eace2674e6def4dc0f031b34e344"
dependencies = [
"thiserror 1.0.68",
"serde",
"thiserror",
]
[[package]]
@ -708,15 +711,15 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.11"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "js-sys"
version = "0.3.76"
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
dependencies = [
"once_cell",
"wasm-bindgen",
@ -730,9 +733,9 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "litemap"
@ -742,9 +745,9 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]]
name = "log"
version = "0.4.22"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "memchr"
@ -760,9 +763,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "miniz_oxide"
version = "0.8.2"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
dependencies = [
"adler2",
]
@ -867,7 +870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc"
dependencies = [
"memchr",
"thiserror 2.0.9",
"thiserror",
"ucd-trie",
]
@ -907,9 +910,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "pin-utils"
@ -925,27 +928,27 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "proc-macro2"
version = "1.0.86"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "reqwest"
version = "0.12.9"
version = "0.12.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da"
dependencies = [
"base64",
"bytes",
@ -977,6 +980,7 @@ dependencies = [
"system-configuration",
"tokio",
"tokio-native-tls",
"tower",
"tower-service",
"url",
"wasm-bindgen",
@ -1008,9 +1012,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustix"
version = "0.38.42"
version = "0.38.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
dependencies = [
"bitflags",
"errno",
@ -1021,9 +1025,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.20"
version = "0.23.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b"
checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8"
dependencies = [
"once_cell",
"rustls-pki-types",
@ -1058,6 +1062,12 @@ dependencies = [
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
version = "1.0.18"
@ -1088,9 +1098,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.13.0"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5"
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
dependencies = [
"core-foundation-sys",
"libc",
@ -1098,18 +1108,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.210"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
@ -1118,9 +1128,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.128"
version = "1.0.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
dependencies = [
"itoa",
"memchr",
@ -1219,9 +1229,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.87"
version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [
"proc-macro2",
"quote",
@ -1271,12 +1281,13 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.14.0"
version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
dependencies = [
"cfg-if",
"fastrand",
"getrandom",
"once_cell",
"rustix",
"windows-sys 0.59.0",
@ -1284,38 +1295,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.68"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892"
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
dependencies = [
"thiserror-impl 1.0.68",
]
[[package]]
name = "thiserror"
version = "2.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc"
dependencies = [
"thiserror-impl 2.0.9",
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.68"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thiserror-impl"
version = "2.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4"
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
@ -1334,9 +1325,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.42.0"
version = "1.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e"
dependencies = [
"backtrace",
"bytes",
@ -1380,6 +1371,27 @@ dependencies = [
"tokio",
]
[[package]]
name = "tower"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
"pin-project-lite",
"sync_wrapper",
"tokio",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]]
name = "tower-service"
version = "0.3.3"
@ -1425,9 +1437,9 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "unicode-ident"
version = "1.0.12"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "untrusted"
@ -1493,20 +1505,21 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
@ -1518,9 +1531,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.49"
version = "0.4.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2"
checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
dependencies = [
"cfg-if",
"js-sys",
@ -1531,9 +1544,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1541,9 +1554,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
@ -1554,15 +1567,18 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.99"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-sys"
version = "0.3.76"
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc"
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
dependencies = [
"js-sys",
"wasm-bindgen",

View file

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

View file

@ -5,7 +5,7 @@ mkdir -p product
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
cp -u -p ./{config.json,config_hanafupookie.json,config_singu.json} ./product/
cp -r ./example_configs ./product/
pkgversion=$(cargo metadata --format-version=1 --no-deps | jq '.packages[] | select(.name == "idmangler-cli") | .version')
echo "package version is:"
@ -16,5 +16,5 @@ echo "$balls2"
cd product
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 idmangler-cli
zip "idmangler-windows-x64-${balls2}.zip" ./example_configs/ idmangler-cli.exe
zip "idmangler-linux-x64-${balls2}.zip" ./example_configs/ idmangler-cli

View file

@ -1,7 +1,7 @@
# 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.
- 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"`

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

@ -5,10 +5,6 @@
],
"name":"Hanafubuki",
"item_type": "Gear",
"shiny": {
"key": "playersKilled",
"value": 9223372036854775807
},
"ids": [
{"id": "3rdSpellCost","base": -25,"roll": 70},
{"id": "4thSpellCost", "base":-15 , "roll":70 },
@ -16,10 +12,6 @@
{"id": "elementalDamage", "base":256 , "roll":130},
{"id": "jumpHeight", "base":3, "roll":130 },
{"id": "rawStrength", "base":15}
],
"powders": [
],
"rerolls": 255
}

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
}

3
rustfmt.toml Normal file
View file

@ -0,0 +1,3 @@
fn_params_layout = "Compressed"
attr_fn_like_width = 210
max_width = 220

View file

@ -1,50 +0,0 @@
[
{
"id": 1,
"key": "mobsKilled",
"displayName": "Mobs Killed",
"statUnit": "raw"
},
{
"id": 2,
"key": "raidsWon",
"displayName": "Raids Won",
"statUnit": "raw"
},
{
"id": 3,
"key": "chestsOpened",
"displayName": "Chests Opened",
"statUnit": "raw"
},
{
"id": 4,
"key": "warsWon",
"displayName": "Wars Won",
"statUnit": "raw"
},
{
"id": 5,
"key": "playersKilled",
"displayName": "Players Killed",
"statUnit": "raw"
},
{
"id": 6,
"key": "dungeonsWon",
"displayName": "Dungeons Won",
"statUnit": "raw"
},
{
"id": 7,
"key": "deaths",
"displayName": "Deaths",
"statUnit": "raw"
},
{
"id": 8,
"key": "lootrunsCompleted",
"displayName": "Lootruns Completed",
"statUnit": "raw"
}
]

276
src/encode.rs Normal file
View file

@ -0,0 +1,276 @@
use crate::errorfr::Errorfr;
use crate::jsonstruct::{CraftedTypesFr, Durability, 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;
use idmangler_lib::types::EncodingVersion;
/// FuncParams struct, used for the three most important parameters for encoding.
/// Also, all the encode functions are stored here, seeing as I require these three params most of the time when encoding.
#[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,
}
impl FuncParams<'_> {
/// ENCODE: StartData
/// (REQUIRED)
pub fn encode_startdata(&mut self) -> Result<(), Errorfr> {
if *self.fr_debug_mode {
println!("Encoding StartData")
}
StartData(self.fr_ver).encode(self.fr_ver, self.fr_out).unwrap();
Ok(())
}
/// ENCODE: TypeData
/// (REQUIRED)
pub fn encode_typedata(&mut self, item_type_deser: ItemTypeDeser) -> Result<(), Errorfr> {
if *self.fr_debug_mode {
println!("Encoding TypeData: {:?}", item_type_deser);
}
TypeData(ItemType::from(item_type_deser)).encode(self.fr_ver, self.fr_out).unwrap();
Ok(())
}
/// ENCODE: NameData
pub fn encode_namedata(&mut self, real_name: &str) -> Result<(), Errorfr> {
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(())
}
/// ENCODE: IdentificationData
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,
},
});
}
if *self.fr_debug_mode {
println!("Encoding IdentificationData: {:?}", &idvec)
}
IdentificationData {
identifications: idvec,
extended_encoding: true,
}
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
/// ENCODE: PowderData
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)
PowderData {
powder_slots: powderlimitfr,
powders: powdervec,
}
.encode(self.fr_ver, self.fr_out)
.unwrap();
Ok(())
}
/// ENCODE: RerollData
pub fn encode_rerolldata(&mut self, rerollcount: u8) -> Result<(), Errorfr> {
if rerollcount != 0 {
RerollData(rerollcount).encode(self.fr_ver, self.fr_out).unwrap();
if *self.fr_debug_mode {
dbg!(rerollcount);
}
}
Ok(())
}
/// ENCODE: ShinyData
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);
}
ShinyData { id: realshinykey, val: shinyvalue }.encode(self.fr_ver, self.fr_out).unwrap();
Ok(())
}
/// ENCODE: EndData
/// (REQUIRED)
pub fn encode_enddata(&mut self) -> Result<(), Errorfr> {
if *self.fr_debug_mode {
println!("Encoding EndData")
}
EndData.encode(self.fr_ver, self.fr_out).unwrap();
Ok(())
}
/// ENCODE: CraftedConsumableTypeData or CraftedGearTypeData based on Type
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(())
}
/// ENCODE: DamageData
/// (CRAFTED ONLY)
pub fn encode_damagedata(&mut self) -> Result<(), Errorfr> {
unimplemented!();
}
/// ENCODE: DefenseData
/// (CRAFTED ONLY)
pub fn encode_defensedata(&mut self) -> Result<(), Errorfr> {
unimplemented!();
}
/// ENCODE: DurabilityData
/// (CRAFTED ONLY)
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 {
// percentage of max durability
let current_percentage = real_dura.dura_cur / real_dura.dura_max;
// 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(())
}
/// ENCODE: RequirementsData
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(())
}
}

102
src/errorfr.rs Normal file
View file

@ -0,0 +1,102 @@
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 2.1: id_keys.json is missing. \nYou should run \"--download id_keys\" or \"--download All\".")]
IDMapJsonMissing,
/// idmap is corrupt
#[error("Error 2.2: id_keys.json is corrupt. \nYou should run \"--download id_keys\" or \"--download All\".\n{0}")]
IDMapJsonCorrupt(serde_json::Error),
/// shiny data json is missing
#[error("Error 2.3: shiny_stats.json is missing. \nYou should run \"--download ShinyStats\" or \"--download All\".")]
ShinyJsonMissing,
/// shiny data json is corrupt
#[error("Error 2.4: shiny_stats.json is corrupt. \nYou should run \"--download ShinyStats\" or \"--download All\".")]
ShinyJsonCorrupt,
/// gear json is missing
#[error("Error 2.5: gear.json is missing. It's only required for the \"perfect mode\" item gen. \nYou should run \"--download Gear\" or \"--download All\".")]
GearJsonMissing,
/// gear data json is corrupt
#[error("Error 2.6: gear.json is corrupt. It's only required for the \"perfect mode\" item gen. \nYou should run \"--download Gear\" or \"--download All\".\n{0:?}")]
GearJsonCorrupt(serde_json::Error),
/// gear json is missing
#[error("Error 2.7: gear_cache.json is missing. It's only required for the \"perfect mode\" item gen. \nYou should run \"--download Gear\" or \"--download All\".")]
GearJsonCacheMissing,
/// gear data json is corrupt
#[error("Error 2.8: gear_cache.json is corrupt. It's only required for the \"perfect mode\" item gen. \nYou should run \"--download Gear\" or \"--download All\".\n{0:?}")]
GearJsonCacheCorrupt(serde_json::Error),
/// gear data json cache could not be created
#[error("Error 2.8: unable to create file gear_cache.json.")]
GearJsonCacheCreateFail,
/// 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,
/// Unrecognisable item for the Perfect gen function
#[error("Error 4.9: Unknown item for perfect gen...")]
PerfectItemNotFound,
}

View file

@ -1,45 +0,0 @@
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,
}

76
src/gearjson.rs Normal file
View file

@ -0,0 +1,76 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::errorfr::Errorfr;
use crate::jsonstruct::Identificationer;
// the struct for the stuff I need in in Hashmap<String, GearJson> gear.json. its a big ass pain
#[derive(Deserialize, Serialize, PartialEq, Eq, Debug, Clone)]
pub struct GearJsonItem {
identifications: Option<
HashMap<
String, GearJsonItemInner
>
>
}
#[derive(Deserialize, Serialize, PartialEq, Eq, Debug, Clone)]
#[serde(untagged)]
pub enum GearJsonItemInner {
r#Struct(GearJsonItemInnerStruct),
r#Int(i32)
}
#[derive(Deserialize, Serialize, PartialEq, Eq, Debug, Clone)]
pub struct GearJsonItemInnerStruct {
max: i32,
min: i32,
raw: i32
}
/// Function to generate a perfect item.
/// It returns Result\<Vec\<Identificationer\>, Errorfr\>
pub fn gen_perfect(name: &str, frjson: &HashMap<String, GearJsonItem>) -> Result<Vec<Identificationer>, Errorfr> {
let mut a: Vec<Identificationer> = Vec::new();
let name = name.to_lowercase();
match frjson.get(&name) {
Some(fr_idents) => {
if let Some(fr_identmap) = &fr_idents.identifications {
for i in fr_identmap {
println!("{i:?}");
if let &GearJsonItemInner::Struct(e) = &i.1 {
// hardcoded list of inverts. Don't question why it's like this, blame whatever the fuck wynncraft was smoking.
// I'm going to have to update this list manually too... why the fuck, wynncraft?
let invert_bool: bool = matches!(i.0.to_lowercase().as_str(),
"4thspellcost" |
"3rdspellcost" |
"2ndspellcost" |
"1stspellcost" |
"raw4thspellcost" |
"raw3rdspellcost" |
"raw2ndspellcost" |
"raw1stSpellCost");
let ider: Identificationer = Identificationer {
id: i.0.clone(),
base: {
if invert_bool {-e.clone().raw} // invert value if invert mode true
else {e.clone().raw} // else regular value
},
roll: Some(match &e.clone().raw {
fr if fr<&0 => 70,
fr if fr>&0 => {
if invert_bool {70} // value 70 if invert mode true
else {130}// else value 130
},
_ => 0
})
};
println!("ider: {ider:?}");
a.push(ider)
}
}
}
},
None => return Err(Errorfr::PerfectItemNotFound)
}
Ok(a)
}

134
src/jsondl.rs Normal file
View file

@ -0,0 +1,134 @@
use crate::{dl_json,
errorfr::Errorfr,
gearjson,
jsonstruct::Shinystruct
};
use serde::Deserialize;
use std::{
collections::HashMap,
fs,
io::{BufReader, Write}
};
pub fn load_idkeys(executable_path: &str) -> Result<HashMap<String, u8>, Errorfr> {
// id_keys.json
serde_json::from_reader(&mut BufReader::new(
&mut fs::File::open(executable_path.to_owned() + "/data/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_json::from_reader(&mut BufReader::new(
fs::File::open(executable_path.to_owned() + "/data/shiny_stats.json")
.map_err(|_| Errorfr::ShinyJsonMissing)?))
.map_err(|_| Errorfr::ShinyJsonCorrupt)
}
pub fn load_gear(executable_path: &str) -> Result<HashMap<String, gearjson::GearJsonItem>, Errorfr> {
// gear.json parse (ONLY FOR DL gear.json)
let a: HashMap<String, gearjson::GearJsonItem> = serde_json::from_reader(&mut BufReader::new(
fs::File::open(executable_path.to_owned() + "/data/gear.json")
.map_err(|_| Errorfr::GearJsonMissing)?))
.map_err(Errorfr::GearJsonCacheCorrupt)?;
// parse the original, "a", into lowercase as "b"
let mut b: HashMap<String, gearjson::GearJsonItem> = HashMap::new();
for i in &a {
let frname = i.0.to_lowercase();
let frvalue = i.1.clone();
b.insert(frname, frvalue);
}
Ok(b)
}
pub fn load_gear_cache(executable_path: &str) -> Result<HashMap<String, gearjson::GearJsonItem>, Errorfr> {
// gear_cache.json (ONLY FOR PERFECT ITEM FUNCTION GEN)
serde_json::from_reader(&mut BufReader::new(
fs::File::open(executable_path.to_owned() + "/data/gear_cache.json")
.map_err(|_| Errorfr::GearJsonCacheMissing)?))
.map_err(Errorfr::GearJsonCorrupt)
}
pub fn dl_json_fr(dlvalue: &String, executable_path: &str) {
let jsons = DownloadJsons::from(dlvalue.clone());
if let Err(e) = fs::create_dir_all(format!("{}{}", executable_path, "/data/")) {
println!("Unable to create path. Path: {} ", e)
}
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, "/data/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, "/data/id_keys.json"),
) {
// error handling below
println!("{} Filename: {}", e, dlvalue)
}
}
if jsons == DownloadJsons::All || jsons == DownloadJsons::Gear {
match dl_json(
"https://raw.githubusercontent.com/Wynntils/Static-Storage/main/Reference/gear.json".parse().unwrap(),
format!("{}{}", executable_path, "/data/gear.json"),
) {
Err(e) => {
// error handling below
println!("{} Filename: {}", e, dlvalue);
},
Ok(_) => {
let frfrnocap = serde_json::to_vec(
&load_gear(executable_path)
.unwrap()
).unwrap();
let mut outer = fs::File::create(format!("{}{}",executable_path, "/data/gear_cache.json")).map_err(|_| Errorfr::GearJsonCacheCreateFail).unwrap();
outer.write_all(&frfrnocap).unwrap();
println!("Making gearcache to {}/data/gear_cache.json", executable_path);
}
}
}
}
// 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,
Gear,
All,
}
impl From<String> for DownloadJsons {
fn from(value: String) -> Self {
match value.to_lowercase().as_str().trim() {
"none" => {
println!("downloading NONE (Why? it's pointless...)");
DownloadJsons::None
}
"id_keys" | "idkeys" | "idkeys.json" | "id_keys.json" => {
println!("downloading ID_KEYS");
DownloadJsons::IdKeys
}
"shiny_stats" | "shinystats" | "shiny_stats.json" | "shinystats.json" => {
println!("downloading SHINY_STATS");
DownloadJsons::ShinyStats
}
"gear" | "gear.json" => {
println!("downloading GEAR");
DownloadJsons::Gear
}
"all" | "everything" | "both" => {
println!("downloading ALL jsons");
DownloadJsons::All
}
_ => {
println!("downloading NONE (unable to understand prompt)");
DownloadJsons::None
}
}
}
}

241
src/jsonstruct.rs Normal file
View file

@ -0,0 +1,241 @@
use crate::errorfr::Errorfr;
use crate::jsonstruct::CraftedTypesFr::{Consu, Gear};
use idmangler_lib::types::{AttackSpeed, ClassType, ConsumableType, ConsumableType::*, CraftedGearType, CraftedGearType::*, EncodingVersion, ItemType, SkillType};
use serde::Deserialize;
use std::fs;
// structs for the json parsing
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct Jsonconfig {
// not a thing to be encoded, this just toggles debug prints. Also settable using --debug
#[serde(alias = "Debug", alias = "DEBUG")]
pub debug: Option<bool>,
// Item Types (Gear, Tome, Charm, Crafted Gear, Crafted Consum)
#[serde(alias = "itemtype", alias = "ITEM_TYPE", alias = "ITEMTYPE", alias = "Item_Type", alias = "Item_type", alias = "ItemType", alias = "Itemtype")]
pub item_type: ItemTypeDeser,
// Crafted type for Crafted item types
#[serde(alias = "craftedtype", alias = "CRAFTED_TYPE", alias = "CRAFTEDTYPE", alias = "Crafted_Type", alias = "Crafted_type", alias = "CraftedType", alias = "Craftedtype")]
pub crafted_type: Option<String>,
// name of item
#[serde(alias = "Name", alias = "NAME")]
pub name: Option<String>,
// shiny data
#[serde(alias = "Shiny", alias = "SHINY")]
pub shiny: Option<Shinyjson>,
// identifications
#[serde(alias = "Ids", alias = "IDS", alias = "identifications", alias = "Identifications", alias = "IDENTIFICATIONS")]
pub ids: Option<Vec<Identificationer>>,
// powders stuff
#[serde(alias = "Powders", alias = "POWDERS", alias = "powder", alias = "Powder", alias = "POWDER")]
pub powders: Option<Vec<PowderFr>>,
// rerolls
#[serde(alias = "Rerolls", alias = "REROLLS", alias = "reroll", alias = "Reroll", alias = "REROLL")]
pub rerolls: Option<u8>,
// durability data (Crafted Gear)
#[serde(alias = "durability", alias = "Durability", alias = "DURABILITY", alias = "dura", alias = "Dura", alias = "DURA")]
pub crafted_durability: Option<Durability>,
// requirements data (Crafted)
#[serde(alias = "requirement", alias = "Requirement", alias = "REQUIREMENT", alias = "requirements", alias = "Requirements", alias = "REQUIREMENTS")]
pub crafted_requirements: Option<RequirementsDeser>,
// identifications (Crafted)
// to be honest i wish there was a better way instead of too many aliases
#[serde(
alias = "craftedids",
alias = "CRAFTED_IDS",
alias = "CRAFTEDIDS",
alias = "Crafted_Ids",
alias = "Crafted_ids",
alias = "CraftedIds",
alias = "Craftedids",
alias = "craftedidentifications",
alias = "CRAFTED_IDENTIFICATIONS",
alias = "CRAFTEDIDENTIFICATIONS",
alias = "Crafted_Identifications",
alias = "Crafted_identifications",
alias = "CraftedIdentifications",
alias = "Craftedidentifications"
)]
pub crafted_ids: Option<Vec<IdentificationerCrafted>>,
pub crafted_damage: Option<DamageDeser>,
}
// 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", alias = "str", alias = "strength")]
pub strength: Option<i32>,
#[serde(alias = "Dex", alias = "dex", alias = "dexterity")]
pub dexterity: Option<i32>,
#[serde(alias = "Def", alias = "def", alias = "defense")]
pub defense: Option<i32>,
#[serde(alias = "Int", alias = "int", alias = "intelligence")]
pub intelligence: Option<i32>,
#[serde(alias = "Agi", alias = "agi", 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, Clone)]
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, Clone)]
pub struct Identificationer {
pub id: String,
pub base: i32,
pub roll: Option<u8>,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct IdentificationerCrafted {
pub name: String,
pub max_roll: i32,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct PowderFr {
pub r#type: char,
pub amount: Option<u8>,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct Shinyjson {
pub key: String,
pub value: i64,
}
#[derive(Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct DamageDeser {
pub attack_speed: AttackSpeed,
}
// 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", alias = "cgear", alias = "CGear")]
CraftedGear = 3,
#[serde(alias = "craftedconsu", alias = "cconsu", 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,25 +1,21 @@
#![allow(
clippy::single_match
)]
#![allow(clippy::single_match)]
#![allow(non_camel_case_types, non_snake_case)]
use idmangler_lib::{
encoding::encode_string,
types::{
Element, ItemType, TransformVersion, {RollType, Stat},
},
DataEncoder, EndData, IdentificationData, NameData, PowderData, RerollData, ShinyData,
StartData, TypeData,
};
use std::{collections::HashMap, env, fs, io, panic, path::PathBuf};
mod structures;
use crate::structures::*;
mod encode;
mod errorfr;
mod gearjson;
mod jsondl;
mod jsonstruct;
use crate::errorfr::Errorfr;
use crate::encode::FuncParams;
use crate::jsondl::*;
use crate::jsonstruct::*;
use crate::gearjson::gen_perfect;
use clap::Parser;
use idmangler_lib::{encoding::string::encode_string, types::EncodingVersion};
use reqwest::Url;
use std::{collections::HashMap, env, fs, io::Write, path::PathBuf};
#[derive(Parser, Debug, Clone)]
#[command(version, about, long_about = None, arg_required_else_help(true))]
@ -28,26 +24,37 @@ struct Args {
#[arg(short, long)]
config: Option<String>,
/// Enable debug mode
/// Enable debug mode (for now this just prints debug info)
#[arg(long, default_value_t = false)]
debug: bool,
/// Download jsons (for ease of use)
#[arg(short, long)]
download: Option<String>,
/// Function to generate perfect value items
#[arg(long)]
perfect: Option<String>,
}
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)?;
out.write_all(body.as_bytes()).map_err(|_| Errorfr::JsonDlReqFileWriteFail)?;
Ok(())
}
fn main() {
if let Err(e) = main_2() {
println!("{}", e)
}
}
fn main_2() -> Result<(), Errorfr> {
let args = Args::parse();
let mut executable_path = env::current_exe().unwrap();
PathBuf::pop(&mut executable_path);
@ -65,75 +72,107 @@ fn main() {
};
// 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
}
}
// main program everything starts here fr
let mut out: Vec<u8> = Vec::new();
// create necessary variables
let ver = TransformVersion::Version1;
// ENCODE: ALotOfStuff
// Also print any mapped errors
if let Err(e) = cook(
&mut out,
&debug_mode,
ver,
loaded_config,
loaded_idkeys,
loaded_shinystats,
) {
println!("{}", e);
};
// final string print
println!("{}", encode_string(&out));
}
Err(e) => println!("{}", e),
}
}
Err(e) => println!("{}", e),
let loaded_config: Jsonconfig = {
if let Some(t) = &args.config {
match load_jsonconfig(t) {
Ok(fr) => {
Ok(fr)
}
Err(e) => Err(e),
}
Err(e) => println!("{}", e),
}
else {
println!("no config path provided, fallback to empty.");
Ok(
Jsonconfig {
debug: Some(false),
item_type: ItemTypeDeser::Gear,
crafted_type: None,
name: None,
shiny: None,
ids: None,
powders: None,
rerolls: None,
crafted_durability: None,
crafted_requirements: None,
crafted_ids: None,
crafted_damage: None,
}
)
}
}?;
let loaded_idkeys = load_idkeys(executable_path)?;
let loaded_shinystats = load_shinystats(executable_path)?;
// check if perfect status and change name if so. otherwise blank yep
let mut namefr: String = "".to_string();
if let Some(t1) = args.perfect {
namefr = t1
}
// debug mode on if in the loaded config
if let Some(debugconfig) = loaded_config.debug {
if debugconfig {
debug_mode = true
}
}
}
// main program everything starts here fr
let mut out: Vec<u8> = Vec::new();
fn cook(
out: &mut Vec<u8>,
debug_mode: &bool,
ver: TransformVersion,
json_config: Jsonconfig,
idsmap: HashMap<String, u8>,
json_shiny: Vec<Shinystruct>,
) -> Result<(), Errorfr> {
let mut fr_params = FuncParams {
fr_out: out,
fr_debug_mode: debug_mode,
// create necessary variables
let ver = EncodingVersion::Version1;
let mut loaded_config_clone = loaded_config.clone();
let mut funcparamsfr: FuncParams = FuncParams {
fr_out: &mut out,
fr_debug_mode: &debug_mode,
fr_ver: ver,
};
// ENCODE: A Lot Of Stuff
// Also print any mapped errors
let cooking = cook(&mut funcparamsfr, &mut loaded_config_clone, loaded_idkeys, loaded_shinystats, namefr, executable_path);
if let Err(e) = cooking {
println!("{}", e); // print error if there is an error
} else {
// final string print if there is no error
println!("{}", cooking?)
}
Ok(())
}
fn cook(fr_params: &mut FuncParams, json_config: &mut Jsonconfig, idsmap: HashMap<String, u8>, json_shiny: Vec<Shinystruct>, namefr: String, executable_path: &str) -> Result<String, Errorfr> {
// ENCODE: StartData and TypeData, ALWAYS
encode_startdata(&mut fr_params);
encode_typedata(&mut fr_params, json_config.item_type);
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 let Some(real_crafted_type) = &json_config.crafted_type {
fr_params.encode_typedata_custom(real_crafted_type)?;
} else {
return Err(Errorfr::JsonNotFoundCraftedType);
}
}
_ => {}
}
// ENCODE: NameData, if ItemType is Gear, Tome, Charm
match json_config.item_type {
ItemTypeDeser::Gear | ItemTypeDeser::Tome | ItemTypeDeser::Charm => {
if let Some(real_name) = json_config.name {
encode_namedata(&mut fr_params, &real_name)
if namefr != *"" {
fr_params.encode_namedata(&namefr)?
}
else if let Some(real_name) = &json_config.name {
fr_params.encode_namedata(real_name)?
} else {
return Err(Errorfr::JsonNotFoundName);
}
}
_ => {}
@ -142,8 +181,38 @@ fn cook(
// ENCODE: IdentificationData
match json_config.item_type {
ItemTypeDeser::Gear | ItemTypeDeser::Tome | ItemTypeDeser::Charm => {
if let Some(real_ids) = json_config.ids {
encode_ids(&mut fr_params, real_ids, idsmap)
if namefr != *"" {
println!("Overriding IDs with perfect ones!");
let fr_gear_cache = load_gear_cache(executable_path)?;
let resultantvec = gen_perfect(&namefr, &fr_gear_cache)?;
fr_params.encode_iddata(&resultantvec, idsmap)?
}
else if let Some(real_ids) = &json_config.ids {
fr_params.encode_iddata(real_ids, idsmap)?
}
}
_ => {}
}
// ENCODE: DurabilityData (REQUIRED for CraftedGear)
match json_config.item_type {
ItemTypeDeser::CraftedGear => {
if let Some(real_dura) = &json_config.crafted_durability {
fr_params.encode_duradata(real_dura)?;
} else {
return Err(Errorfr::JsonNotFoundDura);
}
}
_ => {}
}
// ENCODE: RequirementsData if ItemType is CraftedGear, CraftedConsu
match json_config.item_type {
ItemTypeDeser::CraftedGear | ItemTypeDeser::CraftedConsu => {
if let Some(real_reqs) = json_config.crafted_requirements {
fr_params.encode_reqdata(real_reqs)?
} else {
return Err(Errorfr::JsonNotFoundReqs);
}
}
_ => {}
@ -152,8 +221,8 @@ fn cook(
// ENCODE: PowderData if ItemType is Gear, CraftedGear
match json_config.item_type {
ItemTypeDeser::Gear | ItemTypeDeser::CraftedGear => {
if let Some(real_powders) = json_config.powders {
encode_powder(&mut fr_params, real_powders)
if let Some(real_powders) = &json_config.powders {
fr_params.encode_powderdata(real_powders)?
}
}
_ => {}
@ -164,7 +233,7 @@ fn cook(
ItemTypeDeser::Gear | ItemTypeDeser::Tome | ItemTypeDeser::Charm => {
if let Some(rerollcount) = json_config.rerolls {
// rerolldata
encode_reroll(&mut fr_params, rerollcount)
fr_params.encode_rerolldata(rerollcount)?
}
}
_ => {}
@ -173,189 +242,29 @@ fn cook(
// ENCODE: ShinyData if ItemType is Gear
match json_config.item_type {
ItemTypeDeser::Gear => {
if let Some(shiny) = json_config.shiny {
encode_shiny(&mut fr_params, shiny, json_shiny)
if let Some(shiny) = &json_config.shiny {
fr_params.encode_shinydata(shiny, &json_shiny)?
}
}
_ => {}
}
// ENCODE: EndData, ALWAYS
encode_enddata(&mut fr_params);
fr_params.encode_enddata()?;
Ok(())
}
let mut final_string: String = encode_string(fr_params.fr_out);
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)
}
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)
}
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)
}
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)
}
}
}
fn encode_startdata(general_params: &mut FuncParams) {
// ENCODE: StartData
StartData(general_params.fr_ver)
.encode(general_params.fr_ver, general_params.fr_out)
.unwrap();
}
fn encode_typedata(general_params: &mut FuncParams, item_type_deser: ItemTypeDeser) {
// ENCODE: TypeData
TypeData(ItemType::from(item_type_deser))
.encode(general_params.fr_ver, general_params.fr_out)
.unwrap();
}
fn encode_namedata(general_params: &mut FuncParams, real_name: &str) {
// ENCODE: NameData
NameData(real_name.trim().to_string())
.encode(general_params.fr_ver, general_params.fr_out)
.unwrap();
}
fn encode_ids(
general_params: &mut FuncParams,
real_ids: Vec<Identificationer>,
idsmap: HashMap<String, u8>,
) {
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 => 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)
}
// ENCODE: IdentificationsData
IdentificationData {
identifications: idvec,
extended_encoding: true,
}
.encode(general_params.fr_ver, general_params.fr_out)
.unwrap();
}
fn encode_powder(general_params: &mut FuncParams, real_powders: Vec<Powder>) {
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,
_ => Element::Thunder,
};
if *general_params.fr_debug_mode {
dbg!(eletype);
}
powdervec.push(Some((eletype, 6))); // 6 is the tier. Wynntils ONLY really uses tier 6 so theres no point keeping others.
}
}
if *general_params.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(general_params.fr_ver, general_params.fr_out)
.unwrap();
}
fn encode_reroll(general_params: &mut FuncParams, rerollcount: u8) {
if rerollcount != 0 {
// ENCODE: RerollData if applicable
RerollData(rerollcount)
.encode(general_params.fr_ver, general_params.fr_out)
.unwrap();
if *general_params.fr_debug_mode {
dbg!(rerollcount);
}
}
}
fn encode_shiny(general_params: &mut FuncParams, shiny: Shinyjson, json_shiny: Vec<Shinystruct>) {
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 *general_params.fr_debug_mode {
dbg!(&shiny.key);
// add NameAfter. not actually an encode.
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);
}
}
_ => {}
}
if *general_params.fr_debug_mode {
dbg!(&realshinykey);
dbg!(&shinyvalue);
}
// ENCODE: ShinyData (if applicable)
ShinyData {
id: realshinykey,
val: shinyvalue,
}
.encode(general_params.fr_ver, general_params.fr_out)
.unwrap();
}
fn encode_enddata(general_params: &mut FuncParams) {
// ENCODE: EndData
EndData
.encode(general_params.fr_ver, general_params.fr_out)
.unwrap();
}
Ok(final_string)
}

View file

@ -1,99 +0,0 @@
use idmangler_lib::types::{ItemType, TransformVersion};
use serde::Deserialize;
// structs for the json parsing
#[derive(Deserialize)]
pub struct Powder {
pub r#type: char,
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 item_type: ItemTypeDeser,
pub name: Option<String>,
pub shiny: Option<Shinyjson>,
pub ids: Option<Vec<Identificationer>>,
pub powders: Option<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,
}
// struct for general parameters for most encode functions
pub struct FuncParams<'a> {
pub fr_out: &'a mut Vec<u8>,
pub fr_debug_mode: &'a bool,
pub fr_ver: TransformVersion,
}
// 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 {
Gear = 0,
Tome = 1,
Charm = 2,
CraftedGear = 3,
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,
}
}
}
// 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
}
}
}
}