├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── config.toml ├── lib ├── LICENSE-SpecialSource.md ├── LICENSE-Vineflower.md ├── SpecialSource-1.11.4-shaded.jar └── vineflower-1.10.1+patched.jar └── src ├── config.rs ├── decomp.rs ├── download.rs ├── download ├── authlib.rs └── mojang.rs ├── git.rs ├── main.rs ├── sources.rs └── sources ├── authlib.rs └── mojmap.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /tmp 3 | /repo 4 | /deploy.sh 5 | 6 | /lockfile 7 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adler" 7 | version = "1.0.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 10 | 11 | [[package]] 12 | name = "android-tzdata" 13 | version = "0.1.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 16 | 17 | [[package]] 18 | name = "android_system_properties" 19 | version = "0.1.5" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 22 | dependencies = [ 23 | "libc", 24 | ] 25 | 26 | [[package]] 27 | name = "autocfg" 28 | version = "1.2.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" 31 | 32 | [[package]] 33 | name = "base64" 34 | version = "0.21.7" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 37 | 38 | [[package]] 39 | name = "bumpalo" 40 | version = "3.16.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 43 | 44 | [[package]] 45 | name = "cc" 46 | version = "1.0.91" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "1fd97381a8cc6493395a5afc4c691c1084b3768db713b73aa215217aa245d153" 49 | 50 | [[package]] 51 | name = "cfg-if" 52 | version = "1.0.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 55 | 56 | [[package]] 57 | name = "chrono" 58 | version = "0.4.37" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" 61 | dependencies = [ 62 | "android-tzdata", 63 | "iana-time-zone", 64 | "js-sys", 65 | "num-traits", 66 | "serde", 67 | "wasm-bindgen", 68 | "windows-targets", 69 | ] 70 | 71 | [[package]] 72 | name = "core-foundation-sys" 73 | version = "0.8.6" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" 76 | 77 | [[package]] 78 | name = "crc32fast" 79 | version = "1.4.0" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" 82 | dependencies = [ 83 | "cfg-if", 84 | ] 85 | 86 | [[package]] 87 | name = "decompiled_minecraft_gen" 88 | version = "0.1.0" 89 | dependencies = [ 90 | "chrono", 91 | "lockfile", 92 | "serde", 93 | "serde_json", 94 | "toml", 95 | "ureq", 96 | ] 97 | 98 | [[package]] 99 | name = "equivalent" 100 | version = "1.0.1" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 103 | 104 | [[package]] 105 | name = "flate2" 106 | version = "1.0.28" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" 109 | dependencies = [ 110 | "crc32fast", 111 | "miniz_oxide", 112 | ] 113 | 114 | [[package]] 115 | name = "form_urlencoded" 116 | version = "1.2.1" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 119 | dependencies = [ 120 | "percent-encoding", 121 | ] 122 | 123 | [[package]] 124 | name = "getrandom" 125 | version = "0.2.13" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "a06fddc2749e0528d2813f95e050e87e52c8cbbae56223b9babf73b3e53b0cc6" 128 | dependencies = [ 129 | "cfg-if", 130 | "libc", 131 | "wasi", 132 | ] 133 | 134 | [[package]] 135 | name = "hashbrown" 136 | version = "0.14.3" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" 139 | 140 | [[package]] 141 | name = "iana-time-zone" 142 | version = "0.1.60" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" 145 | dependencies = [ 146 | "android_system_properties", 147 | "core-foundation-sys", 148 | "iana-time-zone-haiku", 149 | "js-sys", 150 | "wasm-bindgen", 151 | "windows-core", 152 | ] 153 | 154 | [[package]] 155 | name = "iana-time-zone-haiku" 156 | version = "0.1.2" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 159 | dependencies = [ 160 | "cc", 161 | ] 162 | 163 | [[package]] 164 | name = "idna" 165 | version = "0.5.0" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 168 | dependencies = [ 169 | "unicode-bidi", 170 | "unicode-normalization", 171 | ] 172 | 173 | [[package]] 174 | name = "indexmap" 175 | version = "2.2.6" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 178 | dependencies = [ 179 | "equivalent", 180 | "hashbrown", 181 | ] 182 | 183 | [[package]] 184 | name = "itoa" 185 | version = "1.0.11" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 188 | 189 | [[package]] 190 | name = "js-sys" 191 | version = "0.3.69" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" 194 | dependencies = [ 195 | "wasm-bindgen", 196 | ] 197 | 198 | [[package]] 199 | name = "libc" 200 | version = "0.2.161" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" 203 | 204 | [[package]] 205 | name = "lockfile" 206 | version = "0.4.0" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "5be1cf190319c74ba3e45923624626ae2e43fe42ad7e60ff38ded81044c37630" 209 | 210 | [[package]] 211 | name = "log" 212 | version = "0.4.21" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 215 | 216 | [[package]] 217 | name = "memchr" 218 | version = "2.7.2" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 221 | 222 | [[package]] 223 | name = "miniz_oxide" 224 | version = "0.7.2" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 227 | dependencies = [ 228 | "adler", 229 | ] 230 | 231 | [[package]] 232 | name = "num-traits" 233 | version = "0.2.18" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" 236 | dependencies = [ 237 | "autocfg", 238 | ] 239 | 240 | [[package]] 241 | name = "once_cell" 242 | version = "1.19.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 245 | 246 | [[package]] 247 | name = "percent-encoding" 248 | version = "2.3.1" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 251 | 252 | [[package]] 253 | name = "proc-macro2" 254 | version = "1.0.79" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 257 | dependencies = [ 258 | "unicode-ident", 259 | ] 260 | 261 | [[package]] 262 | name = "quote" 263 | version = "1.0.35" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 266 | dependencies = [ 267 | "proc-macro2", 268 | ] 269 | 270 | [[package]] 271 | name = "ring" 272 | version = "0.17.8" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 275 | dependencies = [ 276 | "cc", 277 | "cfg-if", 278 | "getrandom", 279 | "libc", 280 | "spin", 281 | "untrusted", 282 | "windows-sys", 283 | ] 284 | 285 | [[package]] 286 | name = "rustls" 287 | version = "0.22.3" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" 290 | dependencies = [ 291 | "log", 292 | "ring", 293 | "rustls-pki-types", 294 | "rustls-webpki", 295 | "subtle", 296 | "zeroize", 297 | ] 298 | 299 | [[package]] 300 | name = "rustls-pki-types" 301 | version = "1.4.1" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" 304 | 305 | [[package]] 306 | name = "rustls-webpki" 307 | version = "0.102.2" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" 310 | dependencies = [ 311 | "ring", 312 | "rustls-pki-types", 313 | "untrusted", 314 | ] 315 | 316 | [[package]] 317 | name = "ryu" 318 | version = "1.0.17" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" 321 | 322 | [[package]] 323 | name = "serde" 324 | version = "1.0.197" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" 327 | dependencies = [ 328 | "serde_derive", 329 | ] 330 | 331 | [[package]] 332 | name = "serde_derive" 333 | version = "1.0.197" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" 336 | dependencies = [ 337 | "proc-macro2", 338 | "quote", 339 | "syn", 340 | ] 341 | 342 | [[package]] 343 | name = "serde_json" 344 | version = "1.0.115" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" 347 | dependencies = [ 348 | "itoa", 349 | "ryu", 350 | "serde", 351 | ] 352 | 353 | [[package]] 354 | name = "serde_spanned" 355 | version = "0.6.5" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" 358 | dependencies = [ 359 | "serde", 360 | ] 361 | 362 | [[package]] 363 | name = "spin" 364 | version = "0.9.8" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 367 | 368 | [[package]] 369 | name = "subtle" 370 | version = "2.5.0" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" 373 | 374 | [[package]] 375 | name = "syn" 376 | version = "2.0.58" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" 379 | dependencies = [ 380 | "proc-macro2", 381 | "quote", 382 | "unicode-ident", 383 | ] 384 | 385 | [[package]] 386 | name = "tinyvec" 387 | version = "1.6.0" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 390 | dependencies = [ 391 | "tinyvec_macros", 392 | ] 393 | 394 | [[package]] 395 | name = "tinyvec_macros" 396 | version = "0.1.1" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 399 | 400 | [[package]] 401 | name = "toml" 402 | version = "0.8.12" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" 405 | dependencies = [ 406 | "serde", 407 | "serde_spanned", 408 | "toml_datetime", 409 | "toml_edit", 410 | ] 411 | 412 | [[package]] 413 | name = "toml_datetime" 414 | version = "0.6.5" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" 417 | dependencies = [ 418 | "serde", 419 | ] 420 | 421 | [[package]] 422 | name = "toml_edit" 423 | version = "0.22.9" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" 426 | dependencies = [ 427 | "indexmap", 428 | "serde", 429 | "serde_spanned", 430 | "toml_datetime", 431 | "winnow", 432 | ] 433 | 434 | [[package]] 435 | name = "unicode-bidi" 436 | version = "0.3.15" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 439 | 440 | [[package]] 441 | name = "unicode-ident" 442 | version = "1.0.12" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 445 | 446 | [[package]] 447 | name = "unicode-normalization" 448 | version = "0.1.23" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" 451 | dependencies = [ 452 | "tinyvec", 453 | ] 454 | 455 | [[package]] 456 | name = "untrusted" 457 | version = "0.9.0" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 460 | 461 | [[package]] 462 | name = "ureq" 463 | version = "2.9.6" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "11f214ce18d8b2cbe84ed3aa6486ed3f5b285cf8d8fbdbce9f3f767a724adc35" 466 | dependencies = [ 467 | "base64", 468 | "flate2", 469 | "log", 470 | "once_cell", 471 | "rustls", 472 | "rustls-pki-types", 473 | "rustls-webpki", 474 | "url", 475 | "webpki-roots", 476 | ] 477 | 478 | [[package]] 479 | name = "url" 480 | version = "2.5.0" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" 483 | dependencies = [ 484 | "form_urlencoded", 485 | "idna", 486 | "percent-encoding", 487 | ] 488 | 489 | [[package]] 490 | name = "wasi" 491 | version = "0.11.0+wasi-snapshot-preview1" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 494 | 495 | [[package]] 496 | name = "wasm-bindgen" 497 | version = "0.2.92" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" 500 | dependencies = [ 501 | "cfg-if", 502 | "wasm-bindgen-macro", 503 | ] 504 | 505 | [[package]] 506 | name = "wasm-bindgen-backend" 507 | version = "0.2.92" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" 510 | dependencies = [ 511 | "bumpalo", 512 | "log", 513 | "once_cell", 514 | "proc-macro2", 515 | "quote", 516 | "syn", 517 | "wasm-bindgen-shared", 518 | ] 519 | 520 | [[package]] 521 | name = "wasm-bindgen-macro" 522 | version = "0.2.92" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" 525 | dependencies = [ 526 | "quote", 527 | "wasm-bindgen-macro-support", 528 | ] 529 | 530 | [[package]] 531 | name = "wasm-bindgen-macro-support" 532 | version = "0.2.92" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" 535 | dependencies = [ 536 | "proc-macro2", 537 | "quote", 538 | "syn", 539 | "wasm-bindgen-backend", 540 | "wasm-bindgen-shared", 541 | ] 542 | 543 | [[package]] 544 | name = "wasm-bindgen-shared" 545 | version = "0.2.92" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" 548 | 549 | [[package]] 550 | name = "webpki-roots" 551 | version = "0.26.1" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" 554 | dependencies = [ 555 | "rustls-pki-types", 556 | ] 557 | 558 | [[package]] 559 | name = "windows-core" 560 | version = "0.52.0" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 563 | dependencies = [ 564 | "windows-targets", 565 | ] 566 | 567 | [[package]] 568 | name = "windows-sys" 569 | version = "0.52.0" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 572 | dependencies = [ 573 | "windows-targets", 574 | ] 575 | 576 | [[package]] 577 | name = "windows-targets" 578 | version = "0.52.6" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 581 | dependencies = [ 582 | "windows_aarch64_gnullvm", 583 | "windows_aarch64_msvc", 584 | "windows_i686_gnu", 585 | "windows_i686_gnullvm", 586 | "windows_i686_msvc", 587 | "windows_x86_64_gnu", 588 | "windows_x86_64_gnullvm", 589 | "windows_x86_64_msvc", 590 | ] 591 | 592 | [[package]] 593 | name = "windows_aarch64_gnullvm" 594 | version = "0.52.6" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 597 | 598 | [[package]] 599 | name = "windows_aarch64_msvc" 600 | version = "0.52.6" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 603 | 604 | [[package]] 605 | name = "windows_i686_gnu" 606 | version = "0.52.6" 607 | source = "registry+https://github.com/rust-lang/crates.io-index" 608 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 609 | 610 | [[package]] 611 | name = "windows_i686_gnullvm" 612 | version = "0.52.6" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 615 | 616 | [[package]] 617 | name = "windows_i686_msvc" 618 | version = "0.52.6" 619 | source = "registry+https://github.com/rust-lang/crates.io-index" 620 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 621 | 622 | [[package]] 623 | name = "windows_x86_64_gnu" 624 | version = "0.52.6" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 627 | 628 | [[package]] 629 | name = "windows_x86_64_gnullvm" 630 | version = "0.52.6" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 633 | 634 | [[package]] 635 | name = "windows_x86_64_msvc" 636 | version = "0.52.6" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 639 | 640 | [[package]] 641 | name = "winnow" 642 | version = "0.6.5" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" 645 | dependencies = [ 646 | "memchr", 647 | ] 648 | 649 | [[package]] 650 | name = "zeroize" 651 | version = "1.7.0" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" 654 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "decompiled_minecraft_gen" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | chrono = { version = "0.4.37", features = ["serde"] } 8 | lockfile = "0.4.0" 9 | serde = { version = "1.0.197", features = ["derive"] } 10 | serde_json = "1.0.115" 11 | toml = { version = "0.8.12", default-features = false, features = ["parse"] } 12 | ureq = "2.9.6" 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # decompiled-minecraft gen 2 | 3 | Generate a Git repo with commits and branches for the decompiled source code of different Minecraft versions and mappings. 4 | 5 | Currently the only branches generated are mojmap and authlib. 6 | 7 | ## Usage 8 | 9 | decompiled-minecraft-gen will create the full repository of decompiled Minecraft versions at `./repo` on run (with `cargo r -r`). 10 | The first time you run it, it'll take a few hours. 11 | 12 | If the repository already exists at that location, it'll update it to the latest snapshot (or if it's up-to-date, it won't do anything). 13 | It'll run `git push --all` after it updates. 14 | 15 | Having a recent version of Java installed is required. 16 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | java_args = ["-Xmx4G", "-Xms1G"] 2 | vineflower_args = [] 3 | -------------------------------------------------------------------------------- /lib/LICENSE-SpecialSource.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, md_5. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | The name of the author may not be used to endorse or promote products derived 14 | from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /lib/LICENSE-Vineflower.md: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /lib/SpecialSource-1.11.4-shaded.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mat-1/decompiled_minecraft_gen/8a47b6567dc82120b4a5258370ccfed207d9a4be/lib/SpecialSource-1.11.4-shaded.jar -------------------------------------------------------------------------------- /lib/vineflower-1.10.1+patched.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mat-1/decompiled_minecraft_gen/8a47b6567dc82120b4a5258370ccfed207d9a4be/lib/vineflower-1.10.1+patched.jar -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | #[derive(Deserialize)] 4 | pub struct Config { 5 | pub java_args: Vec, 6 | #[serde(default)] 7 | pub vineflower_args: Vec, 8 | } 9 | 10 | impl Config { 11 | pub fn load() -> Self { 12 | let config_str = std::fs::read_to_string("config.toml").expect("couldn't read config.toml"); 13 | toml::from_str(&config_str).expect("couldn't parse config.toml") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/decomp.rs: -------------------------------------------------------------------------------- 1 | use std::{fs, io, path::Path, process::Command}; 2 | 3 | use crate::config::Config; 4 | 5 | const VINEFLOWER_PATH: &str = "./lib/vineflower-1.10.1+patched.jar"; 6 | // if you're updating it, download from https://repo1.maven.org/maven2/net/md-5/SpecialSource/ 7 | // make sure to use the -shaded jar! otherwise it won't work 8 | const SPECIALSOURCE_PATH: &str = "./lib/SpecialSource-1.11.4-shaded.jar"; 9 | 10 | pub fn decompile_jar(config: &Config, jar_path: &Path, out_path: &Path) { 11 | for attempt_number in 0..3 { 12 | // make sure we don't delete / 13 | assert!( 14 | out_path.parent().is_some(), 15 | "decompile out path ({out_path:?}) can't be the root" 16 | ); 17 | 18 | if !out_path 19 | .try_exists() 20 | .expect("out path directory ({out_path:?}) must be readable") 21 | { 22 | fs::create_dir_all(out_path).expect("couldn't create out"); 23 | } 24 | let entries_in_out_path = out_path 25 | .read_dir() 26 | .expect("out path must be readable") 27 | .collect::, _>>() 28 | .unwrap(); 29 | // if it's not empty then make sure there's a `net` dir here JUST to be safe 30 | if !entries_in_out_path.is_empty() 31 | && !entries_in_out_path.iter().any(|e| e.file_name() == "net") 32 | { 33 | panic!("tried to decompile into a non-empty directory that doesn't look like a previous decompilation output (no 'net' directory). delete it yourself if you're sure it's fine.") 34 | } 35 | 36 | println!("deleting everything in {out_path:?}"); 37 | for entry in entries_in_out_path { 38 | if entry.path().is_dir() { 39 | if let Err(e) = fs::remove_dir_all(entry.path()) { 40 | println!("couldn't remove directory {entry:?}! {e}"); 41 | } 42 | } else if let Err(e) = fs::remove_file(entry.path()) { 43 | println!("couldn't remove file {entry:?}! {e}"); 44 | } 45 | } 46 | 47 | // make sure it's empty 48 | assert!( 49 | out_path.read_dir().unwrap().next().is_none(), 50 | "out_path ({out_path:?}) should be empty" 51 | ); 52 | 53 | println!("Decompiling {jar_path:?}"); 54 | Command::new("java") 55 | .args(config.java_args.iter().map(String::as_str)) 56 | .arg("-jar") 57 | .arg(VINEFLOWER_PATH) 58 | .args(config.vineflower_args.iter().map(String::as_str)) 59 | .arg(jar_path.to_str().unwrap()) 60 | .arg(out_path.to_str().unwrap()) 61 | .stdout(io::stdout()) 62 | .stderr(io::stderr()) 63 | .output() 64 | .expect("failed to execute vineflower"); 65 | println!("Finished decompiling"); 66 | 67 | if check_decompiled_successfully(out_path) { 68 | println!( 69 | "Decompiled successfully after {} attempt{}", 70 | attempt_number + 1, 71 | if attempt_number == 0 { "" } else { "s" } 72 | ); 73 | return; 74 | } else { 75 | println!("Decompilation failed, retrying :("); 76 | } 77 | } 78 | 79 | panic!("Decompilation failed!"); 80 | } 81 | 82 | fn check_decompiled_successfully(out_path: &Path) -> bool { 83 | // recurse over the out_path and check if there's any java file 84 | 85 | for entry in out_path.read_dir().expect("out path must be readable") { 86 | let entry = entry.expect("entry must be readable"); 87 | if entry.path().is_dir() { 88 | if check_decompiled_successfully(&entry.path()) { 89 | return true; 90 | } 91 | } else if entry.path().extension().unwrap_or_default() == "java" { 92 | return true; 93 | } 94 | } 95 | 96 | false 97 | } 98 | 99 | pub fn remap_jar_with_srg_mappings( 100 | config: &Config, 101 | jar_input_path: &Path, 102 | jar_output_path: &Path, 103 | mappings_path: &Path, 104 | ) { 105 | println!("Remapping {jar_input_path:?} with mappings {mappings_path:?}"); 106 | Command::new("java") 107 | .args(config.java_args.iter().map(String::as_str)) 108 | .args([ 109 | "-jar", 110 | SPECIALSOURCE_PATH, 111 | "--in-jar", 112 | jar_input_path.to_str().unwrap(), 113 | "--out-jar", 114 | jar_output_path.to_str().unwrap(), 115 | "--srg-in", 116 | mappings_path.to_str().unwrap(), 117 | // remove the local variable table so their names are generated by our decompiler 118 | "--kill-lvt", 119 | ]) 120 | // .stdout(io::stdout()) 121 | // .stderr(io::stderr()) 122 | .output() 123 | .expect("failed to execute specialsource"); 124 | } 125 | -------------------------------------------------------------------------------- /src/download.rs: -------------------------------------------------------------------------------- 1 | use std::{fs, path::Path}; 2 | 3 | pub mod authlib; 4 | pub mod mojang; 5 | 6 | pub struct DownloadResult {} 7 | 8 | pub fn download_file_from_url_to_path(url: &str, path: &Path) -> Vec { 9 | println!("downloading {url} to {path:?}"); 10 | let res = ureq::get(url) 11 | .call() 12 | .unwrap_or_else(|_| panic!("failed to download {url}")); 13 | let mut reader = res.into_reader(); 14 | let mut buf = Vec::new(); 15 | reader 16 | .read_to_end(&mut buf) 17 | .unwrap_or_else(|_| panic!("failed to read {url}")); 18 | let _ = fs::create_dir_all(path.parent().expect("path should have a parent")); 19 | fs::write(path, buf.clone()).unwrap_or_else(|_| panic!("failed to write to {path:?}")); 20 | buf 21 | } 22 | 23 | pub fn get_file_from_url_or_cache(url: &str, path: &Path) -> Vec { 24 | if let Ok(buf) = fs::read(path) { 25 | buf 26 | } else { 27 | download_file_from_url_to_path(url, path) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/download/authlib.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use crate::download; 4 | 5 | pub fn get_authlib_version_for_minecraft_version(mc_id: &str) -> String { 6 | let version_data = download::mojang::get_version_data(mc_id); 7 | let authlib = &version_data 8 | .libraries 9 | .into_iter() 10 | .find(|l| l.name.starts_with("com.mojang:authlib:")) 11 | .expect("version has no authlib jar"); 12 | let authlib_version = authlib.name.strip_prefix("com.mojang:authlib:").unwrap(); 13 | authlib_version.to_owned() 14 | } 15 | 16 | pub fn get_version_jar(id: &str) -> PathBuf { 17 | let jar_url = 18 | format!("https://libraries.minecraft.net/com/mojang/authlib/{id}/authlib-{id}.jar"); 19 | let jar_path = PathBuf::from(format!("tmp/authlib/{id}.jar")); 20 | download::get_file_from_url_or_cache(&jar_url, &jar_path); 21 | jar_path 22 | } 23 | -------------------------------------------------------------------------------- /src/download/mojang.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | collections::HashMap, 3 | path::{Path, PathBuf}, 4 | }; 5 | 6 | use chrono::{DateTime, Utc}; 7 | use serde::Deserialize; 8 | 9 | use super::{download_file_from_url_to_path, get_file_from_url_or_cache}; 10 | 11 | const VERSION_MANIFEST_URL: &str = "https://piston-meta.mojang.com/mc/game/version_manifest.json"; 12 | const VERSION_MANIFEST_SAVE_PATH: &str = "tmp/mojang/version_manifest.json"; 13 | 14 | #[derive(Deserialize, Debug)] 15 | pub struct VersionManifest { 16 | pub latest: Latest, 17 | pub versions: Vec, 18 | } 19 | 20 | #[derive(Deserialize, Debug)] 21 | pub struct Latest { 22 | pub release: String, 23 | pub snapshot: String, 24 | } 25 | 26 | #[derive(Deserialize, Debug)] 27 | #[serde(rename_all = "camelCase")] 28 | pub struct ManifestVersion { 29 | pub id: String, 30 | #[serde(rename = "type")] 31 | pub kind: String, 32 | pub url: String, 33 | pub time: DateTime, 34 | pub release_time: DateTime, 35 | } 36 | 37 | pub fn get_version_manifest() -> VersionManifest { 38 | let version_manifest = 39 | get_file_from_url_or_cache(VERSION_MANIFEST_URL, Path::new(VERSION_MANIFEST_SAVE_PATH)); 40 | serde_json::from_slice::(&version_manifest) 41 | .expect("failed to parse version_manifest.json") 42 | } 43 | 44 | pub fn download_version_manifest() -> VersionManifest { 45 | let version_manifest = 46 | download_file_from_url_to_path(VERSION_MANIFEST_URL, Path::new(VERSION_MANIFEST_SAVE_PATH)); 47 | serde_json::from_slice::(&version_manifest) 48 | .expect("failed to parse version_manifest.json") 49 | } 50 | 51 | #[derive(Deserialize, Debug)] 52 | #[serde(rename_all = "camelCase")] 53 | pub struct VersionData { 54 | pub downloads: HashMap, 55 | pub id: String, 56 | pub java_version: JavaVersion, 57 | pub libraries: Vec, 58 | pub release_time: String, 59 | pub time: String, 60 | #[serde(rename = "type")] 61 | pub kind: String, 62 | } 63 | 64 | #[derive(Deserialize, Debug)] 65 | #[serde(rename_all = "camelCase")] 66 | pub struct VersionDownload { 67 | pub sha1: String, 68 | pub size: u64, 69 | pub url: String, 70 | } 71 | 72 | #[derive(Deserialize, Debug)] 73 | #[serde(rename_all = "camelCase")] 74 | pub struct JavaVersion { 75 | pub component: String, 76 | pub major_version: u32, 77 | } 78 | 79 | #[derive(Deserialize, Debug)] 80 | #[serde(rename_all = "camelCase")] 81 | pub struct Library { 82 | pub downloads: LibraryDownloads, 83 | pub name: String, 84 | } 85 | 86 | #[derive(Deserialize, Debug)] 87 | #[serde(rename_all = "camelCase")] 88 | pub struct LibraryDownloads { 89 | pub artifact: Option, 90 | } 91 | 92 | #[derive(Deserialize, Debug)] 93 | #[serde(rename_all = "camelCase")] 94 | pub struct LibraryArtifact { 95 | pub path: String, 96 | pub sha1: String, 97 | pub size: u64, 98 | pub url: String, 99 | } 100 | 101 | pub fn get_version_data(id: &str) -> VersionData { 102 | let manifest = get_version_manifest(); 103 | let manifest_version = manifest 104 | .versions 105 | .iter() 106 | .find(|v| v.id == id) 107 | .unwrap_or_else(|| panic!("couldn't find version {id} in version_manifest.json")); 108 | let version_data = get_file_from_url_or_cache( 109 | &manifest_version.url, 110 | Path::new(&format!("tmp/mojang/{id}.json")), 111 | ); 112 | serde_json::from_slice::(&version_data) 113 | .unwrap_or_else(|e| panic!("failed to parse version data for {id}: {e}")) 114 | } 115 | 116 | pub fn get_version_jar(id: &str) -> PathBuf { 117 | let version_data = get_version_data(id); 118 | let jar_url = &version_data 119 | .downloads 120 | .get("client") 121 | .expect("version has no jar") 122 | .url; 123 | let jar_path = PathBuf::from(format!("tmp/mojang/{id}.jar")); 124 | get_file_from_url_or_cache(jar_url, &jar_path); 125 | jar_path 126 | } 127 | 128 | pub fn get_version_mappings(id: &str) -> Option { 129 | let version_data = get_version_data(id); 130 | let jar_url = &version_data.downloads.get("client_mappings")?.url; 131 | let jar_path = PathBuf::from(format!("tmp/mojang/{id}-mappings.txt")); 132 | get_file_from_url_or_cache(jar_url, &jar_path); 133 | Some(jar_path) 134 | } 135 | -------------------------------------------------------------------------------- /src/git.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs, 3 | path::{Path, PathBuf}, 4 | process::Command, 5 | }; 6 | 7 | use chrono::{DateTime, Utc}; 8 | 9 | use crate::REPO_PATH; 10 | 11 | pub const DEFAULT_BRANCH_NAME: &str = "mojmap"; 12 | 13 | fn repo_path() -> PathBuf { 14 | let repo_path = Path::new(REPO_PATH); 15 | fs::create_dir_all(repo_path) 16 | .unwrap_or_else(|_| panic!("repo at {repo_path:?} couldn't be created")); 17 | repo_path 18 | .canonicalize() 19 | .unwrap_or_else(|_| panic!("repo path {repo_path:?} is invalid")) 20 | } 21 | 22 | pub fn ensure_repo_created() { 23 | Command::new("git") 24 | .args(["init", "--initial-branch", DEFAULT_BRANCH_NAME]) 25 | .current_dir(repo_path()) 26 | .output() 27 | .unwrap(); 28 | } 29 | 30 | pub fn push() { 31 | Command::new("git") 32 | .args(["push", "--all"]) 33 | .current_dir(repo_path()) 34 | .output() 35 | .unwrap(); 36 | } 37 | 38 | pub fn checkout_branch(name: &str) { 39 | Command::new("git") 40 | .args(["checkout", "--orphan", name]) 41 | .current_dir(repo_path()) 42 | .output() 43 | .unwrap(); 44 | // --orphan fails if the branch already exists, so run checkout again without --orphan 45 | Command::new("git") 46 | .args(["checkout", name]) 47 | .current_dir(repo_path()) 48 | .output() 49 | .unwrap(); 50 | } 51 | pub fn commit(message: &str, author_name: &str, author_email: &str, timestamp: DateTime) { 52 | Command::new("git") 53 | .args(["add", "."]) 54 | .current_dir(repo_path()) 55 | .output() 56 | .unwrap(); 57 | Command::new("git") 58 | .args(["commit", "--message", message]) 59 | .current_dir(repo_path()) 60 | .env("GIT_AUTHOR_DATE", ×tamp.to_rfc3339()) 61 | .env("GIT_COMMITTER_DATE", ×tamp.to_rfc3339()) 62 | .env("GIT_AUTHOR_NAME", author_name) 63 | .env("GIT_AUTHOR_EMAIL", author_email) 64 | .env("GIT_COMMITTER_NAME", author_name) 65 | .env("GIT_COMMITTER_EMAIL", author_email) 66 | .output() 67 | .unwrap(); 68 | } 69 | 70 | pub fn commit_messages() -> Vec { 71 | // git rev-list --all --oneline 72 | let output = Command::new("git") 73 | .args(["rev-list", "--oneline", "HEAD"]) 74 | .current_dir(repo_path()) 75 | .output() 76 | .unwrap(); 77 | let mut messages = Vec::new(); 78 | for line in String::from_utf8(output.stdout).unwrap().lines() { 79 | let message = line.split_once(' ').unwrap().1; 80 | messages.push(message.to_string()); 81 | } 82 | messages 83 | } 84 | 85 | pub fn move_decomp_output_into_repo(out_path: &Path, exclude_paths: &[&str]) { 86 | // clear repo first 87 | let repo_path = repo_path(); 88 | let entries_in_repo_path = repo_path 89 | .read_dir() 90 | .unwrap() 91 | .collect::, _>>() 92 | .unwrap(); 93 | if !entries_in_repo_path.iter().any(|e| e.file_name() == ".git") { 94 | panic!("tried to copy files into a directory without a .git!") 95 | } 96 | 97 | println!("deleting everything in {repo_path:?} (except the .git)"); 98 | for entry in entries_in_repo_path { 99 | if entry.file_name() == ".git" { 100 | continue; 101 | }; 102 | if entry.path().is_dir() { 103 | if let Err(e) = fs::remove_dir_all(entry.path()) { 104 | println!("couldn't remove directory {entry:?}! {e}"); 105 | } 106 | } else if let Err(e) = fs::remove_file(entry.path()) { 107 | println!("couldn't remove file {entry:?}! {e}"); 108 | } 109 | } 110 | 111 | println!("copying stuff from {out_path:?} to {repo_path:?}"); 112 | // copy everything from tmp/out except assets and data 113 | for path_name_to_delete in exclude_paths { 114 | let mut path_to_delete = out_path.to_owned(); 115 | path_to_delete.push(path_name_to_delete); 116 | let _ = fs::remove_dir_all(path_to_delete); 117 | } 118 | for entry in out_path.read_dir().unwrap() { 119 | let entry = entry.unwrap(); 120 | let mut new_path = PathBuf::from(REPO_PATH); 121 | new_path.push(entry.path().file_name().unwrap()); 122 | fs::rename(entry.path(), new_path).unwrap(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::path::{self, Path}; 2 | 3 | use config::Config; 4 | 5 | mod config; 6 | pub mod decomp; 7 | pub mod download; 8 | pub mod git; 9 | mod sources; 10 | 11 | const REDOWNLOAD_MANIFEST: bool = !cfg!(debug_assertions); 12 | 13 | pub const REPO_PATH: &str = "repo"; 14 | pub const LOCKFILE_PATH: &str = "lockfile"; 15 | 16 | fn main() { 17 | let lockfile_path = path::absolute(Path::new(LOCKFILE_PATH)).unwrap(); 18 | let _lock = match lockfile::Lockfile::create(&lockfile_path) { 19 | Ok(lock) => lock, 20 | Err(err) => match err { 21 | lockfile::Error::Io(error) => panic!("Failed to create lockfile: {}", error), 22 | lockfile::Error::LockTaken => panic!("Another instance of decompiled_minecraft_gen is already running (lockfile exists at {})", lockfile_path.display()), 23 | _ => panic!("{err}") 24 | }, 25 | }; 26 | 27 | let config = Config::load(); 28 | 29 | if REDOWNLOAD_MANIFEST { 30 | download::mojang::download_version_manifest(); 31 | } 32 | 33 | git::ensure_repo_created(); 34 | 35 | sources::mojmap::generate(&config); 36 | sources::authlib::generate(&config); 37 | 38 | git::push(); 39 | } 40 | -------------------------------------------------------------------------------- /src/sources.rs: -------------------------------------------------------------------------------- 1 | pub mod authlib; 2 | pub mod mojmap; 3 | -------------------------------------------------------------------------------- /src/sources/authlib.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashSet, path::PathBuf}; 2 | 3 | use crate::{config::Config, decomp, download, git}; 4 | 5 | const FIRST_VERSION_WITH_AUTHLIB: &str = "13w39a"; 6 | const BRANCH_NAME: &str = "authlib"; 7 | 8 | pub fn generate(config: &Config) { 9 | git::checkout_branch(BRANCH_NAME); 10 | 11 | let manifest = download::mojang::get_version_manifest(); 12 | 13 | let mut authlib_versions_decompiled = HashSet::new(); 14 | let mut latest_mc_version_that_updated_authlib = None; 15 | 16 | for commit_message in git::commit_messages() { 17 | // authlib commit messages look like "Update to 1.1 (13w39a)" 18 | if let Some(authlib_and_mc_version_ids) = commit_message.strip_prefix("Update to ") { 19 | let mut authlib_and_mc_version_ids_split = 20 | authlib_and_mc_version_ids.split_whitespace(); 21 | let authlib_version = authlib_and_mc_version_ids_split 22 | .next() 23 | .expect("commit message should have authlib version"); 24 | let mc_version = authlib_and_mc_version_ids_split 25 | .next() 26 | .expect("authlib commit message should have Minecraft version") 27 | .trim_matches(|c| c == '(' || c == ')'); 28 | 29 | authlib_versions_decompiled.insert(authlib_version.to_owned()); 30 | if latest_mc_version_that_updated_authlib.is_none() { 31 | latest_mc_version_that_updated_authlib = Some(mc_version.to_owned()); 32 | } 33 | } 34 | } 35 | 36 | let mc_versions_to_check = if let Some(latest_mc_version_decompiled) = 37 | latest_mc_version_that_updated_authlib 38 | { 39 | println!("Latest Minecraft version that updated authlib that we decompiled: {latest_mc_version_decompiled}"); 40 | 41 | manifest 42 | .versions 43 | .iter() 44 | .rev() 45 | .skip_while(|v| v.id != latest_mc_version_decompiled) 46 | .skip(1) 47 | .collect::>() 48 | } else { 49 | println!("No authlib versions decompiled yet, starting at {FIRST_VERSION_WITH_AUTHLIB}"); 50 | 51 | manifest 52 | .versions 53 | .iter() 54 | .rev() 55 | .skip_while(|v| v.id != FIRST_VERSION_WITH_AUTHLIB) 56 | .collect::>() 57 | }; 58 | 59 | for version in mc_versions_to_check { 60 | let mc_version_id = version.id.to_owned(); 61 | println!("Checking version {mc_version_id}"); 62 | 63 | let authlib_version_id = 64 | download::authlib::get_authlib_version_for_minecraft_version(&mc_version_id); 65 | if authlib_versions_decompiled.contains(&authlib_version_id) { 66 | continue; 67 | } 68 | authlib_versions_decompiled.insert(authlib_version_id.clone()); 69 | 70 | let jar_path = download::authlib::get_version_jar(&authlib_version_id); 71 | 72 | let out_path = PathBuf::from("./tmp/out"); 73 | 74 | decomp::decompile_jar(config, &jar_path, &out_path); 75 | 76 | git::move_decomp_output_into_repo(&out_path, &[]); 77 | 78 | git::commit( 79 | &format!("Update to {authlib_version_id} ({mc_version_id})"), 80 | "Mojang", 81 | "support@mojang.com", 82 | version.release_time, 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/sources/mojmap.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use crate::{config::Config, decomp, download, git}; 4 | 5 | const FIRST_VERSION_WITH_MAPPINGS: &str = "1.14.4"; 6 | const BRANCH_NAME: &str = "mojmap"; 7 | 8 | pub fn generate(config: &Config) { 9 | git::checkout_branch(BRANCH_NAME); 10 | 11 | let manifest = download::mojang::get_version_manifest(); 12 | 13 | let mut latest_version_decompiled = None; 14 | for commit_message in git::commit_messages() { 15 | if let Some(version_id) = commit_message.strip_prefix("Update to ") { 16 | latest_version_decompiled = Some(version_id.to_owned()); 17 | break; 18 | } 19 | } 20 | 21 | let versions_to_decompile = if let Some(latest_version_decompiled) = latest_version_decompiled { 22 | println!("Latest version decompiled: {latest_version_decompiled}"); 23 | 24 | manifest 25 | .versions 26 | .iter() 27 | .rev() 28 | .skip_while(|v| v.id != latest_version_decompiled) 29 | .skip(1) 30 | .collect::>() 31 | } else { 32 | println!("No versions decompiled yet, starting at {FIRST_VERSION_WITH_MAPPINGS}"); 33 | 34 | manifest 35 | .versions 36 | .iter() 37 | .rev() 38 | .skip_while(|v| v.id != FIRST_VERSION_WITH_MAPPINGS) 39 | .collect::>() 40 | }; 41 | 42 | println!("versions_to_decompile: {versions_to_decompile:?}"); 43 | 44 | for version in versions_to_decompile { 45 | let version_id = version.id.to_owned(); 46 | println!("Decompiling version {version_id}"); 47 | 48 | let jar_path = download::mojang::get_version_jar(&version_id); 49 | let remapped_jar_path = jar_path.with_file_name(format!( 50 | "{}-remapped.jar", 51 | jar_path 52 | .file_stem() 53 | .unwrap_or_else(|| panic!("jar path {jar_path:?} must have a file extension")) 54 | .to_str() 55 | .unwrap() 56 | )); 57 | let Some(mappings_path) = download::mojang::get_version_mappings(&version_id) else { 58 | println!("{version_id} has no mappings"); 59 | continue; 60 | }; 61 | 62 | let out_path = PathBuf::from("./tmp/out"); 63 | 64 | decomp::remap_jar_with_srg_mappings(config, &jar_path, &remapped_jar_path, &mappings_path); 65 | decomp::decompile_jar(config, &remapped_jar_path, &out_path); 66 | 67 | git::move_decomp_output_into_repo(&out_path, &["assets", "data", "META-INF"]); 68 | 69 | git::commit( 70 | &format!("Update to {version_id}"), 71 | "Mojang", 72 | "support@mojang.com", 73 | version.release_time, 74 | ); 75 | } 76 | } 77 | --------------------------------------------------------------------------------