diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 78bc369..97a30c1 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,7 +10,7 @@ jobs: name: Check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 4349927..4b783de 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -11,7 +11,7 @@ jobs: name: Clippy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/.github/workflows/rustfmt.yml b/.github/workflows/rustfmt.yml index cae854c..eb3345a 100644 --- a/.github/workflows/rustfmt.yml +++ b/.github/workflows/rustfmt.yml @@ -10,7 +10,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 34a80e5..614a6f1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: name: Test Suite runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/Cargo.lock b/Cargo.lock index cbbc526..0597719 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,6 +150,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + [[package]] name = "aligned-vec" version = "0.6.4" @@ -268,6 +277,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "ash" version = "0.38.0+1.3.281" @@ -553,6 +571,26 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.17", + "v_frame", + "y4m", +] + [[package]] name = "av1-grain" version = "0.2.5" @@ -664,9 +702,9 @@ checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitcode" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648bd963d2e5d465377acecfb4b827f9f553b6bc97a8f61715779e9ed9e52b74" +checksum = "0a6ed1b54d8dc333e7be604d00fa9262f4635485ffea923647b6521a5fff045d" dependencies = [ "arrayvec", "bitcode_derive", @@ -677,9 +715,9 @@ dependencies = [ [[package]] name = "bitcode_derive" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffebfc2d28a12b262c303cb3860ee77b91bd83b1f20f0bd2a9693008e2f55a9e" +checksum = "238b90427dfad9da4a9abd60f3ec1cdee6b80454bde49ed37f1781dd8e9dc7f9" dependencies = [ "proc-macro2", "quote", @@ -703,9 +741,12 @@ dependencies = [ [[package]] name = "bitstream-io" -version = "2.6.0" +version = "4.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" +checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" +dependencies = [ + "core2", +] [[package]] name = "bitvec" @@ -766,12 +807,6 @@ dependencies = [ "piper", ] -[[package]] -name = "built" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" - [[package]] name = "built" version = "0.8.0" @@ -790,9 +825,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -895,16 +930,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" version = "1.0.4" @@ -928,9 +953,9 @@ dependencies = [ [[package]] name = "charts-rs" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64caa6454be69fcf2555a9692729d118d26ee8c3b281c355e600707c19b39109" +checksum = "46613e62ca4b6ff0b9e262adaf27dc3113aaf264accb90db048b833c6f95ad45" dependencies = [ "ahash", "arc-swap", @@ -947,9 +972,9 @@ dependencies = [ [[package]] name = "charts-rs-derive" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a22d9bb806d0d341a234556bee1481d8877a78c1a718d9a92aa4e9f542766c" +checksum = "c8d38f1088dcf6ce3487a09c49fc2d2f8759045603f24d5814357e9283260426" dependencies = [ "quote", "syn 2.0.108", @@ -1091,6 +1116,15 @@ dependencies = [ "libc", ] +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "core_maths" version = "0.1.1" @@ -1677,9 +1711,9 @@ dependencies = [ [[package]] name = "exr" -version = "1.73.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", "half", @@ -1692,14 +1726,14 @@ dependencies = [ [[package]] name = "factory" -version = "0.2.0" +version = "0.2.1" dependencies = [ "base64 0.22.1", "bimap", "bincode 2.0.1", "bitcode", "bitvec", - "built 0.8.0", + "built", "bytemuck", "charts-rs", "dhat", @@ -1823,13 +1857,13 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" dependencies = [ "crc32fast", - "libz-rs-sys", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -2083,9 +2117,9 @@ dependencies = [ [[package]] name = "get-size-derive2" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46b134aa084df7c3a513a1035c52f623e4b3065dfaf3d905a4f28a2e79b5bb3f" +checksum = "f2b6d1e2f75c16bfbcd0f95d84f99858a6e2f885c2287d1f5c3a96e8444a34b4" dependencies = [ "attribute-derive", "quote", @@ -2094,9 +2128,9 @@ dependencies = [ [[package]] name = "get-size2" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d51c9f2e956a517619ad9e7eaebc7a573f9c49b38152e12eade750f89156f9" +checksum = "49cf31a6d70300cf81461098f7797571362387ef4bf85d32ac47eaa59b3a5a1a" dependencies = [ "get-size-derive2", ] @@ -2140,9 +2174,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.13.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" dependencies = [ "color_quant", "weezl", @@ -2524,9 +2558,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.8" +version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", "byteorder-lite", @@ -2542,8 +2576,8 @@ dependencies = [ "rayon", "rgb", "tiff", - "zune-core", - "zune-jpeg", + "zune-core 0.5.1", + "zune-jpeg 0.5.12", ] [[package]] @@ -2629,15 +2663,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -2687,9 +2712,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.82" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -2737,9 +2762,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libfuzzer-sys" @@ -2800,15 +2825,6 @@ dependencies = [ "redox_syscall 0.5.18", ] -[[package]] -name = "libz-rs-sys" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd" -dependencies = [ - "zlib-rs", -] - [[package]] name = "libz-sys" version = "1.1.22" @@ -2857,9 +2873,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "loop9" @@ -3626,6 +3642,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -3855,7 +3877,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.7", + "toml_edit", ] [[package]] @@ -4161,19 +4183,21 @@ checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" [[package]] name = "rav1e" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" dependencies = [ + "aligned-vec", "arbitrary", "arg_enum_proc_macro", "arrayvec", + "av-scenechange", "av1-grain", "bitstream-io", - "built 0.7.7", + "built", "cfg-if", "interpolate_name", - "itertools 0.12.1", + "itertools 0.14.0", "libc", "libfuzzer-sys", "log", @@ -4182,23 +4206,21 @@ dependencies = [ "noop_proc_macro", "num-derive", "num-traits", - "once_cell", "paste", "profiling", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand 0.9.2", + "rand_chacha 0.9.0", "simd_helpers", - "system-deps", - "thiserror 1.0.69", + "thiserror 2.0.17", "v_frame", "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.11.20" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" dependencies = [ "avif-serialize", "imgref", @@ -4634,15 +4656,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - [[package]] name = "sha2" version = "0.10.9" @@ -5000,19 +5013,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml", - "version-compare", -] - [[package]] name = "take_mut" version = "0.2.2" @@ -5025,12 +5025,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - [[package]] name = "tempfile" version = "3.23.0" @@ -5116,7 +5110,7 @@ dependencies = [ "half", "quick-error 2.0.1", "weezl", - "zune-jpeg", + "zune-jpeg 0.4.21", ] [[package]] @@ -5220,27 +5214,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime 0.6.11", - "toml_edit 0.22.27", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - [[package]] name = "toml_datetime" version = "0.7.3" @@ -5250,19 +5223,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime 0.6.11", - "winnow", -] - [[package]] name = "toml_edit" version = "0.23.7" @@ -5270,7 +5230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ "indexmap", - "toml_datetime 0.7.3", + "toml_datetime", "toml_parser", "winnow", ] @@ -5514,12 +5474,6 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eab68b56840f69efb0fefbe3ab6661499217ffdc58e2eef7c3f6f69835386322" -[[package]] -name = "version-compare" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" - [[package]] name = "version_check" version = "0.9.5" @@ -5568,9 +5522,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.105" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -5581,11 +5535,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.55" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -5594,9 +5549,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.105" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5604,9 +5559,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.105" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", @@ -5617,9 +5572,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.105" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] @@ -5776,9 +5731,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.82" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -6614,6 +6569,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + [[package]] name = "yoke" version = "0.8.1" @@ -6811,9 +6772,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zune-core" @@ -6821,6 +6782,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + [[package]] name = "zune-inflate" version = "0.2.54" @@ -6836,7 +6803,16 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ - "zune-core", + "zune-core 0.4.12", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "410e9ecef634c709e3831c2cfdb8d9c32164fae1c67496d5b68fff728eec37fe" +dependencies = [ + "zune-core 0.5.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9b0d06b..585b00f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ # cargo-features = ["codegen-backend"] [package] name = "factory" -version = "0.2.0" +version = "0.2.1" edition = "2024" rust-version = "1.85" build = "build.rs" @@ -11,8 +11,8 @@ build = "build.rs" enum-map = { version = "2.7.3", features = ["serde"] } tilelib = { git = "https://github.com/BloodStainedCrow/tilelib.git", optional = true } spin_sleep_util = "0.1.1" -image = { version = "0.25.5", optional = true } -log = "0.4.25" +image = { version = "0.25.9", optional = true } +log = "0.4.29" simple_logger = {version = "5.0.0", optional = true } rayon = "1.10.0" serde = { version = "1.0.217", features = ["derive"], default-features = false } @@ -26,7 +26,7 @@ petgraph = { version = "0.8.2", features = ["rayon", "serde", "serde-1", "serde_ sha2 = "0.10.8" hex = "0.4.3" postcard = { version = "1.1.1", features = ["use-std"] } -charts-rs = { version = "0.3.20", features = ["resvg"] } +charts-rs = { version = "0.3.27", features = ["resvg"] } strum = { version = "0.27.1", features = ["derive"] } bitvec = { version = "1.0.1", features = ["alloc", "serde", "std"], default-features = false } bimap = { version = "0.6.3", features = ["serde", "std"], default-features = false } @@ -35,9 +35,9 @@ wgpu = { version = "25.0.2", features = ["webgl"] } egui_extras = { version = "0.31.1", optional = true } egui_plot = { version = "0.32.1", optional = true } rand = "0.8.5" -bitcode = { version = "0.6.6", features = ["serde"] } +bitcode = { version = "0.6.9", features = ["serde"] } egui = { version = "0.31.1", features = ["bytemuck", "serde"], optional = true } -flate2 = { version = "1.1.1", features = ["zlib-rs"] } +flate2 = { version = "1.1.8", features = ["zlib-rs"] } rstest = "0.25.0" parking_lot = { version = "0.12.3", features = ["serde", "deadlock_detection"] } profiling = { version = "1.0.16" } @@ -48,11 +48,11 @@ noise = { version = "0.9.0", features = ["std"] } rfd = { version = "0.15.3", optional = true } egui_graphs = { version = "0.25.1", optional = true } serde_path_to_error = "0.1.17" -get-size2 = { version = "0.7.1", features = ["derive"], optional = true } +get-size2 = { version = "0.7.4", features = ["derive"], optional = true } egui-show-info = { git = "https://github.com/BloodStainedCrow/egui-show-info", features = ["petgraph", "parking_lot", "enum-map", "bimap"], optional = true } egui-show-info-derive = { git = "https://github.com/BloodStainedCrow/egui-show-info", optional = true } -bytemuck = "1.23.1" +bytemuck = "1.25.0" # ph = "0.9.6" memoffset = "0.9.1" smallvec = { version = "1.15.1", features = ["serde"] } @@ -61,14 +61,14 @@ ecolor = { version = "0.31.1", features = ["color-hex"] } getrandom = { version = "0.3.3", features = ["wasm_js"] } getrandom_old = { version = "0.2.16", features = ["js"], package = "getrandom" } wasm-bindgen = "0.2.104" -wasm-bindgen-futures = "0.4.54" +wasm-bindgen-futures = "0.4.58" wasm-timer = "0.2.5" bincode = { version = "2.0.1", features = ["serde"] } thin-dst = "1.1.0" stable-vec = "0.4.1" recycle_vec = "1.1.2" fork = "0.3.0" -libc = { version = "0.2.177", default-features = false } +libc = { version = "0.2.180", default-features = false } interprocess = "2.2.3" fixed-buffer = "1.0.2" base64 = "0.22.1" diff --git a/README.md b/README.md index c19a723..b70f16a 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,18 @@ # What is this? -This project is an academic recreation of the factory game [Factorio](https://www.factorio.com/) taking additional ideas from [Dyson Sphere Program](https://store.steampowered.com/app/1366540/Dyson_Sphere_Program/). +This project is an academic recreation of the factory game [Factorio](https://www.factorio.com/). -I created it as an exercise to see how far I could optimize the basic concepts and algorithms of the genre in terms of performance, while allowing myself minor changes to the games' rules. +I created it as an exercise to see how far I could optimize the basic mechanics and algorithms of the genre in terms of performance. Another goal that emerged along the way, was learning about the way modern CPUs actually work. -# Roadmap -Currently I adding beacons and thinking about how to efficiently add logistics bots. Then I want to build a comprehensive suit of benchmark test to show if/by how much I was able to improve performance. - # Why did you start? -I was playing the above games and started being unable to expand due to performance issues. So in my hubris I declared: "How hard can it be?". +I was playing Factorio and started being unable to expand due to performance issues. So in my hubris I declared: "How hard can it be?". + +# Current State +Most logic for power grids, belts, splitters, assemblers, labs, inserters, mining drills, solar panels and accumulators is working. This allowed me to recreate a Factorio base, giving me a point for performance comparison. +I was able to run a base comprised of 40 copies of [this](https://factoriobox.1au.us/map/view/2824bc1566bd95b5825baf3bd2eb8fa32de8397526464f5a0327bcb82d64ebf8/#1/nauvis/15/2942/1158/0/447) Factorio Megabase by Smurphy (which Factorio runs at ~40 UPS) at 60 UPS on my machine. + +# Running it +It should run on Linux, Windows and MacOS. Assuming you have [rust and cargo](https://rust-lang.org), just `cargo run --release`. On NixOS the included `shell.nix` contains all you need. -## TODOS -- ~~Place Power Production~~ -- ~~Blueprints so I can actually do perf tests~~ -- ~~Permanently running replay system, so I can easily recreate crashes~~ -- ~~Test harness for replays, to ensure they do not crash~~ -- ~~Automatic insertion limit~~ -- ~~Assembler Module Support~~ -- ~~World listener support (i.e. update whenever something changes in the world, for power, beacons and inserters)~~ -- Lazy Terrain Generation -- ~~Assembler Module Frontend~~ -- ~~Assembler Power Consumption Modifier Support~~ -- ~~Beacons~~ -- ~~FIX Beacon Flicker due to lowering power consumption when beacons are unpowered~~ -- ~~Storage Storage Inserters~~ -- ~~Science Consumption in Labs~~ -- ~~Inserter connections to labs~~ -- ~~Debug inserters~~ -- ~~Production Graphs~~ -- ~~Liquids~~ -- ~~Map View~~ -- ~~Technology~~ -- Mining Drills -- ~~Underground belts~~ -- Fix Underground Pipe connection breaking/overlap -- Place Steam Turbines -- ~~Splitters~~ -- Allow Belts of different types to connect to one another -- Decide if I want beacons to match factorio behaviour or keep the hard switch on/off -- ~~Ore Generation~~ -- Add tile requirements for buildings/recipes (for offshore pump) -- Bots -- MAYBE: A canonical version of the simulation that can be used for diff testing (and as some weird documentation of the mechanics I suppose) \ No newline at end of file +# Attributions +All graphics used with the `graphics` feature are from the Factorio Mod [Krastorio 2 Assets](https://codeberg.org/raiguard/Krastorio2Assets). \ No newline at end of file diff --git a/src/app_state.rs b/src/app_state.rs index c819a19..2ac4173 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -746,8 +746,10 @@ impl StorageStorageInserterStore { hand_size: ITEMCOUNTTYPE, data_store: &DataStore, ) -> InserterIdentifier { - let source = FakeUnionStorage::from_storage_with_statics_at_zero(item, start, data_store); - let dest = FakeUnionStorage::from_storage_with_statics_at_zero(item, dest, data_store); + let source = + FakeUnionStorage::from_storage_with_statics_at_zero(item, start, data_store).unwrap(); + let dest = + FakeUnionStorage::from_storage_with_statics_at_zero(item, dest, data_store).unwrap(); let id: InserterIdentifier = self.inserters[item.into_usize()] .entry(movetime) @@ -829,7 +831,8 @@ impl StorageStorageInserterStore { .0 .update_inserter_src( id, - FakeUnionStorage::from_storage_with_statics_at_zero(item, new_src, data_store), + FakeUnionStorage::from_storage_with_statics_at_zero(item, new_src, data_store) + .unwrap(), ) } @@ -848,7 +851,8 @@ impl StorageStorageInserterStore { .0 .update_inserter_dest( id, - FakeUnionStorage::from_storage_with_statics_at_zero(item, new_dest, data_store), + FakeUnionStorage::from_storage_with_statics_at_zero(item, new_dest, data_store) + .unwrap(), ) } @@ -869,7 +873,8 @@ impl StorageStorageInserterStore { .update_inserter_src_if_equal( id, old_src, - FakeUnionStorage::from_storage_with_statics_at_zero(item, new_src, data_store), + FakeUnionStorage::from_storage_with_statics_at_zero(item, new_src, data_store) + .unwrap(), ) } @@ -890,7 +895,8 @@ impl StorageStorageInserterStore { .update_inserter_dest_if_equal( id, old_dest, - FakeUnionStorage::from_storage_with_statics_at_zero(item, new_dest, data_store), + FakeUnionStorage::from_storage_with_statics_at_zero(item, new_dest, data_store) + .unwrap(), ) } } @@ -1137,8 +1143,7 @@ impl Factory GameState { // Handle storage updates for storage_update in storage_updates { - let mut entity_size = None; - game_state.world.get_entity_at_mut(storage_update.position, data_store).map(|e| { - match (e, storage_update.new_pg_entity.clone()) { - (Entity::Assembler { ty, pos: _, info: AssemblerInfo::Powered { id, pole_position: _, weak_index: _ }, modules: _, rotation }, crate::power::power_grid::PowerGridEntity::Assembler { ty: _, recipe, index }) => { - entity_size = Some(data_store.assembler_info[usize::from(*ty)].size(*rotation)); + let entity = game_state.world.get_entity_at_mut(storage_update.position, data_store).expect(&format!("Did not find entity at {:?} for storage update", storage_update.position)); + + let entity_size = match (entity, storage_update.new_pg_entity.clone()) { + (Entity::Assembler { + ty, + pos: _, + info: AssemblerInfo::Powered { id, pole_position: _, weak_index: _ }, modules: _, rotation }, + crate::power::power_grid::PowerGridEntity::Assembler { ty: _, recipe, index }) => { assert_eq!(id.recipe, recipe); id.grid = storage_update.new_grid; id.assembler_index = index; // FIXME: Store and update the weak_index + + data_store.assembler_info[usize::from(*ty)].size(*rotation) }, (Entity::Lab { pos: _, ty, modules: _, pole_position: Some((_pole_pos, _weak_idx, lab_store_index)) }, crate::power::power_grid::PowerGridEntity::Lab { ty: _, index: new_idx }) => { - entity_size = Some(data_store.lab_info[usize::from(*ty)].size); *lab_store_index = new_idx; // The weak index stays the same since it it still connected to the same power pole + + data_store.lab_info[usize::from(*ty)].size } (_, _) => todo!("Handler storage_update {storage_update:?}") - } - }); + }; // FIXME: Rotation - let e_size = entity_size.unwrap(); + let e_size = entity_size; let inserter_range = data_store.max_inserter_search_range; @@ -1702,7 +1712,7 @@ impl GameState unreachable!(), crate::power::power_grid::PowerGridEntity::Accumulator { .. } => unreachable!(), crate::power::power_grid::PowerGridEntity::Beacon { .. } => unreachable!(), - }.translate(game_state.simulation_state.factory.belts.get_inserter_item(*id, *belt_pos), data_store).unwrap(); + }; game_state.simulation_state.factory.belts.update_belt_storage_inserter_src(*id, *belt_pos, game_state.simulation_state.factory.belts.get_inserter_item(*id, *belt_pos), new_storage, data_store); }, AttachedInserter::BeltBelt { .. } => { @@ -1716,7 +1726,7 @@ impl GameState unreachable!(), crate::power::power_grid::PowerGridEntity::Accumulator { .. } => unreachable!(), crate::power::power_grid::PowerGridEntity::Beacon { .. } => unreachable!(), - }.translate(*item, data_store).unwrap(); + }; let movetime = user_movetime.map(|v| v.into()).unwrap_or(data_store.inserter_infos[*ty as usize].swing_time_ticks); @@ -1740,7 +1750,7 @@ impl GameState unreachable!(), crate::power::power_grid::PowerGridEntity::Accumulator { .. } => unreachable!(), crate::power::power_grid::PowerGridEntity::Beacon { .. } => unreachable!(), - }.translate(game_state.simulation_state.factory.belts.get_inserter_item(*id, *belt_pos), data_store).unwrap(); + }; game_state.simulation_state.factory.belts.update_belt_storage_inserter_dest(*id, *belt_pos, game_state.simulation_state.factory.belts.get_inserter_item(*id, *belt_pos), new_storage, data_store); }, AttachedInserter::BeltBelt { .. } => { @@ -1754,7 +1764,7 @@ impl GameState unreachable!(), crate::power::power_grid::PowerGridEntity::Accumulator { .. } => unreachable!(), crate::power::power_grid::PowerGridEntity::Beacon { .. } => unreachable!(), - }.translate(*item, data_store).unwrap(); + }; let movetime = user_movetime.map(|v| v.into()).unwrap_or(data_store.inserter_infos[*ty as usize].swing_time_ticks); let new_id = game_state.simulation_state.factory.storage_storage_inserters.update_inserter_dest(*item, movetime.into(), *inserter, new_storage, data_store); @@ -1768,7 +1778,7 @@ impl GameState { let id: FluidSystemId<_> = game_state.simulation_state.factory.fluid_store.fluid_box_pos_to_network_id[pos]; if let Some(fluid) = id.fluid { - let storage = match storage_update.new_pg_entity { + let storage = match storage_update.old_pg_entity { crate::power::power_grid::PowerGridEntity::Assembler { ty, recipe, index } => Storage::Assembler { grid: storage_update.old_grid, recipe_idx_with_this_item: recipe.id, index }, crate::power::power_grid::PowerGridEntity::Lab { ty, index } => Storage::Lab { grid: storage_update.old_grid, index }, crate::power::power_grid::PowerGridEntity::LazyPowerProducer { item, index } => todo!(), @@ -1776,13 +1786,9 @@ impl GameState unreachable!(), crate::power::power_grid::PowerGridEntity::Beacon { .. } => unreachable!(), }; - dbg!(storage); - let Some(translated_storage) = storage.translate(fluid, data_store) else { + let Ok(old_storage) = FakeUnionStorage::from_storage_with_statics_at_zero(fluid, storage, data_store) else { return ControlFlow::Continue(()); }; - dbg!(translated_storage); - let old_storage = FakeUnionStorage::from_storage_with_statics_at_zero(fluid, translated_storage, data_store); - dbg!(old_storage); let new_storage = match storage_update.new_pg_entity { crate::power::power_grid::PowerGridEntity::Assembler { ty, recipe, index } => Storage::Assembler { grid: storage_update.new_grid, recipe_idx_with_this_item: recipe.id, index }, @@ -1791,8 +1797,8 @@ impl GameState unreachable!(), crate::power::power_grid::PowerGridEntity::Accumulator { .. } => unreachable!(), crate::power::power_grid::PowerGridEntity::Beacon { .. } => unreachable!(), - }.translate(fluid, data_store).unwrap(); - game_state.simulation_state.factory.fluid_store.update_fluid_conn_if_needed(*pos, old_storage, FakeUnionStorage::from_storage_with_statics_at_zero(fluid, new_storage, data_store)); + }; + game_state.simulation_state.factory.fluid_store.update_fluid_conn_if_needed(*pos, old_storage, FakeUnionStorage::from_storage_with_statics_at_zero(fluid, new_storage, data_store).unwrap()); } }, @@ -2333,7 +2339,7 @@ impl GameState ()>, diff --git a/src/assembler/bucketed.rs b/src/assembler/bucketed.rs index a92f38b..a36c9ab 100644 --- a/src/assembler/bucketed.rs +++ b/src/assembler/bucketed.rs @@ -877,4 +877,8 @@ impl usize { + self.hot_data.len() - self.holes.len() + } } diff --git a/src/assembler/mod.rs b/src/assembler/mod.rs index 6c35fa2..8640c61 100644 --- a/src/assembler/mod.rs +++ b/src/assembler/mod.rs @@ -505,6 +505,58 @@ impl< _ => unreachable!(), } } + + pub fn num_assemblers(&self) -> usize { + let Self { + assemblers_0_1, + assemblers_1_1, + assemblers_2_1, + assemblers_2_2, + assemblers_2_3, + assemblers_3_1, + assemblers_4_1, + assemblers_5_1, + assemblers_6_1, + recipe: _, + } = self; + + assemblers_0_1 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_1_1 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_2_1 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_2_2 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_2_3 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_3_1 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_4_1 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_5_1 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + + assemblers_6_1 + .iter() + .map(|store| store.num_assemblers()) + .sum::() + } } // FIXME: @@ -799,6 +851,8 @@ pub trait MultiAssemblerStore< ret } + + fn num_assemblers(&self) -> usize; } pub mod arrays { diff --git a/src/assembler/simd.rs b/src/assembler/simd.rs index f3066a3..e108e61 100644 --- a/src/assembler/simd.rs +++ b/src/assembler/simd.rs @@ -665,6 +665,7 @@ impl; NUM_INGS] = self @@ -673,13 +674,7 @@ impl usize { + self.len - self.holes.len() + } } #[cfg(test)] diff --git a/src/belt/mod.rs b/src/belt/mod.rs index c9f81fa..fcfe7de 100644 --- a/src/belt/mod.rs +++ b/src/belt/mod.rs @@ -1539,7 +1539,7 @@ impl BeltStore { .inserters .inserters .iter() - .filter_map(|(ins, item)| { + .filter_map(|(ins, item, _movetime, _hand_size)| { let (dir, _state) = ins.state.into(); (dir == Dir::StorageToBelt).then_some(*item) }) @@ -2100,7 +2100,7 @@ impl BeltStore { belt.inserters .inserters .iter() - .filter_map(|(ins, item)| { + .filter_map(|(ins, item, _movetime, _hand_size)| { let (dir, _state) = ins.state.into(); (dir == Dir::StorageToBelt).then_some(*item) }) @@ -2598,8 +2598,9 @@ impl BeltStore { movetime: u16, hand_size: ITEMCOUNTTYPE, ) -> Result<(), SpaceOccupiedError> { - let handle_sushi_belt = - |belt: &mut SushiBelt| belt.add_in_inserter(filter, pos, storage_id); + let handle_sushi_belt = |belt: &mut SushiBelt| { + belt.add_in_inserter(filter, pos, storage_id, movetime, hand_size) + }; match id { BeltTileId::AnyBelt(index, _) => { @@ -2626,7 +2627,7 @@ impl BeltStore { let now_sushi_belt = self.inner.get_sushi_mut(new_index); now_sushi_belt - .add_in_inserter(filter, pos, storage_id) + .add_in_inserter(filter, pos, storage_id, movetime, hand_size) .expect("We already became sushi, it should now work!"); }, } @@ -2667,8 +2668,9 @@ impl BeltStore { movetime: u16, hand_size: ITEMCOUNTTYPE, ) -> Result<(), SpaceOccupiedError> { - let handle_sushi_belt = - |belt: &mut SushiBelt| belt.add_out_inserter(filter, pos, storage_id); + let handle_sushi_belt = |belt: &mut SushiBelt| { + belt.add_out_inserter(filter, pos, storage_id, movetime, hand_size) + }; match id { BeltTileId::AnyBelt(index, _) => { @@ -2695,7 +2697,7 @@ impl BeltStore { let now_sushi_belt = self.inner.get_sushi_mut(new_index); now_sushi_belt - .add_out_inserter(filter, pos, storage_id) + .add_out_inserter(filter, pos, storage_id, movetime, hand_size) .expect("We already became sushi, it should now work!"); }, } @@ -3010,7 +3012,8 @@ impl BeltStore { belt_id.item, new_src, data_store, - ), + ) + .unwrap(), ); }, AnyBelt::Sushi(index) => { @@ -3018,7 +3021,8 @@ impl BeltStore { belt_pos, FakeUnionStorage::from_storage_with_statics_at_zero( src_item, new_src, data_store, - ), + ) + .unwrap(), ); }, AnyBelt::Empty(_) => unimplemented!("Empty belt cannot have inserters"), @@ -3045,7 +3049,8 @@ impl BeltStore { belt_id.item, new_dest, data_store, - ), + ) + .unwrap(), ); }, AnyBelt::Sushi(index) => { @@ -3053,7 +3058,8 @@ impl BeltStore { belt_pos, FakeUnionStorage::from_storage_with_statics_at_zero( dest_item, new_dest, data_store, - ), + ) + .unwrap(), ); }, AnyBelt::Empty(_) => unimplemented!("Empty belt cannot have inserters"), diff --git a/src/belt/smart.rs b/src/belt/smart.rs index 0e93852..850106c 100644 --- a/src/belt/smart.rs +++ b/src/belt/smart.rs @@ -5,6 +5,7 @@ use std::{ u8, }; +use crate::item::Indexable; use crate::{ inserter::{ InserterState, belt_storage_inserter::Dir, @@ -46,10 +47,6 @@ pub static NUM_BELT_FREE_CACHE_HITS: AtomicUsize = AtomicUsize::new(0); // #[cfg(debug_assertions)] pub static NUM_BELT_LOCS_SEARCHED: AtomicUsize = AtomicUsize::new(0); -// HUGE FIXME: -pub const MOVETIME: u8 = 12; -pub const HAND_SIZE: u8 = 12; - #[allow(clippy::module_name_repetitions)] #[cfg_attr(feature = "client", derive(ShowInfo), derive(GetSize))] #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] @@ -98,6 +95,8 @@ pub struct BeltInserterInfo { pub outgoing: bool, pub state: InserterState, pub connection: FakeUnionStorage, + pub hand_size: ITEMCOUNTTYPE, + pub movetime: u8, } #[derive(Debug)] @@ -180,7 +179,7 @@ impl SmartBelt { inserters: SushiInserterStoreDyn { inserters: inserters .into_iter() - .map(|(inserter, _movetime, _hand_size)| (inserter, item)) + .map(|(inserter, movetime, hand_size)| (inserter, item, movetime, hand_size)) .collect(), }, @@ -347,6 +346,8 @@ impl SmartBelt { outgoing: dir == Dir::BeltToStorage, state, connection: inserter.0.storage_id, + movetime: inserter.1, + hand_size: inserter.2, }); } else if pos > belt_pos { return None; @@ -639,7 +640,14 @@ impl SmartBelt { // We KNOW this position is filled debug_assert!(self.locs[loc_idx]); let mut loc = true; - let _changed = ins.update(&mut loc, storages, *movetime, *hand_size, grid_size); + let _changed = ins.update( + self.item.into_usize(), + &mut loc, + storages, + *movetime, + *hand_size, + grid_size, + ); if !loc { self.locs.set(loc_idx, false); @@ -651,7 +659,14 @@ impl SmartBelt { } else { let mut loc = self.locs.get_mut(loc_idx).unwrap(); - let changed = ins.update(loc.as_mut(), storages, *movetime, *hand_size, grid_size); + let changed = ins.update( + self.item.into_usize(), + loc.as_mut(), + storages, + *movetime, + *hand_size, + grid_size, + ); if changed { // the inserter changed something. diff --git a/src/belt/sushi.rs b/src/belt/sushi.rs index fc298d0..85b8c0f 100644 --- a/src/belt/sushi.rs +++ b/src/belt/sushi.rs @@ -9,6 +9,7 @@ use egui_show_info_derive::ShowInfo; use get_size2::GetSize; use crate::inserter::belt_storage_inserter::Dir; +use crate::item::ITEMCOUNTTYPE; use crate::{ belt::belt::NoSpaceError, item::{IdxTrait, Item, WeakIdxTrait}, @@ -24,8 +25,6 @@ use crate::inserter::FakeUnionStorage; use crate::inserter::belt_storage_inserter_non_const_gen::BeltStorageInserterDyn; use itertools::Either; -use crate::belt::smart::{HAND_SIZE, MOVETIME}; - #[cfg_attr(feature = "client", derive(ShowInfo), derive(GetSize))] #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct SushiBelt { @@ -48,7 +47,7 @@ pub struct SushiBelt { #[cfg_attr(feature = "client", derive(ShowInfo), derive(GetSize))] #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub(super) struct SushiInserterStoreDyn { - pub(super) inserters: Box<[(BeltStorageInserterDyn, Item)]>, + pub(super) inserters: Box<[(BeltStorageInserterDyn, Item, u8, ITEMCOUNTTYPE)]>, } #[derive(Debug, PartialEq, Eq)] @@ -82,6 +81,8 @@ impl SushiBelt { filter: Item, pos: BeltLenType, storage_id: FakeUnionStorage, + movetime: u16, + hand_size: ITEMCOUNTTYPE, ) -> Result<(), SpaceOccupiedError> { assert!( usize::from(pos) < self.locs.len(), @@ -92,7 +93,12 @@ impl SushiBelt { let mut pos_after_last_inserter = 0; let mut i = 0; - for offset in self.inserters.inserters.iter().map(|(i, _item)| i.offset) { + for offset in self + .inserters + .inserters + .iter() + .map(|(i, _item, _movetime, _hand_size)| i.offset) + { let next_inserter_pos = pos_after_last_inserter + offset; match next_inserter_pos.cmp(&pos) { @@ -119,6 +125,8 @@ impl SushiBelt { storage_id, ), filter, + movetime.try_into().unwrap_or(u8::MAX), + hand_size, ), ); ins.into_boxed_slice() @@ -126,7 +134,7 @@ impl SushiBelt { let next = self.inserters.inserters.get_mut(i + 1); - if let Some((next_ins, _item)) = next { + if let Some((next_ins, _item, _movetime, _hand_size)) = next { next_ins.offset -= new_inserter_offset + 1; } @@ -138,6 +146,8 @@ impl SushiBelt { filter: Item, pos: BeltLenType, storage_id: FakeUnionStorage, + movetime: u16, + hand_size: ITEMCOUNTTYPE, ) -> Result<(), SpaceOccupiedError> { assert!( usize::from(pos) < self.locs.len(), @@ -148,7 +158,12 @@ impl SushiBelt { let mut pos_after_last_inserter = 0; let mut i = 0; - for offset in self.inserters.inserters.iter().map(|(i, _item)| i.offset) { + for offset in self + .inserters + .inserters + .iter() + .map(|(i, _item, _movetime, _hand_size)| i.offset) + { let next_inserter_pos = pos_after_last_inserter + offset; match next_inserter_pos.cmp(&pos) { @@ -175,6 +190,8 @@ impl SushiBelt { storage_id, ), filter, + movetime.try_into().unwrap_or(u8::MAX), + hand_size, ), ); ins.into_boxed_slice() @@ -182,7 +199,7 @@ impl SushiBelt { let next = self.inserters.inserters.get_mut(i + 1); - if let Some((next_ins, _item)) = next { + if let Some((next_ins, _item, _movetime, _hand_size)) = next { next_ins.offset -= new_inserter_offset + 1; } @@ -193,7 +210,7 @@ impl SushiBelt { pub fn get_inserter_info_at(&self, belt_pos: u16) -> Option { let mut pos = 0; - for (inserter, _item) in self.inserters.inserters.iter() { + for (inserter, _item, movetime, hand_size) in self.inserters.inserters.iter() { pos += inserter.offset; if pos == belt_pos { let (dir, state) = inserter.state.into(); @@ -201,6 +218,9 @@ impl SushiBelt { outgoing: dir == Dir::BeltToStorage, state, connection: inserter.storage_id, + + hand_size: *hand_size, + movetime: *movetime, }); } else if pos > belt_pos { return None; @@ -221,7 +241,12 @@ impl SushiBelt { let mut pos_after_last_inserter = 0; let mut i = 0; - for offset in self.inserters.inserters.iter().map(|(i, _item)| i.offset) { + for offset in self + .inserters + .inserters + .iter() + .map(|(i, _item, _movetime, _hand_size)| i.offset) + { let next_inserter_pos = pos_after_last_inserter + offset; match next_inserter_pos.cmp(&belt_pos) { @@ -243,7 +268,7 @@ impl SushiBelt { pub fn set_inserter_storage_id(&mut self, belt_pos: u16, new: FakeUnionStorage) { let mut pos = 0; - for (inserter, _item) in self.inserters.inserters.iter_mut() { + for (inserter, _item, _movetime, _hand_size) in self.inserters.inserters.iter_mut() { pos += inserter.offset; if pos == belt_pos { inserter.storage_id = new; @@ -265,7 +290,12 @@ impl SushiBelt { let mut pos_after_last_inserter = 0; let mut i = 0; - for offset in self.inserters.inserters.iter().map(|(i, _item)| i.offset) { + for offset in self + .inserters + .inserters + .iter() + .map(|(i, _item, _movetime, _hand_size)| i.offset) + { let next_inserter_pos = pos_after_last_inserter + offset; match next_inserter_pos.cmp(&pos) { @@ -309,7 +339,7 @@ impl SushiBelt { .inserters .inserters .iter() - .map(|(_, item)| *item) + .map(|(_, item, _movetime, _hand_size)| *item) .chain(belt_belt_filter_in.into_iter().filter_map(|info| { let SushiInfo::Pure(item) = info else { unreachable!() @@ -395,12 +425,12 @@ impl SushiBelt { .collect::().into(), inserters: InserterStoreDyn { // FIXME: Some of these inserters might have a different item than what we are converting to. This will result in crashes and item transmutation - inserters: inserters.into_iter().map(|(ins, inserter_item)| { + inserters: inserters.into_iter().map(|(ins, inserter_item, movetime, hand_size)| { assert_eq!(item, inserter_item, "FIXME: We need to handle inserters which will never work again in smart belts"); // if item != inserter_item { // error!("We need to handle inserters which will never work again in smart belts!!!!!!!"); // } - (ins, MOVETIME, HAND_SIZE) + (ins, movetime, hand_size) }).collect(), }, item, @@ -485,7 +515,7 @@ impl SushiBelt { .inserters .inserters .iter() - .map(|(i, _item)| i.offset) + .map(|(i, _item, _movetime, _hand_size)| i.offset) .enumerate(); let mut current_pos = 0; @@ -606,7 +636,7 @@ impl SushiBelt { let free_spots_before_last_inserter_front: u16 = front_inserters .inserters .iter() - .map(|(i, _item)| i.offset) + .map(|(i, _item, _movetime, _hand_size)| i.offset) .sum(); let length_after_last_inserter = TryInto::::try_into(front_len) .expect("Belt should be max u16::MAX long") @@ -614,7 +644,7 @@ impl SushiBelt { - TryInto::::try_into(num_front_inserters) .expect("Belt should be max u16::MAX long"); - if let Some((i, _item)) = back_inserters.inserters.get_mut(0) { + if let Some((i, _item, _movetime, _hand_size)) = back_inserters.inserters.get_mut(0) { i.offset += length_after_last_inserter; } @@ -1047,7 +1077,7 @@ impl Belt for SushiBelt { }); if side == Side::FRONT { - if let Some((i, _ietm)) = self.inserters.inserters.first_mut() { + if let Some((i, _item, _movetime, _hand_size)) = self.inserters.inserters.first_mut() { i.offset -= amount - pos_after_last_removed_inserter; } } diff --git a/src/data/mod.rs b/src/data/mod.rs index d016035..2add391 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1511,33 +1511,34 @@ impl RawDataStore { instantly_finished_technologies, belt_infos: vec![ + // TODO: For now only have one kind of transport belt since connection is still borked BeltInfo { name: "factory_game::fast_transport_belt".to_string().into(), - display_name: "Fast Transport Belt".to_string(), + display_name: "Express Transport Belt".to_string(), has_underground: Some(BeltUndergroundInfo { max_distance: 9 }), has_splitter: None, timer_increase: 45 * 2, }, - BeltInfo { - name: "factory_game::transport_belt".to_string().into(), - display_name: "Transport Belt".to_string(), - has_underground: Some(BeltUndergroundInfo { max_distance: 6 }), - has_splitter: None, - timer_increase: 15 * 2, - }, + // BeltInfo { + // name: "factory_game::transport_belt".to_string().into(), + // display_name: "Transport Belt".to_string(), + // has_underground: Some(BeltUndergroundInfo { max_distance: 6 }), + // has_splitter: None, + // timer_increase: 15 * 2, + // }, ], // FIXME: mining_drill_info: vec![ - MiningDrillInfo { - name: "factory_game::mining_drill".to_string().into(), - display_name: "Electric Mining Drill".to_string().into(), - size: [3, 3], - mining_range: [5, 5], - base_speed: 20, - resource_drain: (1, 1), - output_offset: Some([1, -1]), - }, + // MiningDrillInfo { + // name: "factory_game::mining_drill".to_string().into(), + // display_name: "Electric Mining Drill".to_string().into(), + // size: [3, 3], + // mining_range: [5, 5], + // base_speed: 20, + // resource_drain: (1, 1), + // output_offset: Some([1, -1]), + // }, MiningDrillInfo { name: "factory_game::mining_drill_small_no_output" .to_string() diff --git a/src/frontend/action/action_state_machine.rs b/src/frontend/action/action_state_machine.rs index b494cf5..a699881 100644 --- a/src/frontend/action/action_state_machine.rs +++ b/src/frontend/action/action_state_machine.rs @@ -14,6 +14,7 @@ use log::{error, warn}; use petgraph::Directed; use crate::{ + NewWithDataStore, app_state::SimulationState, belt::splitter::SplitterDistributionMode, blueprint::Blueprint, @@ -46,10 +47,63 @@ pub const WIDTH_PER_LEVEL: usize = 16; pub struct Hotbar { slots: [Option>; 10], } -impl Default for Hotbar { - fn default() -> Self { +impl NewWithDataStore for Hotbar { + fn new( + data_store: impl std::borrow::Borrow>, + ) -> Self { Self { - slots: array::from_fn(|_| None), + slots: array::from_fn(|idx| match idx + 1 { + 1 => Some(HeldObject::Entity(PlaceEntityType::Lab { + pos: Position { x: 0, y: 0 }, + ty: 0, + })), + 2 => Some(HeldObject::Entity(PlaceEntityType::Assembler { + pos: Position { x: 0, y: 0 }, + ty: 0, + rotation: Dir::North, + })), + 3 => Some(HeldObject::Entity(PlaceEntityType::Belt { + pos: Position { x: 0, y: 0 }, + ty: 0, + direction: Dir::North, + })), + 4 => Some(HeldObject::Entity(PlaceEntityType::Inserter { + pos: Position { x: 0, y: 0 }, + ty: 0, + dir: Dir::North, + filter: None, + user_movetime: None, + })), + 5 => Some(HeldObject::Entity(PlaceEntityType::PowerPole { + pos: Position { x: 0, y: 0 }, + ty: 0, + })), + 6 => Some(HeldObject::Entity(PlaceEntityType::Chest { + pos: Position { x: 0, y: 0 }, + ty: 0, + })), + 7 => Some(HeldObject::Entity(PlaceEntityType::Underground { + pos: Position { x: 0, y: 0 }, + ty: 0, + direction: Dir::North, + underground_dir: UndergroundDir::Entrance, + })), + 8 => Some(HeldObject::Entity(PlaceEntityType::SolarPanel { + pos: Position { x: 0, y: 0 }, + ty: 0, + })), + 9 => Some(HeldObject::Entity(PlaceEntityType::FluidTank { + pos: Position { x: 0, y: 0 }, + ty: 0, + rotation: Dir::North, + })), + 10 => Some(HeldObject::Entity(PlaceEntityType::Beacon { + pos: Position { x: 0, y: 0 }, + ty: 0, + })), + + _ => unreachable!(), + }), } } } @@ -222,7 +276,7 @@ impl current_fork_save_in_progress: None, - hotbar: Hotbar::default(), + hotbar: Hotbar::new(data_store), hotbar_window_open: true, } } @@ -1290,7 +1344,7 @@ impl data_store: &DataStore, ) { // Possible Actions - ui.columns_const(|uis: &mut [egui::Ui; 12]| { + ui.columns_const(|uis: &mut [egui::Ui; 13]| { for (i, ui) in uis.iter_mut().enumerate() { let ty_count = match i { 0 => data_store.assembler_info.len(), @@ -1305,6 +1359,7 @@ impl 9 => data_store.solar_panel_info.len(), 10 => data_store.lab_info.len(), 11 => data_store.inserter_infos.len(), + 12 => data_store.mining_drill_info.len(), _ => unreachable!(), } as u8; @@ -1413,6 +1468,14 @@ impl }), &data_store.inserter_infos[ty as usize].display_name, ), + 12 => ( + HeldObject::Entity(PlaceEntityType::MiningDrill { + pos: Position { x: 0, y: 0 }, + ty, + rotation: Dir::North, + }), + &data_store.mining_drill_info[ty as usize].display_name, + ), _ => unreachable!(), }; diff --git a/src/frontend/world/tile.rs b/src/frontend/world/tile.rs index d19f7c1..d6c53e2 100644 --- a/src/frontend/world/tile.rs +++ b/src/frontend/world/tile.rs @@ -419,7 +419,8 @@ fn try_attaching_fluids( conn_fluid, conn_storage, data_store, - ), + ) + .unwrap(), conn_pos, ) }, @@ -431,7 +432,8 @@ fn try_attaching_fluids( conn_fluid, conn_storage, data_store, - ), + ) + .unwrap(), conn_pos, ) }, @@ -3214,17 +3216,13 @@ impl World { - let dest_storage_untranslated = match dest_storage_untranslated { + let dest_storage = match dest_storage_untranslated { Static::Done(storage) => storage, Static::ToInstantiate => { unreachable!("Storages must be instantiated before calling this function") }, }; - let dest_storage = dest_storage_untranslated - .translate(filter, data_store) - .unwrap(); - match simulation_state.factory.belts.add_belt_storage_inserter( filter, start_belt_id, @@ -3233,7 +3231,8 @@ impl World World { - let start_storage_untranslated = match start_storage_untranslated { + let start_storage = match start_storage_untranslated { Static::Done(storage) => storage, Static::ToInstantiate => { unreachable!("Storages must be instantiated before calling this function") }, }; - let start_storage = start_storage_untranslated - .translate(filter, data_store) - .unwrap(); - match simulation_state.factory.belts.add_storage_belt_inserter( filter, dest_belt_id, @@ -3271,7 +3266,8 @@ impl World World { - let start_storage_untranslated = match start_storage_untranslated { + let start_storage = match start_storage_untranslated { Static::Done(storage) => storage, Static::ToInstantiate => { unreachable!("Storages must be instantiated before calling this function") }, }; - let dest_storage_untranslated = match dest_storage_untranslated { + let dest_storage = match dest_storage_untranslated { Static::Done(storage) => storage, Static::ToInstantiate => { unreachable!("Storages must be instantiated before calling this function") }, }; - let start_storage = start_storage_untranslated - .translate(filter, data_store) - .unwrap(); - let dest_storage = dest_storage_untranslated - .translate(filter, data_store) - .unwrap(); - let index = simulation_state.factory.storage_storage_inserters.add_ins( filter, movetime.into(), diff --git a/src/inserter/belt_storage_inserter.rs b/src/inserter/belt_storage_inserter.rs index c41cc76..27a67a9 100644 --- a/src/inserter/belt_storage_inserter.rs +++ b/src/inserter/belt_storage_inserter.rs @@ -82,7 +82,8 @@ impl BeltStorageInserter<{ Dir::BeltToStorage }> { } }, InserterState::WaitingForSpaceInDestination(count) => { - let (max_insert, old) = index_fake_union(storages, self.storage_id, grid_size); + let (max_insert, old) = + index_fake_union(todo!(), storages, self.storage_id, grid_size); let to_insert = min(count, *max_insert - *old); if to_insert > 0 { @@ -134,7 +135,8 @@ impl BeltStorageInserter<{ Dir::StorageToBelt }> { match self.state { InserterState::WaitingForSourceItems(count) => { - let (_max_insert, old) = index_fake_union(storages, self.storage_id, grid_size); + let (_max_insert, old) = + index_fake_union(todo!(), storages, self.storage_id, grid_size); let to_extract = min(max_hand_size - count, *old); diff --git a/src/inserter/belt_storage_inserter_non_const_gen.rs b/src/inserter/belt_storage_inserter_non_const_gen.rs index be40213..8a67da5 100644 --- a/src/inserter/belt_storage_inserter_non_const_gen.rs +++ b/src/inserter/belt_storage_inserter_non_const_gen.rs @@ -88,6 +88,7 @@ impl BeltStorageInserterDyn { #[inline(always)] pub fn update( &mut self, + item_id: usize, mut loc: impl DerefMut + Deref, storages: SingleItemStorages, movetime: u8, @@ -109,7 +110,8 @@ impl BeltStorageInserterDyn { } }, DynInserterState::BSWaitingForSpaceInDestination(count) => { - let (max_insert, old) = index_fake_union(storages, self.storage_id, grid_size); + let (max_insert, old) = + index_fake_union(item_id, storages, self.storage_id, grid_size); let to_insert = min(count, *max_insert - *old); if to_insert > 0 { @@ -144,7 +146,8 @@ impl BeltStorageInserterDyn { false }, DynInserterState::SBWaitingForSourceItems(count) => { - let (_max_insert, old) = index_fake_union(storages, self.storage_id, grid_size); + let (_max_insert, old) = + index_fake_union(item_id, storages, self.storage_id, grid_size); let to_extract = min(max_hand_size - count, *old); diff --git a/src/inserter/belt_storage_pure_buckets.rs b/src/inserter/belt_storage_pure_buckets.rs index a70a156..2be1991 100644 --- a/src/inserter/belt_storage_pure_buckets.rs +++ b/src/inserter/belt_storage_pure_buckets.rs @@ -613,6 +613,7 @@ impl BucketedStorageStorageInserterStore { } fn handle_waiting_for_item_ins( + item_id: usize, inserter: &mut UpdatingInserter, frontend: &mut BucketedStorageStorageInserterStoreFrontend, storages: SingleItemStorages, @@ -633,7 +634,8 @@ impl BucketedStorageStorageInserterStore { } }, Dir::StorageToBelt => { - let (_max_insert, old) = index_fake_union(storages, inserter.storage_id, grid_size); + let (_max_insert, old) = + index_fake_union(item_id, storages, inserter.storage_id, grid_size); let to_extract = min(inserter.max_hand_size - inserter.current_hand, *old); @@ -663,6 +665,7 @@ impl BucketedStorageStorageInserterStore { } fn handle_waiting_for_space_ins( + item_id: usize, inserter: &mut UpdatingInserter, frontend: &mut BucketedStorageStorageInserterStoreFrontend, storages: SingleItemStorages, @@ -673,7 +676,8 @@ impl BucketedStorageStorageInserterStore { ) -> bool { match DIR { Dir::BeltToStorage => { - let (max_insert, old) = index_fake_union(storages, inserter.storage_id, grid_size); + let (max_insert, old) = + index_fake_union(item_id, storages, inserter.storage_id, grid_size); let to_insert = min(inserter.current_hand, *max_insert - *old); @@ -751,6 +755,7 @@ impl BucketedStorageStorageInserterStore { #[profiling::function] pub fn update( &mut self, + item_id: usize, frontend: &mut BucketedStorageStorageInserterStoreFrontend, storages: SingleItemStorages, belts: &mut [SmartBelt], @@ -808,6 +813,7 @@ impl BucketedStorageStorageInserterStore { Dir::BeltToStorage => { let now_moving = self.waiting_for_item.extract_if(.., |inserter| { Self::handle_waiting_for_item_ins::( + item_id, inserter, frontend, storages, @@ -835,6 +841,7 @@ impl BucketedStorageStorageInserterStore { Dir::StorageToBelt => { let now_moving = self.waiting_for_item.extract_if(.., |inserter| { Self::handle_waiting_for_item_ins::( + item_id, inserter, frontend, storages, @@ -912,6 +919,7 @@ impl BucketedStorageStorageInserterStore { ItemIdxType, { Dir::BeltToStorage }, >( + item_id, inserter, frontend, storages, @@ -944,6 +952,7 @@ impl BucketedStorageStorageInserterStore { ItemIdxType, { Dir::StorageToBelt }, >( + item_id, inserter, frontend, storages, @@ -1312,6 +1321,7 @@ mod test { for (storage, belt) in values.into_iter().zip(belt_ids) { if random::() < 1 { store[item].0.update( + item, &mut frontend[item], &mut [ (max_insert.as_slice(), storages_in[item].as_mut_slice()), @@ -1322,6 +1332,7 @@ mod test { current_tick, ); store[item].1.update( + item, &mut frontend[item], &mut [ (max_insert.as_slice(), storages_in[item].as_mut_slice()), @@ -1394,6 +1405,7 @@ mod test { } } store.0.update( + 0, frontend, &mut [ (max_insert.as_slice(), storage_in.as_mut_slice()), @@ -1404,6 +1416,7 @@ mod test { current_tick, ); store.1.update( + 0, frontend, &mut [ (max_insert.as_slice(), storage_in.as_mut_slice()), diff --git a/src/inserter/mod.rs b/src/inserter/mod.rs index 4da4953..c19b6ec 100644 --- a/src/inserter/mod.rs +++ b/src/inserter/mod.rs @@ -183,7 +183,7 @@ impl FakeUnionStorage { item: Item, storage: Storage, data_store: &DataStore, - ) -> Self { + ) -> Result { let grid_size: usize = grid_size(item, data_store); let static_size: usize = static_size(item, data_store); @@ -195,11 +195,16 @@ impl FakeUnionStorage { recipe_idx_with_this_item, index, } => { - assert!( - recipe_idx_with_this_item.into_usize() - < data_store.num_recipes_with_item[item.into_usize()] - ); - Self { + let recipe_idx_with_this_item = *data_store + .recipe_to_translated_index + .get(&( + Recipe { + id: recipe_idx_with_this_item, + }, + item, + )) + .ok_or(())?; + Ok(Self { index: u32::from(index), grid_or_static_flag: u16::from(grid) .checked_add(u16::try_from(grid_offset).unwrap()) @@ -208,21 +213,21 @@ impl FakeUnionStorage { recipe_idx_with_this_item, )) .unwrap(), - } + }) }, - Storage::Lab { grid, index } => Self { + Storage::Lab { grid, index } => Ok(Self { index: u32::from(index), grid_or_static_flag: u16::from(grid) .checked_add(u16::try_from(grid_offset).unwrap()) .expect("Grid ID too high (would overflow the grid_or_static)"), recipe_idx_with_this_item: data_store.num_recipes_with_item[usize_from(item.id)] as u16, - }, - Storage::Static { index, static_id } => Self { + }), + Storage::Static { index, static_id } => Ok(Self { index: u32::try_from(index).unwrap(), grid_or_static_flag: 0, recipe_idx_with_this_item: static_id, - }, + }), } } } @@ -248,30 +253,6 @@ pub enum Storage { } impl Storage { - pub fn translate( - self, - item: Item, - data_store: &DataStore, - ) -> Option { - match self { - Storage::Assembler { - grid, - recipe_idx_with_this_item, - index, - } => Some(Storage::Assembler { - grid, - recipe_idx_with_this_item: *data_store.recipe_to_translated_index.get(&( - Recipe { - id: recipe_idx_with_this_item, - }, - item, - ))?, - index, - }), - storage => Some(storage), - } - } - pub fn change_grid(self, new_id: PowerGridIdentifier) -> Self { match self { Storage::Assembler { @@ -291,43 +272,13 @@ impl Storage { } } - fn into_inner_and_outer_indices( - self, - num_grids_total: usize, - num_recipes: usize, - grid_size: usize, - ) -> (usize, usize) { - match self { - Storage::Assembler { - grid, - recipe_idx_with_this_item, - index, - } => { - debug_assert!( - usize_from(recipe_idx_with_this_item) < num_recipes, - "The recipe stored in an inserter needs to be translated!" - ); - let outer = Into::::into(grid) * grid_size - + Into::::into(recipe_idx_with_this_item); - (outer, index.try_into().unwrap()) - }, - Storage::Lab { grid, index } => { - let outer = Into::::into(grid) * grid_size + num_recipes; - (outer, index.try_into().unwrap()) - }, - Storage::Static { static_id, index } => { - // debug_assert!(usize::from(static_id) < data_store.num_different_static_containers); - let outer = num_grids_total * grid_size + Into::::into(static_id as u8); - (outer, index.try_into().unwrap()) - }, - } - } - - fn into_inner_and_outer_indices_with_statics_at_zero( + fn into_inner_and_outer_indices_with_statics_at_zero( self, + item: Item, num_recipes: usize, grid_size: usize, static_size: usize, + data_store: &DataStore, ) -> (usize, usize) { let grid_offset = static_size.div_ceil(grid_size); @@ -337,6 +288,15 @@ impl Storage { recipe_idx_with_this_item, index, } => { + let recipe_idx_with_this_item = *data_store + .recipe_to_translated_index + .get(&( + Recipe { + id: recipe_idx_with_this_item, + }, + item, + )) + .unwrap(); debug_assert!( usize_from(recipe_idx_with_this_item) < num_recipes, "The recipe stored in an inserter needs to be translated!" @@ -378,6 +338,17 @@ pub enum StaticID { PureSoloOwnedMiningDrill = 1, } +impl TryFrom for StaticID { + type Error = (); + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::Chest), + 1 => Ok(Self::PureSoloOwnedMiningDrill), + _ => Err(()), + } + } +} + #[cfg(test)] mod test { use crate::DATA_STORE; @@ -443,28 +414,28 @@ mod test { proptest! { - #[test] - fn storage_and_fake_union_result_in_same_indices((item, num_grids, storage) in union_test_input()) { - let grid_size = grid_size(item, &DATA_STORE); + // #[test] + // fn storage_and_fake_union_result_in_same_indices((item, num_grids, storage) in union_test_input()) { + // let grid_size = grid_size(item, &DATA_STORE); - let storage_union = FakeUnionStorage::from_storage(item, storage, &DATA_STORE); + // let storage_union = FakeUnionStorage::from_storage(item, storage, &DATA_STORE); - let union_indices = storage_union.into_inner_and_outer_indices(num_grids.into(), grid_size); + // let union_indices = storage_union.into_inner_and_outer_indices(num_grids.into(), grid_size); - let storage_indices = storage.into_inner_and_outer_indices(num_grids.into(), DATA_STORE.num_recipes_with_item[usize_from(item.id)], grid_size); + // let storage_indices = storage.into_inner_and_outer_indices(Item::try_from(0).unwrap(), num_grids.into(), DATA_STORE.num_recipes_with_item[usize_from(item.id)], grid_size, &DATA_STORE); - prop_assert_eq!(union_indices, storage_indices); - } + // prop_assert_eq!(union_indices, storage_indices); + // } #[test] fn storage_and_fake_union_result_in_same_indices_with_statics_at_zero((item, _num_grids, storage) in union_test_input()) { let grid_size = grid_size(item, &DATA_STORE); - let storage_union = FakeUnionStorage::from_storage_with_statics_at_zero(item, storage, &DATA_STORE); + let storage_union = FakeUnionStorage::from_storage_with_statics_at_zero(item, storage, &DATA_STORE).unwrap(); let union_indices = storage_union.into_inner_and_outer_indices_with_statics_at_zero(grid_size); - let storage_indices = storage.into_inner_and_outer_indices_with_statics_at_zero(DATA_STORE.num_recipes_with_item[usize_from(item.id)], grid_size, static_size(item, &DATA_STORE)); + let storage_indices = storage.into_inner_and_outer_indices_with_statics_at_zero(item, DATA_STORE.num_recipes_with_item[usize_from(item.id)], grid_size, static_size(item, &DATA_STORE), &DATA_STORE); prop_assert_eq!(union_indices, storage_indices); } diff --git a/src/inserter/storage_storage_inserter.rs b/src/inserter/storage_storage_inserter.rs index 9b1f087..8eb259c 100644 --- a/src/inserter/storage_storage_inserter.rs +++ b/src/inserter/storage_storage_inserter.rs @@ -43,6 +43,7 @@ impl StorageStorageInserter { pub fn update( &mut self, + item_id: usize, storages: SingleItemStorages, movetime: u8, max_hand_size: ITEMCOUNTTYPE, @@ -53,7 +54,8 @@ impl StorageStorageInserter { match self.state { InserterState::WaitingForSourceItems(count) => { - let (_max_insert, old) = index_fake_union(storages, self.storage_id_in, grid_size); + let (_max_insert, old) = + index_fake_union(item_id, storages, self.storage_id_in, grid_size); let to_extract = min(max_hand_size - count, *old); @@ -69,7 +71,8 @@ impl StorageStorageInserter { } }, InserterState::WaitingForSpaceInDestination(count) => { - let (max_insert, old) = index_fake_union(storages, self.storage_id_out, grid_size); + let (max_insert, old) = + index_fake_union(item_id, storages, self.storage_id_out, grid_size); let to_insert = min(count, *max_insert - *old); diff --git a/src/inserter/storage_storage_with_buckets.rs b/src/inserter/storage_storage_with_buckets.rs index 53a2ac4..8492fbc 100644 --- a/src/inserter/storage_storage_with_buckets.rs +++ b/src/inserter/storage_storage_with_buckets.rs @@ -653,7 +653,8 @@ impl BucketedStorageStorageInserterStore { _current_tick: u32, _movetime: u16, ) -> bool { - let (_max_insert, old) = index_fake_union(storages, inserter.storage_id_in, grid_size); + let (_max_insert, old) = + index_fake_union(todo!(), storages, inserter.storage_id_in, grid_size); let to_extract = min(inserter.max_hand_size - inserter.current_hand, *old); @@ -686,7 +687,8 @@ impl BucketedStorageStorageInserterStore { _current_tick: u32, _movetime: u16, ) -> bool { - let (max_insert, old) = index_fake_union(storages, inserter.storage_id_out, grid_size); + let (max_insert, old) = + index_fake_union(todo!(), storages, inserter.storage_id_out, grid_size); let to_insert = min(inserter.current_hand, *max_insert - *old); diff --git a/src/inserter/storage_storage_with_buckets_indirect.rs b/src/inserter/storage_storage_with_buckets_indirect.rs index 305ffc5..475a111 100644 --- a/src/inserter/storage_storage_with_buckets_indirect.rs +++ b/src/inserter/storage_storage_with_buckets_indirect.rs @@ -272,6 +272,7 @@ impl BucketedStorageStorageInserterStore { } fn handle_waiting_for_item_ins( + item_id: usize, inserter: &mut InserterState, bucket_data: &mut InserterBucketData, @@ -282,7 +283,7 @@ impl BucketedStorageStorageInserterStore { ) -> bool { let storage_id = bucket_data.storage_id_in; - let (_max_insert, old) = index_fake_union(storages, storage_id, grid_size); + let (_max_insert, old) = index_fake_union(item_id, storages, storage_id, grid_size); let old_val = *old; let max_hand_size = bucket_data.max_hand_size; @@ -309,6 +310,7 @@ impl BucketedStorageStorageInserterStore { } fn handle_waiting_for_space_ins( + item_id: usize, inserter: &mut InserterState, bucket_data: &mut InserterBucketData, @@ -319,7 +321,7 @@ impl BucketedStorageStorageInserterStore { ) -> bool { let storage_id = bucket_data.storage_id_out; - let (max_insert, old) = index_fake_union(storages, storage_id, grid_size); + let (max_insert, old) = index_fake_union(item_id, storages, storage_id, grid_size); let old_val = *old; let max_insert = *max_insert; @@ -456,6 +458,7 @@ impl BucketedStorageStorageInserterStore { ); let now_moving = self.waiting_for_item.extract_if(start..end, |inserter| { Self::handle_waiting_for_item_ins( + item_id, &mut self.inserters[inserter.index.index as usize], inserter, storages, @@ -529,6 +532,7 @@ impl BucketedStorageStorageInserterStore { self.waiting_for_space_in_destination .extract_if(start..end, |inserter| { Self::handle_waiting_for_space_ins( + item_id, &mut self.inserters[inserter.index.index as usize], inserter, storages, diff --git a/src/lab.rs b/src/lab.rs index ca53c87..969f3a6 100644 --- a/src/lab.rs +++ b/src/lab.rs @@ -26,7 +26,7 @@ pub struct MultiLabStore { pub sciences: Box<[Vec]>, timer: Vec, prod_timer: Vec, - holes: Vec, + pub holes: Vec, /// Base Crafting Speed in 5% increments /// i.e. 28 => 140% Crafting speed diff --git a/src/liquid/mod.rs b/src/liquid/mod.rs index c199187..3a4cc58 100644 --- a/src/liquid/mod.rs +++ b/src/liquid/mod.rs @@ -682,6 +682,7 @@ impl FluidSystemStore { { if *inc == old_storage { *inc = new_storage; + log::trace!("Found connection to update"); } } for outgoing in self.fluid_systems_with_fluid[fluid.into_usize()][id.index] @@ -693,10 +694,13 @@ impl FluidSystemStore { { if *outgoing == old_storage { *outgoing = new_storage; + log::trace!("Found connection to update"); } } }, - None => {}, + None => { + log::trace!("No need to update fluid connections for empty fluid network"); + }, } } @@ -1553,6 +1557,7 @@ impl FluidSystem { } pub fn update_fluid_system( + item_id: usize, hot_data: &mut FluidSystemHotData, storages: SingleItemStorages, grid_size: usize, @@ -1566,7 +1571,7 @@ pub fn update_fluid_system( if hot_data.current_fluid_level == 0 { break; } - let (max, data) = index_fake_union(storages, outgoing_conn, grid_size); + let (max, data) = index_fake_union(item_id, storages, outgoing_conn, grid_size); let amount_wanted = *max - *data; let amount_extracted = min( @@ -1592,7 +1597,7 @@ pub fn update_fluid_system( if hot_data.current_fluid_level == hot_data.storage_capacity { break; } - let (_max, data) = index_fake_union(storages, incoming_conn, grid_size); + let (_max, data) = index_fake_union(item_id, storages, incoming_conn, grid_size); let amount_wanted = *data; let amount_extracted = min( diff --git a/src/par_generation.rs b/src/par_generation.rs index 62cd876..5634961 100644 --- a/src/par_generation.rs +++ b/src/par_generation.rs @@ -1425,7 +1425,8 @@ fn pipe_stage( _ => unreachable!(), }, data_store, - ), + ) + .unwrap(), pos, ) }), diff --git a/src/power/mod.rs b/src/power/mod.rs index 0d84e66..1126760 100644 --- a/src/power/mod.rs +++ b/src/power/mod.rs @@ -341,12 +341,51 @@ impl PowerGridStorage true, + _ => false, + }) + .count(); + let num_labs_in_sim = + grid.lab_stores.sciences[0].len() - grid.lab_stores.holes.len(); + + assert_eq!(num_labs_in_list, num_labs_in_graph); + assert_eq!(num_labs_in_list, num_labs_in_sim); + + let num_assemblers_in_list: usize = + grid.num_assemblers_of_type.iter().copied().sum(); + let num_assemblers_in_graph = grid + .grid_graph + .weak_components() + .filter(|grid_entity| match grid_entity { + (_, PowerGridEntity::Assembler { .. }) => true, + _ => false, + }) + .count(); + let num_assemblers_in_sim: usize = grid.stores.num_assemblers(); + + assert_eq!(num_assemblers_in_list, num_assemblers_in_graph); + assert_eq!(num_assemblers_in_list, num_assemblers_in_sim); + } + } let mut connected_poles: Vec<_> = connected_poles.into_iter().collect(); let ret = if !connected_poles.is_empty() { // Find the largest grid, and choose it as the base // If the size is a tossup pick the one with the smaller grid_id to reduce holes in the power_grid list - let grid = connected_poles + let kept_grid_id = connected_poles .iter() .map(|pos| self.pole_pos_to_grid_id[pos]) .max_by_key(|grid_id| { @@ -364,7 +403,7 @@ impl PowerGridStorage PowerGridStorage>() { // No need to merge a grid with itself. - if other_grid == grid { + if other_grid == kept_grid_id { continue; } ran_once = true; let storage_updates = self .merge_power_grids( - grid, + kept_grid_id, other_grid, data_store, pole_position, connected_poles.iter().copied(), ) .into_iter() - .flatten(); + .flatten() + .map(|update| { + // TODO: Make debug assert + assert_eq!(update.new_grid, kept_grid_id); + assert_eq!(update.old_grid, other_grid); + + update + }); + let old_len = storage_update_vec.len(); storage_update_vec.extend(storage_updates); + let new_updates = storage_update_vec.len() - old_len; } assert!(ran_once); #[cfg(debug_assertions)] { - for key in self.power_grids[grid as usize].grid_graph.keys() { + for key in self.power_grids[kept_grid_id as usize].grid_graph.keys() { if let Some(index) = connected_poles.iter().position(|v| v == key) { connected_poles.remove(index); } @@ -419,7 +467,7 @@ impl PowerGridStorage PowerGridStorage { max_lazy_power: Watt, pub last_power_mult: u8, + pub power_mult_at_last_beacon_update: u8, pub power_mult_history: Timeline, // FIXME: Not actually storing where the power consumption/production originates is not very useful :/ // pub power_consumption_history: Timeline, @@ -209,6 +210,7 @@ impl PowerGrid PowerGrid PowerGrid PowerGrid= other.power_mult_at_last_beacon_update { + self.power_mult_at_last_beacon_update + } else { + other.power_mult_at_last_beacon_update + } + }, power_mult_history: { if self.last_power_consumption >= other.last_power_consumption { self.power_mult_history @@ -2312,6 +2324,7 @@ impl PowerGrid, ) -> ( ResearchProgress, @@ -2641,23 +2654,65 @@ impl PowerGrid, (_, _, _))> = if next_power_mult - < MIN_BEACON_POWER_MULT - && self.last_power_mult >= MIN_BEACON_POWER_MULT - { - // Disable beacons (But keep power consumption modifier unchanged, to prevent flickering) - self.beacon_affected_entities - .iter() - .map(|(k, v)| (*k, (-v.0, -v.1, -0))) - .collect() - } else if next_power_mult >= MIN_BEACON_POWER_MULT - && self.last_power_mult < MIN_BEACON_POWER_MULT - { - // Enable beacons (But keep power consumption modifier unchanged, to prevent flickering) - self.beacon_affected_entities - .iter() - .map(|(k, v)| (*k, (v.0, v.1, 0))) - .collect() + // let beacon_updates: Vec<(BeaconAffectedEntity<_>, (_, _, _))> = if next_power_mult + // < MIN_BEACON_POWER_MULT + // && self.last_power_mult >= MIN_BEACON_POWER_MULT + // { + // // Disable beacons (But keep power consumption modifier unchanged, to prevent flickering) + // self.beacon_affected_entities + // .iter() + // .map(|(k, v)| (*k, (-v.0, -v.1, -0))) + // .collect() + // } else if next_power_mult >= MIN_BEACON_POWER_MULT + // && self.last_power_mult < MIN_BEACON_POWER_MULT + // { + // // Enable beacons (But keep power consumption modifier unchanged, to prevent flickering) + // self.beacon_affected_entities + // .iter() + // .map(|(k, v)| (*k, (v.0, v.1, 0))) + // .collect() + // } else { + // vec![] + // }; + + // This is scaling beacon effect linearly + // FIXME: For this to be correct, when adding a beacon/adding modules to beacon etc, we need to calculate the effect the same way + + // TODO: AFAIK Factorio does not update the effects of beacons every tick but more sparsely (to save UPS) + // For now I will do the same, and only update the beacon effectiveness every 60 ticks (1/seconds) + // We are still much more effective than Factorio here since AFAIK, they need to update beacosn even if the power satisfaction (and as such the beacon effect) did not change + // In that case I can just not do any updates + let beacon_updates = if current_tick % 60 == 0 { + let ret = if next_power_mult != self.power_mult_at_last_beacon_update { + profiling::scope!("Generate Beacon updates"); + self.beacon_affected_entities + .iter() + .map(|(&entity, &effect)| { + let effect: [i16; 3] = effect.into(); + let old_effect = effect.map(|e| { + i32::from(e) * i32::from(self.power_mult_at_last_beacon_update) / 64 + }); + let new_effect = + effect.map(|e| i32::from(e) * i32::from(next_power_mult) / 64); + + let change = old_effect + .into_iter() + .zip(new_effect) + .map(|(old, new)| new - old) + .map(|v| v.try_into().unwrap()) + .collect_array() + .unwrap(); + + (entity, change.into()) + }) + .collect() + } else { + vec![] + }; + + self.power_mult_at_last_beacon_update = next_power_mult; + + ret } else { vec![] }; diff --git a/src/rendering/eframe_app.rs b/src/rendering/eframe_app.rs index 85b3864..10a12c9 100644 --- a/src/rendering/eframe_app.rs +++ b/src/rendering/eframe_app.rs @@ -325,7 +325,7 @@ impl eframe::App for App { game_state_receiver: recv, }; } - } + } // else if ui.button("Load Debug Save").clicked() { // #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] // if let Some(path) = rfd::FileDialog::new() diff --git a/src/rendering/mod.rs b/src/rendering/mod.rs index d3782ca..62a9ac8 100644 --- a/src/rendering/mod.rs +++ b/src/rendering/mod.rs @@ -169,6 +169,8 @@ pub struct TextureAtlas { underground: enum_map::EnumMap>, + accumulator: EntitySprite, + mining_drill: EntitySprite, solar_panel: EntitySprite, @@ -273,6 +275,7 @@ fn texture_atlas() -> TextureAtlas { no_power: entity_sprite_from_path_scaled!("temp_assets/no_power.png", 1, 1.0), assembler: entity_sprite_from_path_tiling!("temp_assets/assembler.png", 1), + accumulator: entity_sprite_from_path_tiling!("temp_assets/assembler.png", 1), chest: entity_sprite_from_path_tiling!("temp_assets/outside_world.png", 1), items: vec![sprite_from_path!("temp_assets/plate.png", 1); 200].into_boxed_slice(), @@ -495,6 +498,8 @@ fn texture_atlas() -> TextureAtlas { 1.0 / 2.0 ), + accumulator: entity_sprite_from_path_tiling!("temp_assets/krastorio/energy-storage.png", 1), + lab: entity_sprite_from_path_tiling!("temp_assets/krastorio/advanced-lab.png", 1), dark_square: sprite_from_path!("temp_assets/dark_square.png", 1), diff --git a/src/rendering/render_world.rs b/src/rendering/render_world.rs index 30ee5a2..7f57a49 100644 --- a/src/rendering/render_world.rs +++ b/src/rendering/render_world.rs @@ -1,6 +1,6 @@ use crate::belt::belt::Belt; -use crate::belt::smart::{HAND_SIZE, NUM_BELT_LOCS_SEARCHED, SmartBelt}; use crate::belt::smart::{NUM_BELT_FREE_CACHE_HITS, NUM_BELT_UPDATES}; +use crate::belt::smart::{NUM_BELT_LOCS_SEARCHED, SmartBelt}; use crate::blueprint::blueprint_string::BlueprintString; use crate::chest::ChestSize; use crate::frontend::action::action_state_machine::ForkSaveInfo; @@ -909,11 +909,16 @@ pub fn render_world( let movetime: u16 = user_movetime.map(|v| v.into()).unwrap_or(data_store.inserter_infos[*ty as usize].swing_time_ticks).into(); match info { crate::frontend::world::tile::AttachedInserter::BeltStorage { id, belt_pos } => { - let hand_size = HAND_SIZE; let Some(state) = game_state.simulation_state.factory.belts.get_inserter_info_at(*id, *belt_pos) else { error!("Could not get rendering info for inserter!"); continue; }; + let hand_size = state.hand_size; + + // TODO: Due to clamping this does not currently hold: + // assert_eq!(movetime, u16::from(state.movetime)); + let movetime = u16::from(state.movetime); + let item = game_state.simulation_state.factory.belts.get_inserter_item(*id, *belt_pos); let (mut position, items): (f32, ITEMCOUNTTYPE) = match state.state { @@ -960,7 +965,7 @@ pub fn render_world( // TODO: }, crate::frontend::world::tile::AttachedInserter::StorageStorage { item, inserter } => { - let hand_size = HAND_SIZE; + let hand_size = data_store.inserter_infos[*ty as usize].base_hand_size; let item = *item; let state = game_state.simulation_state.factory.storage_storage_inserters.get_inserter(item, movetime, *inserter, current_tick); @@ -1205,7 +1210,7 @@ pub fn render_world( [usize::from(*ty)].size, 0, entity_layer); }, Entity::Accumulator { ty, pos, .. } => { - texture_atlas.chest.draw([ + texture_atlas.accumulator.draw([ draw_offset.0 + pos.x as f32, draw_offset.1 + pos.y as f32, ], data_store.solar_panel_info @@ -1702,7 +1707,7 @@ pub fn render_world( ); }, crate::frontend::world::tile::PlaceEntityType::Accumulator { pos, ty } => { - texture_atlas.chest.draw( + texture_atlas.accumulator.draw( [draw_offset.0 + pos.x as f32, draw_offset.1 + pos.y as f32], data_store.accumulator_info[usize::from(*ty)].size, 0, @@ -2201,7 +2206,6 @@ pub fn render_ui< lower_dec = 1.0; } - dbg!(lower_dec); lower_dec = lower_dec * ticks_per_value / 60.0 / 60.0; (0..40) @@ -2299,7 +2303,7 @@ pub fn render_ui< actions.push(ActionType::Remove(assembler_pos)); - let area = data_store.mining_drill_info[1].size(*rotation); + let area = data_store.mining_drill_info[0].size(*rotation); for x in assembler_pos.x..(assembler_pos.x + i32::from(area[0])) { for y in assembler_pos.y..(assembler_pos.y + i32::from(area[1])) { @@ -2332,7 +2336,7 @@ pub fn render_ui< entities: EntityPlaceOptions::Single(PlaceEntityType::MiningDrill { pos: assembler_pos, rotation: inserter_rotation, - ty: 1, + ty: 0, }), force: false, })); diff --git a/src/rendering/temp_assets/krastorio/energy-storage.png b/src/rendering/temp_assets/krastorio/energy-storage.png new file mode 100644 index 0000000..8629c67 Binary files /dev/null and b/src/rendering/temp_assets/krastorio/energy-storage.png differ diff --git a/src/storage_list.rs b/src/storage_list.rs index 3c2e82b..cfd7281 100644 --- a/src/storage_list.rs +++ b/src/storage_list.rs @@ -1,3 +1,4 @@ +use core::panic; use std::iter; use std::u16; @@ -5,6 +6,7 @@ use itertools::Itertools; use rayon::iter::IndexedParallelIterator; use strum::IntoEnumIterator; +use crate::DATA_STORE; use crate::assembler::MultiAssemblerStore; use crate::chest::MultiChestStore; use crate::item::Indexable; @@ -132,6 +134,7 @@ pub fn index<'a, 'b, RecipeIdxType: IdxTrait>( #[inline(always)] pub fn index_fake_union<'a, 'b>( + item_id: usize, slice: SingleItemStorages<'a, 'b>, storage_id: FakeUnionStorage, grid_size: usize, @@ -144,7 +147,94 @@ pub fn index_fake_union<'a, 'b>( "Out slice was out of bounds for storage_id {storage_id:?}. len was {len}, index was {outer}, grid_size was {grid_size}.", ); }; - (&subslice.0[inner], &mut subslice.1[inner]) + + let Some(max_insert) = subslice.0.get(inner) else { + let item = Item { + id: item_id.try_into().unwrap(), + }; + let static_size: usize = static_size(item, &DATA_STORE); + let is_static = (storage_id.grid_or_static_flag as usize) < static_size; + let index = storage_id.index; + + if !is_static { + let grid_id = storage_id.grid_or_static_flag as usize - static_size; + + let recipe = DATA_STORE.recipe_to_translated_index.iter().find( + |((_recipe, found_item), index)| { + item == *found_item + && u16::from(**index) == storage_id.recipe_idx_with_this_item + }, + ); + + if let Some(((r, _), _)) = recipe { + // we are a assembler + panic!( + "Failed FakeUnion Index for item {} for Assembler in grid {}, with recipe {} and index {}", + &DATA_STORE.item_names[item_id], + grid_id, + DATA_STORE.recipe_names[r.into_usize()], + index + ); + } else { + // We are a lab + panic!( + "Failed FakeUnion Index for item {} for Lab in grid {}, with index {}", + &DATA_STORE.item_names[item_id], grid_id, index + ); + } + } else { + let static_id = StaticID::try_from(storage_id.recipe_idx_with_this_item as u8).unwrap(); + + panic!( + "Failed FakeUnion Index for item {} for Static {:?}, with index {}", + &DATA_STORE.item_names[item_id], static_id, index + ); + } + }; + let Some(items) = subslice.1.get_mut(inner) else { + let item = Item { + id: item_id.try_into().unwrap(), + }; + let static_size: usize = static_size(item, &DATA_STORE); + let is_static = (storage_id.grid_or_static_flag as usize) < static_size; + let index = storage_id.index; + + if !is_static { + let grid_id = storage_id.grid_or_static_flag as usize - static_size; + + let recipe = DATA_STORE.recipe_to_translated_index.iter().find( + |((_recipe, found_item), index)| { + item == *found_item + && u16::from(**index) == storage_id.recipe_idx_with_this_item + }, + ); + + if let Some(((r, _), _)) = recipe { + // we are a assembler + panic!( + "Failed FakeUnion Index for item {} for Assembler in grid {}, with recipe {} and index {}", + &DATA_STORE.item_names[item_id], + grid_id, + DATA_STORE.recipe_names[r.into_usize()], + index + ); + } else { + // We are a lab + panic!( + "Failed FakeUnion Index for item {} for Lab in grid {}, with index {}", + &DATA_STORE.item_names[item_id], grid_id, index + ); + } + } else { + let static_id = StaticID::try_from(storage_id.recipe_idx_with_this_item as u8).unwrap(); + + panic!( + "Failed FakeUnion Index for item {} for Static {:?}, with index {}", + &DATA_STORE.item_names[item_id], static_id, index + ); + } + }; + (max_insert, items) } #[profiling::function] diff --git a/test_blueprints/solar_tile.bp b/test_blueprints/solar_tile.bp index 392ce4e..3934598 100644 --- a/test_blueprints/solar_tile.bp +++ b/test_blueprints/solar_tile.bp @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c00805e515c34c57351071faa8c70b8891f0541ad4bae04c6f4ec0fec70ef02 -size 592 +oid sha256:9ffa0b20b177f29b19871a3b201fb430ef7892c99cb63e83248fec42604e3ec1 +size 572