From 39a5895c12baab11d215617b9aeaeee2c554e342 Mon Sep 17 00:00:00 2001 From: thedarkcolour <30441001+thedarkcolour@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:46:15 -0700 Subject: [PATCH] Rework barrels to use JSON recipes for fluid transformation recipes --- changelog.md | 6 + .../9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e | 87 ++++----- .../witch_water.json | 20 ++ .../recipes/lava_crucible/cobblestone.json | 4 +- .../recipes/lava_crucible/gravel.json | 4 +- .../recipes/lava_crucible/netherrack.json | 4 +- .../exdeorum/recipes/lava_crucible/stone.json | 4 +- .../diamond/iron_ore_chunk.json | 2 +- .../flint/iron_ore_chunk.json | 2 +- .../golden/iron_ore_chunk.json | 2 +- .../iron/iron_ore_chunk.json | 2 +- .../netherite/iron_ore_chunk.json | 2 +- .../string/iron_ore_chunk.json | 2 +- .../sieve/gravel/diamond/iron_ore_chunk.json | 2 +- .../sieve/gravel/flint/iron_ore_chunk.json | 2 +- .../sieve/gravel/golden/iron_ore_chunk.json | 2 +- .../sieve/gravel/iron/iron_ore_chunk.json | 2 +- .../gravel/netherite/iron_ore_chunk.json | 2 +- .../sieve/gravel/string/iron_ore_chunk.json | 2 +- .../recipes/water_crucible/apple.json | 4 +- .../recipes/water_crucible/beetroot.json | 4 +- .../recipes/water_crucible/cactus.json | 4 +- .../recipes/water_crucible/carrot.json | 4 +- .../recipes/water_crucible/grass.json | 4 +- .../recipes/water_crucible/grass_block.json | 4 +- .../recipes/water_crucible/leaves.json | 4 +- .../recipes/water_crucible/lily_pad.json | 4 +- .../recipes/water_crucible/melon.json | 4 +- .../recipes/water_crucible/melon_slice.json | 4 +- .../exdeorum/recipes/water_crucible/moss.json | 4 +- .../recipes/water_crucible/moss_carpet.json | 4 +- .../recipes/water_crucible/mushrooms.json | 4 +- .../recipes/water_crucible/potato.json | 4 +- .../recipes/water_crucible/pumpkin.json | 4 +- .../recipes/water_crucible/saplings.json | 4 +- .../recipes/water_crucible/sea_pickle.json | 4 +- .../recipes/water_crucible/seagrass.json | 4 +- .../recipes/water_crucible/seeds.json | 4 +- .../water_crucible/seeds_and_spores.json | 4 +- .../recipes/water_crucible/small_flowers.json | 4 +- .../recipes/water_crucible/spore_blossom.json | 4 +- .../recipes/water_crucible/sugar_cane.json | 4 +- .../recipes/water_crucible/sweet_berries.json | 4 +- .../recipes/water_crucible/tall_flowers.json | 4 +- .../exdeorum/recipes/water_crucible/vine.json | 4 +- .../exdeorum/block/BarrelBlock.java | 6 +- .../AbstractCrucibleBlockEntity.java | 9 +- .../blockentity/BarrelBlockEntity.java | 176 +++++++++--------- .../blockentity/helper/FluidHelper.java | 45 ++++- .../exdeorum/client/ter/BarrelRenderer.java | 15 +- .../exdeorum/compat/PreferredOres.java | 1 + .../compat/kubejs/ExDeorumKubeJsBindings.java | 19 +- .../exdeorum/data/recipe/Recipes.java | 15 +- .../exdeorum/fluid/WitchWaterFluid.java | 6 +- .../exdeorum/recipe/CodecUtil.java | 36 ---- .../exdeorum/recipe/EFinishedRecipe.java | 17 +- .../exdeorum/recipe/RecipeUtil.java | 98 +++++++++- .../exdeorum/recipe/WeightedList.java | 161 ++++++++++++++++ .../barrel/BarrelFluidMixingRecipe.java | 2 +- .../barrel/FinishedBarrelCompostRecipe.java | 10 +- .../FinishedBarrelFluidMixingRecipe.java | 18 +- .../barrel/FinishedBarrelMixingRecipe.java | 10 +- .../FinishedFluidTransformationRecipe.java | 64 +++++++ .../barrel/FluidTransformationRecipe.java | 165 ++++++++++++++++ .../cache/FluidTransformationRecipeCache.java | 69 +++++++ .../exdeorum/recipe/crook/CrookRecipe.java | 2 +- .../recipe/crook/FinishedCrookRecipe.java | 10 +- .../recipe/crucible/CrucibleHeatRecipe.java | 2 +- .../recipe/crucible/CrucibleRecipe.java | 5 +- .../crucible/FinishedCrucibleHeatRecipe.java | 10 +- .../crucible/FinishedCrucibleRecipe.java | 15 +- .../recipe/hammer/FinishedHammerRecipe.java | 10 +- .../recipe/sieve/FinishedSieveRecipe.java | 10 +- .../exdeorum/registry/ERecipeSerializers.java | 2 + .../exdeorum/registry/ERecipeTypes.java | 2 + .../recipe/RecipeSerializationTests.java | 32 +++- .../exdeorum/recipe/RecipeUtilTest.java | 25 +++ .../exdeorum/recipe/WeightedListTest.java | 105 +++++++++++ 78 files changed, 1070 insertions(+), 359 deletions(-) create mode 100644 src/generated/resources/data/exdeorum/recipes/barrel_fluid_transformation/witch_water.json delete mode 100644 src/main/java/thedarkcolour/exdeorum/recipe/CodecUtil.java create mode 100644 src/main/java/thedarkcolour/exdeorum/recipe/WeightedList.java create mode 100644 src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedFluidTransformationRecipe.java create mode 100644 src/main/java/thedarkcolour/exdeorum/recipe/barrel/FluidTransformationRecipe.java create mode 100644 src/main/java/thedarkcolour/exdeorum/recipe/cache/FluidTransformationRecipeCache.java create mode 100644 src/test/java/thedarkcolour/exdeorum/recipe/WeightedListTest.java diff --git a/changelog.md b/changelog.md index 630e41dc..98ebb904 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,9 @@ +## Ex Deorum 1.26 +- Fluid transformation recipes are now data driven +- Increased drop rate of Iron Ore Chunk +- Updated documentation to explain how to add Ex Deorum recipes through JSON data packs. If you are using KubeJS/CraftTweaker, this will probably be useful to you as well. Check it out [here](https://exdeorum.readthedocs.io/en/latest/datapack/). +- Fixed Witch Water spawning mushrooms when not converting (now, they only spawn while converting from water to witch water) + ## Ex Deorum 1.25 - Fixed crash with fluid containers - Added `exdeorum:summation` result count type for sieve recipes, mostly for converting Ex Nihilo Sequentia recipes over (also usable for loot tables) diff --git a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e index 3aa35b8b..baa3deae 100644 --- a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e +++ b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e @@ -1,4 +1,4 @@ -// 1.20.1 2024-02-13T15:52:36.681433 Recipes +// 1.20.1 2024-03-11T16:13:53.5720006 Recipes e37b64428f17e304e91539ac0513456d7ce40cd1 data/exdeorum/advancements/recipes/building_blocks/sponge.json 5ad481a0c376c1a1785a5d3b992064d0ec0bf3b0 data/exdeorum/advancements/recipes/food/end_cake.json 25dd027e844a72b03c95dbe5e3c3dd8c738ceb00 data/exdeorum/advancements/recipes/misc/acacia_barrel.json @@ -174,6 +174,7 @@ b9a34df74ce0ee9c4247a9a64784c851eb1de58c data/exdeorum/recipes/barrel_compost/wo 6d2469e79cbc88817a4582fa467857d65d9b70ed data/exdeorum/recipes/barrel_fluid_mixing/obsidian.json 4657af4003335ca25d2f92c43fd82dc3b3ad7fb2 data/exdeorum/recipes/barrel_fluid_mixing/slime_block.json 5e2a7bd06a83260c18c007bcf793c336faef264d data/exdeorum/recipes/barrel_fluid_mixing/stone.json +89c033548e54ca28030b79f07249787b51d7db7d data/exdeorum/recipes/barrel_fluid_transformation/witch_water.json bdcdeae9d06028ce943d06c367b58677efe03fa8 data/exdeorum/recipes/barrel_mixing/clay.json 72f969f4db1f82a627df573c866a1b291e540a0a data/exdeorum/recipes/barrel_mixing/end_stone.json 37f73e219fda3c6f56bf55f8ec7f97586ecdbae1 data/exdeorum/recipes/barrel_mixing/ice.json @@ -298,10 +299,10 @@ f1368be282014a882ece8c28d43ea1d3f8c19ad2 data/exdeorum/recipes/jacaranda_sieve.j 332d5396af038b56047e88fcad713478e45cbd97 data/exdeorum/recipes/jungle_barrel.json 7239040d0cee42fe9077c89eaa3d768a07db0557 data/exdeorum/recipes/jungle_crucible.json bffa756563ac5aa791f299ae6d7d042813c2614a data/exdeorum/recipes/jungle_sieve.json -d24ed2178e5875da5e0a6f82b5ac9c2ece4b64ff data/exdeorum/recipes/lava_crucible/cobblestone.json -0963c17c9f78907017fa0192c684f016c39f31eb data/exdeorum/recipes/lava_crucible/gravel.json -e9affa16c926fe63ca2270a81aba4e33cd0b198b data/exdeorum/recipes/lava_crucible/netherrack.json -20744c980e4a68f67acea24af617f1ddb865f9a3 data/exdeorum/recipes/lava_crucible/stone.json +83f2a9b35dbee148a7f74e2bd3d85daa8f276c74 data/exdeorum/recipes/lava_crucible/cobblestone.json +9058a167bc4eab87e02be115ae6391aafd82177d data/exdeorum/recipes/lava_crucible/gravel.json +f6c2801f5410a26fba7ff632b5c7ce80d2df3042 data/exdeorum/recipes/lava_crucible/netherrack.json +6dd34eedb61a5063e283739ee1e033f52cfb6607 data/exdeorum/recipes/lava_crucible/stone.json de4aec27404547b2cc9a709e54eba1459c210149 data/exdeorum/recipes/lunar_barrel.json 848e724409a1ade08e1d40a28b6d570e0362cb45 data/exdeorum/recipes/lunar_crucible.json 6760d41983e3553c785f251c1ab4813db7312b32 data/exdeorum/recipes/lunar_sieve.json @@ -399,7 +400,7 @@ c546193f9cab7af9c92ea4a05c080c2ea24f33a2 data/exdeorum/recipes/sieve/crushed_dee db7026d3f31ec9a4e2ac085101a49cbcbc67b712 data/exdeorum/recipes/sieve/crushed_deepslate/diamond/emerald.json 69e4b707f2e433bda0742dfbba9223f0d4dbf872 data/exdeorum/recipes/sieve/crushed_deepslate/diamond/gold_ore_chunk.json b60486888c693bef336989c8e36b62f8bc60ce28 data/exdeorum/recipes/sieve/crushed_deepslate/diamond/iridium_ore_chunk.json -91dabfb0a3256393d74779c2bc291a0b13f93eb4 data/exdeorum/recipes/sieve/crushed_deepslate/diamond/iron_ore_chunk.json +daf4aea771f0bd538b42af2788dfb6bf64ea4398 data/exdeorum/recipes/sieve/crushed_deepslate/diamond/iron_ore_chunk.json fa548967f2323aa67b8b0adb3802cb513047dff7 data/exdeorum/recipes/sieve/crushed_deepslate/diamond/lapis_lazuli.json 1918afd9a0af6536a5a4c0fd90d11143f90f937e data/exdeorum/recipes/sieve/crushed_deepslate/diamond/lead_ore_chunk.json fce785ad95a0f7c2f5077c7fe2f98ce64e3d4f92 data/exdeorum/recipes/sieve/crushed_deepslate/diamond/lithium_ore_chunk.json @@ -421,7 +422,7 @@ d789f6cde58525c3fe965eb40ececa89e4ee8241 data/exdeorum/recipes/sieve/crushed_dee f90e1a71760aea8e3bede5b4ad8607c172e42b0e data/exdeorum/recipes/sieve/crushed_deepslate/flint/emerald.json 925ebffabfed246a52990df6db690d64b3242875 data/exdeorum/recipes/sieve/crushed_deepslate/flint/gold_ore_chunk.json 05d695f74dea3e675f4b85bb42174c97a57cf96c data/exdeorum/recipes/sieve/crushed_deepslate/flint/iridium_ore_chunk.json -c8053bbcfc5f7b8933e09517b6457578401603db data/exdeorum/recipes/sieve/crushed_deepslate/flint/iron_ore_chunk.json +93ceac1deecc354104bcfc881fab201754fcb18c data/exdeorum/recipes/sieve/crushed_deepslate/flint/iron_ore_chunk.json 28d91d9c411f7a1d9daec605b3c1a204e75f063a data/exdeorum/recipes/sieve/crushed_deepslate/flint/lapis_lazuli.json 7b3cc3cf4af738377cef6d50dae392fc64e8848d data/exdeorum/recipes/sieve/crushed_deepslate/flint/lead_ore_chunk.json eb1dc810e1f4ba76ce23b0799acfbc5f43e34eb7 data/exdeorum/recipes/sieve/crushed_deepslate/flint/lithium_ore_chunk.json @@ -443,7 +444,7 @@ a4b81bbfbeb70efa064fe6ea1eea68b6f2da96c8 data/exdeorum/recipes/sieve/crushed_dee 355bbd4ef545137d3d1a0754f272297dbec3e1b7 data/exdeorum/recipes/sieve/crushed_deepslate/golden/gold_nugget.json 7d701e272f47a5029786c2a59ceed24a8a6fe339 data/exdeorum/recipes/sieve/crushed_deepslate/golden/gold_ore_chunk.json 21ca6821d3f1e259eb4efa2046bd53315f588b21 data/exdeorum/recipes/sieve/crushed_deepslate/golden/iridium_ore_chunk.json -93ace70556c0b59bfd2de7b14562506b032dbb46 data/exdeorum/recipes/sieve/crushed_deepslate/golden/iron_ore_chunk.json +22093b07c1075eb377848e39675704cb1f89e833 data/exdeorum/recipes/sieve/crushed_deepslate/golden/iron_ore_chunk.json f82704720c2b43f9f482aac5109d00d0419186ff data/exdeorum/recipes/sieve/crushed_deepslate/golden/lapis_lazuli.json c2a7d4076e92291d7b183c9c30f85848a748883b data/exdeorum/recipes/sieve/crushed_deepslate/golden/lead_ore_chunk.json bb0991f3c3362fa59f6221a13637c4a60335c5de data/exdeorum/recipes/sieve/crushed_deepslate/golden/lithium_ore_chunk.json @@ -464,7 +465,7 @@ a573a2731f646884bd3f4ae61136280dde8c2c96 data/exdeorum/recipes/sieve/crushed_dee f1a444b52e9e1696a846592b833a2ceb63c994bc data/exdeorum/recipes/sieve/crushed_deepslate/iron/emerald.json f387102be827d0ad7ef6590bdd97435adc0adb19 data/exdeorum/recipes/sieve/crushed_deepslate/iron/gold_ore_chunk.json 05129a20fdb122ca64e61252ae7011b0189c4c4f data/exdeorum/recipes/sieve/crushed_deepslate/iron/iridium_ore_chunk.json -4a9e056ddaeafce083fa91f4adca89f28e409b42 data/exdeorum/recipes/sieve/crushed_deepslate/iron/iron_ore_chunk.json +7424678a70bbfe69af04e248aa2dbf92ea71b00d data/exdeorum/recipes/sieve/crushed_deepslate/iron/iron_ore_chunk.json e2356f1aa76f9f39f3d9eb71e34b206d567456be data/exdeorum/recipes/sieve/crushed_deepslate/iron/lapis_lazuli.json 9601262f949921d5bdd6c3fe2b8bd1aa75101007 data/exdeorum/recipes/sieve/crushed_deepslate/iron/lead_ore_chunk.json 6988d47f7ac27c7b0c2f43b22080df420a00cae2 data/exdeorum/recipes/sieve/crushed_deepslate/iron/lithium_ore_chunk.json @@ -484,7 +485,7 @@ cdc25d35d8ec98f7cca1a74dd417f3590a839583 data/exdeorum/recipes/sieve/crushed_dee 69c3f29af10cbd0b6a929ea29612e54678687dec data/exdeorum/recipes/sieve/crushed_deepslate/netherite/emerald.json a743371407c1200e19049de0c1cfb7db54e9e224 data/exdeorum/recipes/sieve/crushed_deepslate/netherite/gold_ore_chunk.json 55e3999812bcae17b63f1815782979969733cbd1 data/exdeorum/recipes/sieve/crushed_deepslate/netherite/iridium_ore_chunk.json -641be85ac7300b45c139844316086cb5c30b8599 data/exdeorum/recipes/sieve/crushed_deepslate/netherite/iron_ore_chunk.json +fc19cf491131e9fc0aa47ae2eab42f6cc378a666 data/exdeorum/recipes/sieve/crushed_deepslate/netherite/iron_ore_chunk.json 0d84fa101dd247f42867022a1aa15cb45e719ef3 data/exdeorum/recipes/sieve/crushed_deepslate/netherite/lapis_lazuli.json 2b8244da348847d271355e1cadaa2d08e285bc8f data/exdeorum/recipes/sieve/crushed_deepslate/netherite/lead_ore_chunk.json 95537aa47bd9ad122c4330e70f593ebdee3c7676 data/exdeorum/recipes/sieve/crushed_deepslate/netherite/lithium_ore_chunk.json @@ -504,7 +505,7 @@ e5e179dec565277380d0d0b4e35990c8baeeda65 data/exdeorum/recipes/sieve/crushed_dee 7d3b675754200bcd0d44a1b595a7cd1443ce3f28 data/exdeorum/recipes/sieve/crushed_deepslate/string/emerald.json 744b9140fc69e1cf0a59d72524baf1770d45ae8c data/exdeorum/recipes/sieve/crushed_deepslate/string/gold_ore_chunk.json b37bd819bfe576ac0f75b9eab2a59436832ad1a4 data/exdeorum/recipes/sieve/crushed_deepslate/string/iridium_ore_chunk.json -a2e895b8b68e6cddf045a4dc97f323679e37be60 data/exdeorum/recipes/sieve/crushed_deepslate/string/iron_ore_chunk.json +88bff049d23e5ea9ff4946c3b8deb322ff4abd23 data/exdeorum/recipes/sieve/crushed_deepslate/string/iron_ore_chunk.json c2165469fc079114e44a96c89753e01e276d4f05 data/exdeorum/recipes/sieve/crushed_deepslate/string/lapis_lazuli.json cd1cb531c5e7cdc9c96450e4bf0f411a279d3fd3 data/exdeorum/recipes/sieve/crushed_deepslate/string/lead_ore_chunk.json defb4a676f1e5f08d81ba04acecb452bd497f8ec data/exdeorum/recipes/sieve/crushed_deepslate/string/lithium_ore_chunk.json @@ -744,7 +745,7 @@ ac9139345f1b1d4bd8fb48350d3a6df9a33c2a93 data/exdeorum/recipes/sieve/gravel/diam 66d27aa930f24ab223056cd8e306a62b0d7c91c9 data/exdeorum/recipes/sieve/gravel/diamond/flint.json 3544e4e64e54f9ab80015c8d708e397777cb3212 data/exdeorum/recipes/sieve/gravel/diamond/gold_ore_chunk.json b25b9a23f50fa60719f74ffc26b53017f8d74cd0 data/exdeorum/recipes/sieve/gravel/diamond/iridium_ore_chunk.json -6cf8e4f262fa4e4153bcaa6c684854712f720021 data/exdeorum/recipes/sieve/gravel/diamond/iron_ore_chunk.json +552825678b5e7967289200ad01c1ef6beeefbe06 data/exdeorum/recipes/sieve/gravel/diamond/iron_ore_chunk.json 71084e96ae9c98c76ecb03b38de241b72ad0cf8c data/exdeorum/recipes/sieve/gravel/diamond/lapis_lazuli.json 981752f69c4094f1cb4a8d0272399117eb28f19b data/exdeorum/recipes/sieve/gravel/diamond/lead_ore_chunk.json be9d385c0cb20baf3a5a084d4110e81fae2c2988 data/exdeorum/recipes/sieve/gravel/diamond/magnesium_ore_chunk.json @@ -767,7 +768,7 @@ adfae10501cc5a1f7d13ce93da1fe2b9f2d26624 data/exdeorum/recipes/sieve/gravel/flin d988d062013ae4d6afcb8e5e13065518a012d126 data/exdeorum/recipes/sieve/gravel/flint/gold_ore_chunk.json a3f7e6269846b25acbd994b0e564020f7a22cd0f data/exdeorum/recipes/sieve/gravel/flint/granite_pebble.json cb1601e4e798f148a352d0910a028f594a944d4c data/exdeorum/recipes/sieve/gravel/flint/iridium_ore_chunk.json -1526d58887ae5ca553fb5d6de0edbb4ce85dc916 data/exdeorum/recipes/sieve/gravel/flint/iron_ore_chunk.json +5f08daac6cb75b6fda8441dfc43be424fd2e32ec data/exdeorum/recipes/sieve/gravel/flint/iron_ore_chunk.json 702f85e882f2b10a6613f41074ccfc9b759c42b9 data/exdeorum/recipes/sieve/gravel/flint/lapis_lazuli.json 91d01d076b8a72827d270de34fe03022a44c9291 data/exdeorum/recipes/sieve/gravel/flint/lead_ore_chunk.json 0e26f51a7c57c969447ca398021c10225c38d839 data/exdeorum/recipes/sieve/gravel/flint/magnesium_ore_chunk.json @@ -791,7 +792,7 @@ b910213c60616555b2701eab2e6ed6c10ab2996d data/exdeorum/recipes/sieve/gravel/gold 4f0edad66d6d5899a81fb32c11da8b4f4943e483 data/exdeorum/recipes/sieve/gravel/golden/gold_nugget.json 4be0b7be825c07b1406f45f6b9182d6c0a643cb3 data/exdeorum/recipes/sieve/gravel/golden/gold_ore_chunk.json 5e940efaf67afe5273df3bdea9054e57f2685d52 data/exdeorum/recipes/sieve/gravel/golden/iridium_ore_chunk.json -5a33eb0cec0ddfef976f26708dcc2f55ac7f167e data/exdeorum/recipes/sieve/gravel/golden/iron_ore_chunk.json +bf2e0f336645be47182a8cec4c81ab97d09ead65 data/exdeorum/recipes/sieve/gravel/golden/iron_ore_chunk.json ae0acc3deb886e04d8226b1cbe36e67a8dd360bf data/exdeorum/recipes/sieve/gravel/golden/lapis_lazuli.json 35f01fd1939936fa63ea4c13afda51a444e139e8 data/exdeorum/recipes/sieve/gravel/golden/lead_ore_chunk.json ff3cb01dbb798637b1cbc6bfc3038944595ae519 data/exdeorum/recipes/sieve/gravel/golden/magnesium_ore_chunk.json @@ -814,7 +815,7 @@ e28dd0cc2ae440c324a78b97757266ef0243b94e data/exdeorum/recipes/sieve/gravel/iron 6610b8fb3cb40f1d5e149fe3831d82063add8b5d data/exdeorum/recipes/sieve/gravel/iron/flint.json 5bbb6415d53f5efac6799f654bc3486a277aed31 data/exdeorum/recipes/sieve/gravel/iron/gold_ore_chunk.json 23e6a404d85a3351772fb713b5db7c5582345e4c data/exdeorum/recipes/sieve/gravel/iron/iridium_ore_chunk.json -be90f3b4db2a9e24f218ca9ba2b96bcbb607e693 data/exdeorum/recipes/sieve/gravel/iron/iron_ore_chunk.json +3d355020c82eeed520d8a33a4b35bc5703eaa991 data/exdeorum/recipes/sieve/gravel/iron/iron_ore_chunk.json b8b54b1de7034163b0f679f7e0368530dc15e159 data/exdeorum/recipes/sieve/gravel/iron/lapis_lazuli.json c02f2b1d17c3cdb68ed9b6afd41bd30adbc4fda6 data/exdeorum/recipes/sieve/gravel/iron/lead_ore_chunk.json 68757b584fee704ad0c459b16eab12f729362a5e data/exdeorum/recipes/sieve/gravel/iron/magnesium_ore_chunk.json @@ -836,7 +837,7 @@ cb71ef4f529eafcdc9b37ac05c69d5f382ff85ea data/exdeorum/recipes/sieve/gravel/iron 41aaa9c5a1b61ea79b231528a6e76c9c1d273331 data/exdeorum/recipes/sieve/gravel/netherite/gold_nugget.json 22a8a86bd12d7db9a4929121692dccfe3616a942 data/exdeorum/recipes/sieve/gravel/netherite/gold_ore_chunk.json f2c95dc2b7bee18aa27ad336ad470957050148d3 data/exdeorum/recipes/sieve/gravel/netherite/iridium_ore_chunk.json -e28a30509e84956d6d193911cfe8ba252a2825cf data/exdeorum/recipes/sieve/gravel/netherite/iron_ore_chunk.json +ad8d3754eb5262296af4131a484c812628dd7d08 data/exdeorum/recipes/sieve/gravel/netherite/iron_ore_chunk.json 8f49a2cdf84583537955e4c27c854bf34dc47903 data/exdeorum/recipes/sieve/gravel/netherite/lapis_lazuli.json f12a4bd98ef79dd7e9073d1626e8294f11f900ae data/exdeorum/recipes/sieve/gravel/netherite/lead_ore_chunk.json 61dda81ce471e511fc24d01c84866549a0c2888a data/exdeorum/recipes/sieve/gravel/netherite/magnesium_ore_chunk.json @@ -857,7 +858,7 @@ bd1ce763ae605e9a0d82e4afa58c4811516bc6bf data/exdeorum/recipes/sieve/gravel/stri b298e2f51255b88beea1394e2f609768fbb36921 data/exdeorum/recipes/sieve/gravel/string/flint.json 0c0e184928b7371b1cabaca16b51d137a52fc77b data/exdeorum/recipes/sieve/gravel/string/gold_ore_chunk.json 1a3a7eba846fb34fa5391dc7fb29509011a7f88c data/exdeorum/recipes/sieve/gravel/string/iridium_ore_chunk.json -8006ea24e8d9c89a1886e806659ab1bb733da534 data/exdeorum/recipes/sieve/gravel/string/iron_ore_chunk.json +cbe0eed19afb1c57760aafa210546a38e265f287 data/exdeorum/recipes/sieve/gravel/string/iron_ore_chunk.json 19ddad521fcb43ea69e4aeda92f8ea841630c530 data/exdeorum/recipes/sieve/gravel/string/lapis_lazuli.json f245cf69e06874c43bc2bdaabb7806c59d274c93 data/exdeorum/recipes/sieve/gravel/string/lead_ore_chunk.json 78081972da9f17787319a28bc5d29b50ca8fab12 data/exdeorum/recipes/sieve/gravel/string/magnesium_ore_chunk.json @@ -1228,32 +1229,32 @@ e6ff95b6fbc43c73a537174e01c9eb519e8fdef1 data/exdeorum/recipes/unfired_porcelain 346b70c2d2516f6e735fd1f156e22a649175813d data/exdeorum/recipes/warped_barrel.json 1ae1b311f2e370c924041da80fea01ac8da870c5 data/exdeorum/recipes/warped_crucible.json 7d589e398d803bc7a30614f6ee4aa0d48ca3540e data/exdeorum/recipes/warped_sieve.json -4fbb682aa185e8d9d945619554dc98015221a4eb data/exdeorum/recipes/water_crucible/apple.json -fa23650a3d75ed6278d9c3860aa6ea086371210b data/exdeorum/recipes/water_crucible/beetroot.json -8fed4fdb981ca82436919a074fc1166a2fc6385d data/exdeorum/recipes/water_crucible/cactus.json -8d9de0f7eb46ffb7990a9ac311ec697dffa40443 data/exdeorum/recipes/water_crucible/carrot.json -b191c567f221393c91baaaf456212caebee30048 data/exdeorum/recipes/water_crucible/grass.json -a71db1fcbabb44ed0a0a709175ca2a419b98caa8 data/exdeorum/recipes/water_crucible/grass_block.json -1a31f9a9826fc882acc135c40845b1f227476c7c data/exdeorum/recipes/water_crucible/leaves.json -0e8f136f5fa986bc1c73e063cad5377597fc1a6d data/exdeorum/recipes/water_crucible/lily_pad.json -27134a6501957007812b98886e16d22cd8517ee0 data/exdeorum/recipes/water_crucible/melon.json -d9c0f111e2ae9715cd76a9d5f0ceadce72e34c87 data/exdeorum/recipes/water_crucible/melon_slice.json -3252ccfd40508d9b50e881cee8b5e50e1be7ccee data/exdeorum/recipes/water_crucible/moss.json -8e2e91cb5d81688355ef9ad4f1eb859af24973bb data/exdeorum/recipes/water_crucible/moss_carpet.json -4a5b07cf133e13fc6c2c5d3ea56a60b21d836c27 data/exdeorum/recipes/water_crucible/mushrooms.json -b4674be18b463bed47425ea85f4dd992480c2409 data/exdeorum/recipes/water_crucible/potato.json -0505bf31de1c13f3a22ee2cbdd1595bbb4857692 data/exdeorum/recipes/water_crucible/pumpkin.json -8b04ebb043ce62c0f17adf40cb45431f8e54701f data/exdeorum/recipes/water_crucible/saplings.json -c3ac3ad583b38351ae54d5fe291506dd87d402ab data/exdeorum/recipes/water_crucible/seagrass.json -a48d1f3abe9bf8607096ee8be1ec70d670dfd8d3 data/exdeorum/recipes/water_crucible/sea_pickle.json -43440237534dba69b9f4d97b84148b0e6f131c61 data/exdeorum/recipes/water_crucible/seeds.json -7668124adff54b4cc345e1338ec90ed8b84662c9 data/exdeorum/recipes/water_crucible/seeds_and_spores.json -dabaaa0c9db5dd4668b528df176606609f45c0ce data/exdeorum/recipes/water_crucible/small_flowers.json -0b210ee847c361d8568e0b581ea1e0dfca16fc6c data/exdeorum/recipes/water_crucible/spore_blossom.json -8198da30f7d529f2350f8e276a7660a15bba0a4f data/exdeorum/recipes/water_crucible/sugar_cane.json -3927d17ed5a24132956fa60b51bdb22e67ef4626 data/exdeorum/recipes/water_crucible/sweet_berries.json -9d4abedfd8af2e988c4f11d62ed66743f3e8ac07 data/exdeorum/recipes/water_crucible/tall_flowers.json -a5333ee537aa0e10b740e20a137a24b7699ff52b data/exdeorum/recipes/water_crucible/vine.json +869c22919d2e8004a4d673b02006254bb5d5be03 data/exdeorum/recipes/water_crucible/apple.json +a518997f4f4e48414d2880ddf8bb01e3acdfb4c3 data/exdeorum/recipes/water_crucible/beetroot.json +139a25fefb90ab0f0ce0210062fdb17f2853d691 data/exdeorum/recipes/water_crucible/cactus.json +8fea9c88f60f3f8a85e0fe0f4d7a3efacb2b277e data/exdeorum/recipes/water_crucible/carrot.json +159ec896ca6a807042a8fba793f331fd183bb421 data/exdeorum/recipes/water_crucible/grass.json +cc9b853c700e14c019334bfae36bf8e9f44dfe30 data/exdeorum/recipes/water_crucible/grass_block.json +d2bab4ad2c3ff1bd0d27752e25515c7de4b35ff3 data/exdeorum/recipes/water_crucible/leaves.json +52619bdbe7644f93641449b4d9c2c38ee7fca1ae data/exdeorum/recipes/water_crucible/lily_pad.json +bbbc1d66da41e6a736c7b390c13d7e54ef792ab9 data/exdeorum/recipes/water_crucible/melon.json +d070954f86ceda52d006e8492c3018a10145e0f0 data/exdeorum/recipes/water_crucible/melon_slice.json +7662288906c5cf44dba97891d5cb4dfd31cf8383 data/exdeorum/recipes/water_crucible/moss.json +590c737ca8f89a2aaffb02c007b8f9390ff3571f data/exdeorum/recipes/water_crucible/moss_carpet.json +0d5fc77b292960772c7a84d2c5425980642b86df data/exdeorum/recipes/water_crucible/mushrooms.json +cc35722008f3bef166b65539e4feb180509e79bf data/exdeorum/recipes/water_crucible/potato.json +750ab48f805db09fcb3351ee8db83e9257f7fc53 data/exdeorum/recipes/water_crucible/pumpkin.json +dadcf0474738c5545058e28ed38232b6117f6c28 data/exdeorum/recipes/water_crucible/saplings.json +1dc644ba382fcfc5dbd6bdfac4bc88a5684cfaea data/exdeorum/recipes/water_crucible/seagrass.json +9454184f23b7e567479f743fdf4dfbdc200f55b1 data/exdeorum/recipes/water_crucible/sea_pickle.json +bb86024d353c8347ce35f8c464296045a1589c67 data/exdeorum/recipes/water_crucible/seeds.json +6ac4af54d7c2a89ae06209479c0344a9140906a7 data/exdeorum/recipes/water_crucible/seeds_and_spores.json +312054df63af0de599582452308272719353b890 data/exdeorum/recipes/water_crucible/small_flowers.json +afc3166b1040068a465cd7ec3a532413a87b58d2 data/exdeorum/recipes/water_crucible/spore_blossom.json +ab3ae2221e47670534c49837620fcc61e088aa90 data/exdeorum/recipes/water_crucible/sugar_cane.json +9133a58cb4b5f2f69f0de7a22d1eca2023a29396 data/exdeorum/recipes/water_crucible/sweet_berries.json +3ba422c14ce1396e1686ac41045be16f2ef9c7e8 data/exdeorum/recipes/water_crucible/tall_flowers.json +ae732ce5e5c70e4b5b44396b1db432c22c2dd561 data/exdeorum/recipes/water_crucible/vine.json 05c12b51cdd74a0619df2b35d4d6fafffb84ee0c data/exdeorum/recipes/willow_barrel.json c1dd98278720c97caccca82449d769c6a8a0f5e0 data/exdeorum/recipes/willow_crucible.json 24e72702e3ae9d0832deac8917603c4565f7aed2 data/exdeorum/recipes/willow_sieve.json diff --git a/src/generated/resources/data/exdeorum/recipes/barrel_fluid_transformation/witch_water.json b/src/generated/resources/data/exdeorum/recipes/barrel_fluid_transformation/witch_water.json new file mode 100644 index 00000000..b7c53a37 --- /dev/null +++ b/src/generated/resources/data/exdeorum/recipes/barrel_fluid_transformation/witch_water.json @@ -0,0 +1,20 @@ +{ + "type": "exdeorum:barrel_fluid_transformation", + "base_fluid": "minecraft:lava", + "byproducts": [ + { + "value": "minecraft:red_mushroom", + "weight": 50 + }, + { + "value": "minecraft:brown_mushroom", + "weight": 50 + } + ], + "catalyst": { + "block": "minecraft:mycelium" + }, + "duration": 1700, + "result_color": 2822231, + "result_fluid": "exdeorum:witch_water" +} \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/lava_crucible/cobblestone.json b/src/generated/resources/data/exdeorum/recipes/lava_crucible/cobblestone.json index 05c1aea0..4a47a9f6 100644 --- a/src/generated/resources/data/exdeorum/recipes/lava_crucible/cobblestone.json +++ b/src/generated/resources/data/exdeorum/recipes/lava_crucible/cobblestone.json @@ -1,8 +1,8 @@ { "type": "exdeorum:lava_crucible", "fluid": { - "Amount": 250, - "FluidName": "minecraft:lava" + "amount": 250, + "fluid": "minecraft:lava" }, "ingredient": { "tag": "forge:cobblestone" diff --git a/src/generated/resources/data/exdeorum/recipes/lava_crucible/gravel.json b/src/generated/resources/data/exdeorum/recipes/lava_crucible/gravel.json index 75c4fc2a..c00bdcf2 100644 --- a/src/generated/resources/data/exdeorum/recipes/lava_crucible/gravel.json +++ b/src/generated/resources/data/exdeorum/recipes/lava_crucible/gravel.json @@ -1,8 +1,8 @@ { "type": "exdeorum:lava_crucible", "fluid": { - "Amount": 250, - "FluidName": "minecraft:lava" + "amount": 250, + "fluid": "minecraft:lava" }, "ingredient": { "tag": "forge:gravel" diff --git a/src/generated/resources/data/exdeorum/recipes/lava_crucible/netherrack.json b/src/generated/resources/data/exdeorum/recipes/lava_crucible/netherrack.json index 54169313..43b1b15e 100644 --- a/src/generated/resources/data/exdeorum/recipes/lava_crucible/netherrack.json +++ b/src/generated/resources/data/exdeorum/recipes/lava_crucible/netherrack.json @@ -1,8 +1,8 @@ { "type": "exdeorum:lava_crucible", "fluid": { - "Amount": 500, - "FluidName": "minecraft:lava" + "amount": 500, + "fluid": "minecraft:lava" }, "ingredient": { "tag": "forge:netherrack" diff --git a/src/generated/resources/data/exdeorum/recipes/lava_crucible/stone.json b/src/generated/resources/data/exdeorum/recipes/lava_crucible/stone.json index 51794b75..4de20bdf 100644 --- a/src/generated/resources/data/exdeorum/recipes/lava_crucible/stone.json +++ b/src/generated/resources/data/exdeorum/recipes/lava_crucible/stone.json @@ -1,8 +1,8 @@ { "type": "exdeorum:lava_crucible", "fluid": { - "Amount": 250, - "FluidName": "minecraft:lava" + "amount": 250, + "fluid": "minecraft:lava" }, "ingredient": { "tag": "forge:stone" diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/diamond/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/diamond/iron_ore_chunk.json index b185be65..45e03ccd 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/diamond/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/diamond/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.16 + "p": 0.18 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/flint/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/flint/iron_ore_chunk.json index 45d45442..32336082 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/flint/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/flint/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.11 + "p": 0.13 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/golden/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/golden/iron_ore_chunk.json index 1c659395..a00aa0a3 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/golden/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/golden/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.13 + "p": 0.15 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/iron/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/iron/iron_ore_chunk.json index 9e4981ec..a02e93b9 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/iron/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/iron/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.12 + "p": 0.15 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/netherite/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/netherite/iron_ore_chunk.json index 566bc3ba..10bb292d 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/netherite/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/netherite/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.17 + "p": 0.2 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/string/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/string/iron_ore_chunk.json index c770d8d8..b2c980f1 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/string/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/crushed_deepslate/string/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.1 + "p": 0.12 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/diamond/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/diamond/iron_ore_chunk.json index 7a0f1303..6c01285a 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/diamond/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/diamond/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.13 + "p": 0.15 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/flint/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/flint/iron_ore_chunk.json index 3edcfbf1..66c4e29e 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/flint/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/flint/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.08 + "p": 0.12 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/golden/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/golden/iron_ore_chunk.json index cdb815ac..f56f7f12 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/golden/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/golden/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.07 + "p": 0.14 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/iron/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/iron/iron_ore_chunk.json index 809e0e87..41c3cd13 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/iron/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/iron/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.11 + "p": 0.14 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/netherite/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/netherite/iron_ore_chunk.json index e1221c7b..ff32085b 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/netherite/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/netherite/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.13 + "p": 0.17 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/string/iron_ore_chunk.json b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/string/iron_ore_chunk.json index 1ca801ef..d189ca70 100644 --- a/src/generated/resources/data/exdeorum/recipes/sieve/gravel/string/iron_ore_chunk.json +++ b/src/generated/resources/data/exdeorum/recipes/sieve/gravel/string/iron_ore_chunk.json @@ -8,6 +8,6 @@ "result_amount": { "type": "minecraft:binomial", "n": 1.0, - "p": 0.07 + "p": 0.1 } } \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/apple.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/apple.json index 3ceaeb51..2eb00489 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/apple.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/apple.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:apple" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/beetroot.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/beetroot.json index e0cc1b21..f5037657 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/beetroot.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/beetroot.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:beetroot" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/cactus.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/cactus.json index 48fb96a3..87a61952 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/cactus.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/cactus.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 250, - "FluidName": "minecraft:water" + "amount": 250, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:cactus" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/carrot.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/carrot.json index a53fe8ac..cfe7876d 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/carrot.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/carrot.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:carrot" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/grass.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/grass.json index 05bb7d19..2a69163f 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/grass.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/grass.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": [ { diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/grass_block.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/grass_block.json index fe283447..853f08d0 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/grass_block.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/grass_block.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 150, - "FluidName": "minecraft:water" + "amount": 150, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:grass_block" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/leaves.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/leaves.json index 76893e9c..2aff9db5 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/leaves.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/leaves.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 250, - "FluidName": "minecraft:water" + "amount": 250, + "fluid": "minecraft:water" }, "ingredient": { "tag": "minecraft:leaves" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/lily_pad.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/lily_pad.json index 6293397e..cec706d0 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/lily_pad.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/lily_pad.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 150, - "FluidName": "minecraft:water" + "amount": 150, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:lily_pad" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/melon.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/melon.json index 6965be92..fbc21f4f 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/melon.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/melon.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 250, - "FluidName": "minecraft:water" + "amount": 250, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:melon" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/melon_slice.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/melon_slice.json index 37318444..677e3be2 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/melon_slice.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/melon_slice.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 50, - "FluidName": "minecraft:water" + "amount": 50, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:melon_slice" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/moss.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/moss.json index f854e677..0a3d0728 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/moss.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/moss.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 150, - "FluidName": "minecraft:water" + "amount": 150, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:moss_block" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/moss_carpet.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/moss_carpet.json index 36ae68ab..86b3d3ac 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/moss_carpet.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/moss_carpet.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:moss_carpet" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/mushrooms.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/mushrooms.json index 15467f56..e5f3dfe1 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/mushrooms.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/mushrooms.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "tag": "forge:mushrooms" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/potato.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/potato.json index 9fbb475c..ecdbedad 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/potato.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/potato.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:potato" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/pumpkin.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/pumpkin.json index b38a68ab..8ed94d82 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/pumpkin.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/pumpkin.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 250, - "FluidName": "minecraft:water" + "amount": 250, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:pumpkin" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/saplings.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/saplings.json index 9c2f6dc2..8ac323db 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/saplings.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/saplings.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "tag": "minecraft:saplings" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/sea_pickle.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/sea_pickle.json index 2bea9fc6..27b9a005 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/sea_pickle.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/sea_pickle.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 200, - "FluidName": "minecraft:water" + "amount": 200, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:sea_pickle" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/seagrass.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/seagrass.json index 1e5c836d..b7dbbb6e 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/seagrass.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/seagrass.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:seagrass" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds.json index f2109e01..c5c0224d 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 50, - "FluidName": "minecraft:water" + "amount": 50, + "fluid": "minecraft:water" }, "ingredient": { "tag": "forge:seeds" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds_and_spores.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds_and_spores.json index 603ce51d..5a53db8a 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds_and_spores.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/seeds_and_spores.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 50, - "FluidName": "minecraft:water" + "amount": 50, + "fluid": "minecraft:water" }, "ingredient": [ { diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/small_flowers.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/small_flowers.json index d195fb76..6f823289 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/small_flowers.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/small_flowers.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "tag": "minecraft:small_flowers" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/spore_blossom.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/spore_blossom.json index dfca2ae7..47e043c8 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/spore_blossom.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/spore_blossom.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 150, - "FluidName": "minecraft:water" + "amount": 150, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:spore_blossom" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/sugar_cane.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/sugar_cane.json index 289d874a..dc51ca9f 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/sugar_cane.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/sugar_cane.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:sugar_cane" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/sweet_berries.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/sweet_berries.json index 391a2bf1..56c3cb8a 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/sweet_berries.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/sweet_berries.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 50, - "FluidName": "minecraft:water" + "amount": 50, + "fluid": "minecraft:water" }, "ingredient": [ { diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/tall_flowers.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/tall_flowers.json index 86c4faba..1177abc1 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/tall_flowers.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/tall_flowers.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 200, - "FluidName": "minecraft:water" + "amount": 200, + "fluid": "minecraft:water" }, "ingredient": { "tag": "minecraft:tall_flowers" diff --git a/src/generated/resources/data/exdeorum/recipes/water_crucible/vine.json b/src/generated/resources/data/exdeorum/recipes/water_crucible/vine.json index fc57ad1e..3b857b6f 100644 --- a/src/generated/resources/data/exdeorum/recipes/water_crucible/vine.json +++ b/src/generated/resources/data/exdeorum/recipes/water_crucible/vine.json @@ -1,8 +1,8 @@ { "type": "exdeorum:water_crucible", "fluid": { - "Amount": 100, - "FluidName": "minecraft:water" + "amount": 100, + "fluid": "minecraft:water" }, "ingredient": { "item": "minecraft:vine" diff --git a/src/main/java/thedarkcolour/exdeorum/block/BarrelBlock.java b/src/main/java/thedarkcolour/exdeorum/block/BarrelBlock.java index 515284c5..90d59021 100644 --- a/src/main/java/thedarkcolour/exdeorum/block/BarrelBlock.java +++ b/src/main/java/thedarkcolour/exdeorum/block/BarrelBlock.java @@ -76,11 +76,15 @@ public class BarrelBlock extends EBlock { @Override public void neighborChanged(BlockState pState, Level level, BlockPos pos, Block pBlock, BlockPos fromPos, boolean pIsMoving) { - // Only check when the above block is updated + // Only check when the above block is updated, or when the below block is updated if (fromPos.getY() - pos.getY() == 1) { if (level.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { barrel.tryInWorldFluidMixing(); } + } else if (fromPos.getY() - pos.getY() == -1) { + if (level.getBlockEntity(pos) instanceof BarrelBlockEntity barrel) { + barrel.updateFluidTransform(); + } } } } diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java index a1f4d57a..514cb4a5 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/AbstractCrucibleBlockEntity.java @@ -360,14 +360,7 @@ public abstract class AbstractCrucibleBlockEntity extends EBlockEntity { } } if (crucible instanceof WaterCrucibleBlockEntity && level.isRainingAt(pos.above())) { - if (crucible.tank.isEmpty()) { - crucible.tank.setFluid(new FluidStack(Fluids.WATER, 1)); - crucible.markUpdated(); - } else if (crucible.tank.getFluid().getFluid() == Fluids.WATER && - crucible.tank.getFluidAmount() < crucible.tank.getCapacity()) { - crucible.tank.getFluid().grow(1); - crucible.markUpdated(); - } + BarrelBlockEntity.fillRainWater(crucible, crucible.tank); } } } diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java index 1132e01c..b7071cf5 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/BarrelBlockEntity.java @@ -26,6 +26,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.tags.FluidTags; +import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.item.ItemEntity; @@ -54,7 +55,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import thedarkcolour.exdeorum.block.BarrelBlock; import thedarkcolour.exdeorum.blockentity.helper.FluidHelper; import thedarkcolour.exdeorum.client.CompostColors; @@ -62,6 +63,7 @@ import thedarkcolour.exdeorum.config.EConfig; import thedarkcolour.exdeorum.material.BarrelMaterial; import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe; +import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; import thedarkcolour.exdeorum.registry.EBlockEntities; import thedarkcolour.exdeorum.registry.EFluids; @@ -73,10 +75,14 @@ public class BarrelBlockEntity extends EBlockEntity { public float progress; public short compost; // compost colors (has to be shorts because Java bytes are signed and only go to 127, when need 255) + // also used for fluid transformation (destination color) public short r, g, b; // Used to avoid triggering obsidian dupes in onContentsChanged, because Forge's FluidUtil actually modifies the tank for some reason private boolean isBeingFilledByPlayer; public final boolean transparent; + // Current transformation recipe + @Nullable + public FluidTransformationRecipe currentTransformRecipe = null; private final LazyOptional itemHandler = LazyOptional.of(() -> this.item); private final LazyOptional fluidHandler = LazyOptional.of(() -> this.tank); @@ -158,7 +164,7 @@ public class BarrelBlockEntity extends EBlockEntity { } public boolean isBurning() { - return isHotFluid(this.tank.getFluid().getFluid().getFluidType()) && this.progress != 0.0f; + return this.getBlockState().ignitedByLava() && isHotFluid(this.tank.getFluid().getFluid().getFluidType()) && this.progress != 0.0f; } // Composting is in progress if at 1000. When finished, compost is set back to 0 @@ -453,6 +459,26 @@ public class BarrelBlockEntity extends EBlockEntity { } } + public void updateFluidTransform() { + if (!this.level.isClientSide) { + var belowState = this.level.getBlockState(this.worldPosition.below()); + if (this.tank.getFluidAmount() != 1000) { + this.currentTransformRecipe = null; + } else { + this.currentTransformRecipe = RecipeUtil.getFluidTransformationRecipe(this.tank.getFluid().getFluid(), belowState); + + if (this.currentTransformRecipe != null) { + var color = this.currentTransformRecipe.resultColor; + this.r = (short) ((color >> 16) & 0xff); + this.g = (short) ((color >> 8) & 0xff); + this.b = (short) ((color) & 0xff); + markUpdated(); + } + } + this.progress = 0.0f; + } + } + public static class Ticker implements BlockEntityTicker { @Override public void tick(Level level, BlockPos pos, BlockState state, BarrelBlockEntity barrel) { @@ -460,31 +486,61 @@ public class BarrelBlockEntity extends EBlockEntity { // Turn compost to dirt if (barrel.isComposting()) { barrel.doCompost(); - } else if (barrel.hasFullWater()) { - var rand = level.random; - var mycelium = 0f; + } else if (isHotFluid(barrel.tank.getFluid().getFluid().getFluidType()) && state.ignitedByLava()) { + if ((barrel.progress += getProgressStep()) >= 1.0f) { + if (barrel.tank.getFluidAmount() == 1000) { + var fluid = barrel.tank.getFluid().getFluid(); + level.setBlockAndUpdate(pos, fluid.getFluidType().getBlockForFluidState(level, pos, fluid.defaultFluidState())); + } else { + level.setBlockAndUpdate(pos, Blocks.FIRE.defaultBlockState()); + } + } + barrel.markUpdated(); + } else if (level.isRainingAt(pos.above()) && barrel.item.getStackInSlot(0).isEmpty() && barrel.compost == 0) { + fillRainWater(barrel, barrel.tank); + } else if (barrel.currentTransformRecipe != null) { + var recipe = barrel.currentTransformRecipe; + var catalysts = 0; - for (BlockPos cursor : BlockPos.betweenClosed(pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1)) { - if (level.getBlockState(cursor).getBlock() == Blocks.MYCELIUM) { - mycelium += 0.15f; + for (var cursor : BlockPos.betweenClosed(pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, pos.getX() + 1, pos.getY() - 1, pos.getZ() + 1)) { + if (recipe.catalyst.test(level.getBlockState(cursor))) { + catalysts++; - if (rand.nextInt(1500) == 0) { - BlockPos above = cursor.above(); + if (!recipe.byproducts.isEmpty()) { + var rand = level.random; - if (level.getBlockState(above).isAir()) { - if (rand.nextBoolean()) { - level.setBlockAndUpdate(above, Blocks.RED_MUSHROOM.defaultBlockState()); - } else { - level.setBlockAndUpdate(above, Blocks.BROWN_MUSHROOM.defaultBlockState()); + if (rand.nextInt(1500) == 0) { + var above = cursor.above(); + + if (level.getBlockState(above).isAir()) { + var byproduct = recipe.byproducts.getRandom(rand); + if (byproduct.canSurvive(level, above)) { + level.setBlockAndUpdate(above, byproduct); + } } } } } } - // Try to perform a fluid transformation recipe + if (catalysts == 0) { + barrel.currentTransformRecipe = null; + } else { + barrel.progress += catalysts * (1.0f / barrel.currentTransformRecipe.duration); + if (barrel.progress >= 1.0f - Mth.EPSILON) { + // Reset progress + barrel.progress = 0.0f; + level.playSound(null, pos, SoundEvents.BREWING_STAND_BREW, SoundSource.BLOCKS, 1.0f, 0.6f); + barrel.tank.setFluid(FluidStack.EMPTY); + barrel.tank.fill(new FluidStack(EFluids.WITCH_WATER.get(), 1000), IFluidHandler.FluidAction.EXECUTE); + } + barrel.markUpdated(); + } + } else if (barrel.hasFullWater()) { if (barrel.tank.getFluid().getFluid().getFluidType() == ForgeMod.WATER_TYPE.get()) { - if (mycelium == 0 && state.ignitedByLava() && rand.nextInt(500) == 0) { + var rand = level.random; + // Leak water to create moss (only wooden barrels do this) + if (state.ignitedByLava() && rand.nextInt(500) == 0) { var randomPos = pos.offset(rand.nextIntBetweenInclusive(-MOSS_SPREAD_RANGE, MOSS_SPREAD_RANGE), -1, rand.nextIntBetweenInclusive(-MOSS_SPREAD_RANGE, MOSS_SPREAD_RANGE)); var randomBlock = level.getBlockState(randomPos).getBlock(); @@ -494,37 +550,6 @@ public class BarrelBlockEntity extends EBlockEntity { level.setBlock(randomPos, Blocks.MOSSY_STONE_BRICKS.defaultBlockState(), 3); } } - - if (barrel.progress != (barrel.progress += mycelium * getProgressStep())) { - barrel.markUpdated(); - } - - if (barrel.progress >= 1.0f) { - // Reset progress - barrel.progress = 0.0f; - level.playSound(null, pos, SoundEvents.BREWING_STAND_BREW, SoundSource.BLOCKS, 1.0f, 0.6f); - barrel.tank.setFluid(new FluidStack(EFluids.WITCH_WATER.get(), barrel.tank.getFluidAmount())); - } - } - } else if (isHotFluid(barrel.tank.getFluid().getFluid().getFluidType())) { - if (state.ignitedByLava()) { - if ((barrel.progress += getProgressStep()) >= 1.0f) { - if (barrel.tank.getFluidAmount() == 1000) { - var fluid = barrel.tank.getFluid().getFluid(); - level.setBlockAndUpdate(pos, fluid.getFluidType().getBlockForFluidState(level, pos, fluid.defaultFluidState())); - } else { - level.setBlockAndUpdate(pos, Blocks.FIRE.defaultBlockState()); - } - } - barrel.markUpdated(); - } - } else if (level.isRainingAt(pos.above()) && barrel.item.getStackInSlot(0).isEmpty() && barrel.compost == 0) { - if (barrel.tank.isEmpty()) { - barrel.tank.setFluid(new FluidStack(Fluids.WATER, 1)); - barrel.markUpdated(); - } else if (barrel.tank.getFluid().getFluid() == Fluids.WATER) { - barrel.tank.getFluid().grow(1); - barrel.markUpdated(); } } } else { @@ -533,6 +558,16 @@ public class BarrelBlockEntity extends EBlockEntity { } } + public static void fillRainWater(EBlockEntity block, FluidHelper tank) { + if (tank.isEmpty()) { + tank.setFluid(new FluidStack(Fluids.WATER, 1)); + block.markUpdated(); + } else if (tank.getFluid().getFluid() == Fluids.WATER && tank.getFluidAmount() < tank.getCapacity()) { + tank.getFluid().grow(1); + block.markUpdated(); + } + } + private static float getProgressStep() { return EConfig.SERVER.barrelProgressStep.get().floatValue(); } @@ -556,6 +591,7 @@ public class BarrelBlockEntity extends EBlockEntity { @Override public void onLoad() { tryInWorldFluidMixing(); + updateFluidTransform(); } // Inner class @@ -571,7 +607,7 @@ public class BarrelBlockEntity extends EBlockEntity { } @Override - public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { if (stack.isEmpty()) return ItemStack.EMPTY; validateSlotIndex(slot); @@ -595,7 +631,7 @@ public class BarrelBlockEntity extends EBlockEntity { } @Override - public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + public ItemStack extractItem(int slot, int amount, boolean simulate) { return super.extractItem(slot, amount, simulate); } @@ -624,45 +660,7 @@ public class BarrelBlockEntity extends EBlockEntity { BarrelBlockEntity.this.tryInWorldFluidMixing(); BarrelBlockEntity.this.markUpdated(); } - } - - @Override - public int fill(FluidStack resource, FluidAction action) { - if (resource.isEmpty() || !isFluidValid(resource)) { - return 0; - } - if (action.simulate()) { - if (this.fluid.isEmpty()) { - return Math.min(this.capacity, resource.getAmount()); - } - if (!this.fluid.isFluidEqual(resource)) { - return 0; - } - return Math.min(this.capacity - this.fluid.getAmount(), resource.getAmount()); - } - if (this.fluid.isEmpty()) { - // fix forge's implementation to avoid dupes - int amount = Math.min(this.capacity, resource.getAmount()); - this.fluid = new FluidStack(resource, Math.min(this.capacity, amount)); - onContentsChanged(); - return amount; - } - if (!this.fluid.isFluidEqual(resource)) - { - return 0; - } - int filled = this.capacity - this.fluid.getAmount(); - - if (resource.getAmount() < filled) { - this.fluid.grow(resource.getAmount()); - filled = resource.getAmount(); - } else { - this.fluid.setAmount(this.capacity); - } - if (filled > 0) { - onContentsChanged(); - } - return filled; + BarrelBlockEntity.this.updateFluidTransform(); } } } diff --git a/src/main/java/thedarkcolour/exdeorum/blockentity/helper/FluidHelper.java b/src/main/java/thedarkcolour/exdeorum/blockentity/helper/FluidHelper.java index b2b4e105..863c82da 100644 --- a/src/main/java/thedarkcolour/exdeorum/blockentity/helper/FluidHelper.java +++ b/src/main/java/thedarkcolour/exdeorum/blockentity/helper/FluidHelper.java @@ -19,14 +19,57 @@ package thedarkcolour.exdeorum.blockentity.helper; import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.templates.FluidTank; -// Only changed behavior from FluidTank is that fluid stacks read from NBT are clamped and removed validator predicate. +// Changed behavior from FluidTank: +// - fluid stacks read from NBT are clamped. +// - removed validator predicate +// - fixed incorrect fill implementation that caused dupes with the barrel public class FluidHelper extends FluidTank { public FluidHelper(int capacity) { super(capacity); } + @Override + public int fill(FluidStack resource, FluidAction action) { + if (resource.isEmpty() || !isFluidValid(resource)) { + return 0; + } + if (action.simulate()) { + if (this.fluid.isEmpty()) { + return Math.min(this.capacity, resource.getAmount()); + } + if (!this.fluid.isFluidEqual(resource)) { + return 0; + } + return Math.min(this.capacity - this.fluid.getAmount(), resource.getAmount()); + } + if (this.fluid.isEmpty()) { + // fix forge's implementation to avoid dupes + int amount = Math.min(this.capacity, resource.getAmount()); + this.fluid = new FluidStack(resource, Math.min(this.capacity, amount)); + onContentsChanged(); + return amount; + } + if (!this.fluid.isFluidEqual(resource)) + { + return 0; + } + int filled = this.capacity - this.fluid.getAmount(); + + if (resource.getAmount() < filled) { + this.fluid.grow(resource.getAmount()); + filled = resource.getAmount(); + } else { + this.fluid.setAmount(this.capacity); + } + if (filled > 0) { + onContentsChanged(); + } + return filled; + } + @Override public FluidTank readFromNBT(CompoundTag nbt) { super.readFromNBT(nbt); diff --git a/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java b/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java index 68288451..523a087c 100644 --- a/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java +++ b/src/main/java/thedarkcolour/exdeorum/client/ter/BarrelRenderer.java @@ -33,6 +33,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.level.material.Fluid; import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.common.capabilities.ForgeCapabilities; import thedarkcolour.exdeorum.ExDeorum; @@ -82,19 +83,19 @@ public class BarrelRenderer implements BlockEntityRenderer { var pos = barrel.getBlockPos(); var percentage = fluidStack.getAmount() / 1000.0f; var y = Mth.lerp(percentage, 1.0f, 14.0f) / 16f; - var col = RenderUtil.getFluidColor(fluid, level, pos); + var inputFluidColor = RenderUtil.getFluidColor(fluid, level, pos); // Split into RGB components - var r = (col >> 16) & 0xff; - var g = (col >> 8) & 0xff; - var b = col & 0xff; + var r = (inputFluidColor >> 16) & 0xff; + var g = (inputFluidColor >> 8) & 0xff; + var b = inputFluidColor & 0xff; if (barrel.isBrewing()) { float progress = barrel.progress; // Transition between water color and witch water color (200B41) - r = (int) Mth.lerp(progress, r, 32); - g = (int) Mth.lerp(progress, g, 11); - b = (int) Mth.lerp(progress, b, 65); + r = (int) Mth.lerp(progress, r, barrel.r); + g = (int) Mth.lerp(progress, g, barrel.g); + b = (int) Mth.lerp(progress, b, barrel.b); } if (barrel.transparent) { diff --git a/src/main/java/thedarkcolour/exdeorum/compat/PreferredOres.java b/src/main/java/thedarkcolour/exdeorum/compat/PreferredOres.java index 33bbaa0f..1040ab8e 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/PreferredOres.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/PreferredOres.java @@ -42,6 +42,7 @@ public class PreferredOres { private static final Map, Item> PREFERRED_ORE_ITEMS = new Object2ObjectOpenHashMap<>(11, Hash.DEFAULT_LOAD_FACTOR); static { + // todo these should update whenever data is reloaded putPreferredOre(EItemTags.ORES_ALUMINUM, EConfig.COMMON.preferredAluminumOre, getDefaultAluminumOre()); putPreferredOre(EItemTags.ORES_COBALT, EConfig.COMMON.preferredCobaltOre, getDefaultCobaltOre()); putPreferredOre(EItemTags.ORES_SILVER, EConfig.COMMON.preferredSilverOre, getDefaultSilverOre()); diff --git a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java index eb7e9e4b..d6c6cde1 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/kubejs/ExDeorumKubeJsBindings.java @@ -18,7 +18,6 @@ package thedarkcolour.exdeorum.compat.kubejs; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import dev.latvian.mods.kubejs.bindings.event.ServerEvents; import dev.latvian.mods.kubejs.recipe.RecipesEventJS; import dev.latvian.mods.kubejs.recipe.ReplacementMatch; @@ -26,8 +25,6 @@ import dev.latvian.mods.kubejs.recipe.filter.RecipeFilter; import dev.latvian.mods.kubejs.script.ScriptType; import dev.latvian.mods.rhino.util.HideFromJS; import net.minecraft.advancements.critereon.StatePropertiesPredicate; -import net.minecraft.commands.arguments.blocks.BlockStateParser; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -35,6 +32,7 @@ import net.minecraft.world.level.block.state.properties.Property; import net.minecraftforge.registries.RegistryObject; import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.recipe.BlockPredicate; +import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleHeatRecipe; import thedarkcolour.exdeorum.registry.ERecipeTypes; @@ -59,17 +57,12 @@ class ExDeorumKubeJsBindings { @SuppressWarnings({"rawtypes", "unchecked"}) public void setCrucibleHeatValueForState(String stateString, int value) { onRecipesEvent(event -> { - try { - var state = BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK.asLookup(), stateString, false).blockState(); - var properties = StatePropertiesPredicate.Builder.properties(); - for (Property prop : state.getProperties()) { - bypassTypeChecking(properties, prop, state); - } - event.custom(new FinishedCrucibleHeatRecipe(null, BlockPredicate.blockState(state.getBlock(), properties.build()), value).serializeRecipe()); - } catch (CommandSyntaxException exception) { - // Throw a more appropriate exception. - throw new IllegalArgumentException("Failed to parse BlockState string \"" + stateString + "\""); + var state = RecipeUtil.parseBlockState(stateString); + var properties = StatePropertiesPredicate.Builder.properties(); + for (Property prop : state.getProperties()) { + bypassTypeChecking(properties, prop, state); } + event.custom(new FinishedCrucibleHeatRecipe(null, BlockPredicate.blockState(state.getBlock(), properties.build()), value).serializeRecipe()); }); } diff --git a/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java b/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java index 617b961a..21374eef 100644 --- a/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java +++ b/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java @@ -34,6 +34,7 @@ import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.CampfireBlock; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; @@ -53,9 +54,8 @@ import thedarkcolour.exdeorum.compat.ModIds; import thedarkcolour.exdeorum.data.ModCompatData; import thedarkcolour.exdeorum.material.DefaultMaterials; import thedarkcolour.exdeorum.recipe.TagResultRecipe; -import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelCompostRecipe; -import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelFluidMixingRecipe; -import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelMixingRecipe; +import thedarkcolour.exdeorum.recipe.WeightedList; +import thedarkcolour.exdeorum.recipe.barrel.*; import thedarkcolour.exdeorum.recipe.BlockPredicate; import thedarkcolour.exdeorum.recipe.crook.FinishedCrookRecipe; import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleHeatRecipe; @@ -89,6 +89,7 @@ public class Recipes { crucibleHeatSources(writer); barrelCompostRecipes(writer); barrelMixingRecipes(writer); + fluidTransformationRecipes(writer); } private static void craftingRecipes(Consumer writer, MKRecipeProvider recipes) { @@ -648,6 +649,14 @@ public class Recipes { writer.accept(new FinishedBarrelFluidMixingRecipe(new ResourceLocation(ExDeorum.ID, "barrel_fluid_mixing/" + path(result)), base, 1000, additive, result, consumesAdditive)); } + private static void fluidTransformationRecipes(Consumer writer) { + writer.accept(new FinishedFluidTransformationRecipe(modLoc("barrel_fluid_transformation/witch_water"), Fluids.WATER, EFluids.WITCH_WATER.get(), 0x2B1057, BlockPredicate.singleBlock(Blocks.MYCELIUM), WeightedList.builder().add(50, Blocks.RED_MUSHROOM.defaultBlockState()).add(50, Blocks.BROWN_MUSHROOM.defaultBlockState()).build(), 1700)); + } + + static ResourceLocation modLoc(String path) { + return new ResourceLocation(ExDeorum.ID, path); + } + static ICondition tagNotEmpty(TagKey tag) { return new NotCondition(new TagEmptyCondition(tag.location())); } diff --git a/src/main/java/thedarkcolour/exdeorum/fluid/WitchWaterFluid.java b/src/main/java/thedarkcolour/exdeorum/fluid/WitchWaterFluid.java index aae3b239..04dccb68 100644 --- a/src/main/java/thedarkcolour/exdeorum/fluid/WitchWaterFluid.java +++ b/src/main/java/thedarkcolour/exdeorum/fluid/WitchWaterFluid.java @@ -58,6 +58,7 @@ public class WitchWaterFluid extends FluidType { @Override public void initializeClient(Consumer consumer) { consumer.accept(new IClientFluidTypeExtensions() { + private static final Vector3f FOG_COLOR = new Vector3f(32f / 255f, 12f / 255f, 64f / 255f); @Override public ResourceLocation getStillTexture() { return STILL_TEXTURE; @@ -75,13 +76,12 @@ public class WitchWaterFluid extends FluidType { @Override public @NotNull Vector3f modifyFogColor(Camera camera, float partialTick, ClientLevel level, int renderDistance, float darkenWorldAmount, Vector3f fluidFogColor) { - return new Vector3f(32f / 255f, 12f / 255f, 64f / 255f); + return FOG_COLOR; } - // todo return the correct value here @Override public int getTintColor() { - return 0xFFFFFFFF; + return 0xffffffff; } }); } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/CodecUtil.java b/src/main/java/thedarkcolour/exdeorum/recipe/CodecUtil.java deleted file mode 100644 index 6a17309e..00000000 --- a/src/main/java/thedarkcolour/exdeorum/recipe/CodecUtil.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Ex Deorum - * Copyright (c) 2024 thedarkcolour - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package thedarkcolour.exdeorum.recipe; - -import com.google.gson.JsonElement; -import com.mojang.serialization.Codec; -import com.mojang.serialization.JsonOps; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.Tag; - -@SuppressWarnings("OptionalGetWithoutIsPresent") -public class CodecUtil { - public static JsonElement encode(Codec codec, T object) { - return codec.encodeStart(JsonOps.INSTANCE, object).result().get(); - } - - public static T decode(Codec codec, JsonElement json) { - return codec.parse(JsonOps.INSTANCE, json).result().get(); - } -} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/EFinishedRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/EFinishedRecipe.java index 3140448e..a2e11a14 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/EFinishedRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/EFinishedRecipe.java @@ -23,16 +23,27 @@ import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; -public interface EFinishedRecipe extends FinishedRecipe { +public abstract class EFinishedRecipe implements FinishedRecipe { + private final ResourceLocation id; + + public EFinishedRecipe(ResourceLocation id) { + this.id = id; + } + + @Override + public ResourceLocation getId() { + return this.id; + } + @Nullable @Override - default JsonObject serializeAdvancement() { + public JsonObject serializeAdvancement() { return null; } @Nullable @Override - default ResourceLocation getAdvancementId() { + public ResourceLocation getAdvancementId() { return null; } } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java index 2144f0ae..a6f55b21 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java @@ -18,11 +18,15 @@ package thedarkcolour.exdeorum.recipe; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectSet; +import net.minecraft.commands.arguments.blocks.BlockStateParser; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -38,6 +42,7 @@ import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.storage.loot.LootContext; @@ -54,6 +59,7 @@ import thedarkcolour.exdeorum.item.HammerItem; import thedarkcolour.exdeorum.loot.SummationGenerator; import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe; +import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe; import thedarkcolour.exdeorum.recipe.cache.*; import thedarkcolour.exdeorum.recipe.crook.CrookRecipe; @@ -82,6 +88,7 @@ public final class RecipeUtil { private static SingleIngredientRecipeCache hammerRecipeCache; private static SieveRecipeCache sieveRecipeCache; private static BarrelFluidMixingRecipeCache barrelFluidMixingRecipeCache; + private static FluidTransformationRecipeCache fluidTransformationRecipeCache; private static CrookRecipeCache crookRecipeCache; private static CrucibleHeatRecipeCache crucibleHeatRecipeCache; @@ -92,6 +99,7 @@ public final class RecipeUtil { hammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.HAMMER).trackAllRecipes(); sieveRecipeCache = new SieveRecipeCache(recipes); barrelFluidMixingRecipeCache = new BarrelFluidMixingRecipeCache(recipes); + fluidTransformationRecipeCache = new FluidTransformationRecipeCache(recipes); crookRecipeCache = new CrookRecipeCache(recipes); crucibleHeatRecipeCache = new CrucibleHeatRecipeCache(recipes); HammerItem.refreshValidBlocks(); @@ -104,6 +112,7 @@ public final class RecipeUtil { hammerRecipeCache = null; sieveRecipeCache = null; barrelFluidMixingRecipeCache = null; + fluidTransformationRecipeCache = null; crookRecipeCache = null; crucibleHeatRecipeCache = null; } @@ -321,6 +330,15 @@ public final class RecipeUtil { } } + @Nullable + public static FluidTransformationRecipe getFluidTransformationRecipe(Fluid baseFluid, BlockState catalystState) { + if (baseFluid != Fluids.EMPTY) { + return fluidTransformationRecipeCache.getRecipe(baseFluid, catalystState); + } else { + return null; + } + } + public static double getExpectedValue(NumberProvider provider) { if (provider instanceof ConstantValue constant) { return constant.value; @@ -349,11 +367,11 @@ public final class RecipeUtil { } @Nullable - public static BlockPredicate readBlockPredicate(ResourceLocation recipeId, JsonObject json) { - BlockPredicate blockPredicate = BlockPredicate.fromJson(json.getAsJsonObject("block_predicate")); + public static BlockPredicate readBlockPredicate(ResourceLocation recipeId, JsonObject json, String key) { + BlockPredicate blockPredicate = BlockPredicate.fromJson(json.getAsJsonObject(key)); if (blockPredicate == null) { - ExDeorum.LOGGER.error("Invalid block_predicate for recipe {}, refer to Ex Deorum documentation for syntax: {}", recipeId, json.getAsJsonObject("block_predicate")); + ExDeorum.LOGGER.error("Invalid {} for recipe {}, refer to Ex Deorum documentation for syntax: {}", key, recipeId, json.getAsJsonObject(key)); } return blockPredicate; } @@ -388,4 +406,78 @@ public final class RecipeUtil { public static ObjectSet> getHeatSources() { return crucibleHeatRecipeCache.getEntries(); } + + public static FluidStack readFluidStack(JsonObject json, String key) { + if (json.has(key)) { + var fluidJson = json.getAsJsonObject(key); + // Since we aren't using codec anymore, we can use consistent naming with other JSON objects + if (fluidJson.has("FluidName")) { + var stack = new FluidStack(RecipeUtil.readFluid(fluidJson, "FluidName"), GsonHelper.getAsInt(fluidJson, "Amount")); + if (fluidJson.has("Tag")) { + stack.setTag(CraftingHelper.getNBT(fluidJson.get("Tag"))); + } + return stack; + } else { + var stack = new FluidStack(RecipeUtil.readFluid(fluidJson, "fluid"), GsonHelper.getAsInt(fluidJson, "amount")); + if (fluidJson.has("nbt")) { + stack.setTag(CraftingHelper.getNBT(fluidJson.get("nbt"))); + } + return stack; + } + } else { + throw new JsonSyntaxException("Missing fluid"); + } + } + + public static JsonElement writeFluidStackJson(FluidStack fluidStack) { + JsonObject object = new JsonObject(); + object.addProperty("fluid", getFluidId(fluidStack.getFluid())); + object.addProperty("amount", fluidStack.getAmount()); + if (fluidStack.hasTag()) { + object.addProperty("nbt", fluidStack.getTag().getAsString()); + } + return object; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static JsonPrimitive writeBlockState(BlockState state) { + var registryKey = BuiltInRegistries.BLOCK.getKey(state.getBlock()); + + Collection properties = (Collection) ((Collection)state.getProperties()); + + if (properties.isEmpty()) { + return new JsonPrimitive(registryKey.toString()); + } else { + StringBuilder builder = new StringBuilder(); + builder.append(registryKey); + builder.append('['); + for (Iterator iterator = properties.iterator(); iterator.hasNext(); ) { + var property = iterator.next(); + builder.append(property.getName()); + builder.append('='); + builder.append(property.getName(state.getValue(property))); + if (iterator.hasNext()) { + builder.append(','); + } + } + builder.append(']'); + return new JsonPrimitive(builder.toString()); + } + } + + public static BlockState parseBlockState(String stateString) { + try { + return BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK.asLookup(), stateString, false).blockState(); + } catch (CommandSyntaxException e) { + throw new IllegalArgumentException("Failed to parse BlockState string \"" + stateString + "\""); + } + } + + public static String getFluidId(Fluid baseFluid) { + return BuiltInRegistries.FLUID.getKey(baseFluid).toString(); + } + + public static String writeItemJson(Item result) { + return BuiltInRegistries.ITEM.getKey(result).toString(); + } } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/WeightedList.java b/src/main/java/thedarkcolour/exdeorum/recipe/WeightedList.java new file mode 100644 index 00000000..882c037c --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/WeightedList.java @@ -0,0 +1,161 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.recipe; + +import com.google.common.base.Preconditions; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import net.minecraft.util.RandomSource; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.Function; + +// much simpler version of SimpleWeightedRandomList that supports .equals +public class WeightedList { + private final int totalWeight; + private final Object[] values; + private final int[] weights; + + private WeightedList(int totalWeight, Object[] values, int[] weights) { + Preconditions.checkArgument(values.length == weights.length, "Values and weights arrays are different sizes"); + + this.totalWeight = totalWeight; + this.values = values; + this.weights = weights; + } + + public boolean isEmpty() { + return this.values.length == 0; + } + + // list must not be empty + @SuppressWarnings("unchecked") + public T getRandom(RandomSource rand) { + int chosenIndex = rand.nextInt(this.totalWeight); + + for (int i = 0; i < this.values.length; i++) { + chosenIndex -= this.weights[i]; + if (chosenIndex < 0) { + return (T) this.values[i]; + } + } + + throw new IllegalStateException("Could not get random element"); + } + + @SuppressWarnings("unchecked") + public void toNetwork(FriendlyByteBuf buffer, BiConsumer valueWriter) { + buffer.writeVarInt(this.values.length); + for (int i = 0; i < this.values.length; i++) { + valueWriter.accept(buffer, (T) this.values[i]); + buffer.writeVarInt(this.weights[i]); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WeightedList that = (WeightedList) o; + return Arrays.equals(this.values, that.values) && Arrays.equals(this.weights, that.weights); + } + + @Override + public int hashCode() { + int result = Arrays.hashCode(this.values); + result = 31 * result + Arrays.hashCode(this.weights); + return result; + } + + public static Builder builder() { + return new Builder<>(); + } + + public static WeightedList fromNetwork(FriendlyByteBuf buffer, Function valueReader) { + int size = buffer.readVarInt(); + Object[] values = new Object[size]; + int[] weights = new int[size]; + int totalWeight = 0; + for (int i = 0; i < size; i++) { + values[i] = Objects.requireNonNull(valueReader.apply(buffer), "Failed to read weighted list value from network"); + totalWeight += weights[i] = buffer.readVarInt(); + } + return new WeightedList<>(totalWeight, values, weights); + } + + public JsonArray toJson(Function serializer) { + JsonArray array = new JsonArray(); + for (int i = 0; i < this.values.length; i++) { + @SuppressWarnings("unchecked") + var value = serializer.apply((T) this.values[i]); + var weight = this.weights[i]; + var json = new JsonObject(); + json.add("value", value); + json.addProperty("weight", weight); + array.add(json); + } + return array; + } + + @Nullable + public static WeightedList fromJson(JsonArray array, Function deserializer) { + WeightedList.Builder list = WeightedList.builder(); + + for (var element : array) { + if (element instanceof JsonObject obj) { + int weight = GsonHelper.getAsInt(obj, "weight"); + var value = deserializer.apply(obj.get("value")); + if (value == null) { + return null; + } else { + list.add(weight, value); + } + } else { + throw new JsonSyntaxException("Invalid weighted list entry"); + } + } + return list.build(); + } + + public static class Builder { + private final ArrayList values = new ArrayList<>(); + private final IntArrayList weights = new IntArrayList(); + private int totalWeight; + + public Builder add(int weight, T element) { + this.totalWeight += weight; + this.values.add(element); + this.weights.add(weight); + return this; + } + + public WeightedList build() { + return new WeightedList<>(this.totalWeight, this.values.toArray(), this.weights.toArray(new int[0])); + } + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelFluidMixingRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelFluidMixingRecipe.java index cacf5a83..f56cc460 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelFluidMixingRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/BarrelFluidMixingRecipe.java @@ -76,7 +76,7 @@ public class BarrelFluidMixingRecipe implements Recipe { @Override public ItemStack getResultItem(RegistryAccess pRegistryAccess) { - return ItemStack.EMPTY; + return new ItemStack(this.result); } @Override diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelCompostRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelCompostRecipe.java index 677baa23..f393f49a 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelCompostRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelCompostRecipe.java @@ -25,13 +25,12 @@ import net.minecraft.world.item.crafting.RecipeSerializer; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; import thedarkcolour.exdeorum.registry.ERecipeSerializers; -public class FinishedBarrelCompostRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedBarrelCompostRecipe extends EFinishedRecipe { private final Ingredient ingredient; private final int volume; public FinishedBarrelCompostRecipe(ResourceLocation id, Ingredient ingredient, int volume) { - this.id = id; + super(id); this.ingredient = ingredient; this.volume = volume; } @@ -42,11 +41,6 @@ public class FinishedBarrelCompostRecipe implements EFinishedRecipe { json.addProperty("volume", this.volume); } - @Override - public ResourceLocation getId() { - return this.id; - } - @Override public RecipeSerializer getType() { return ERecipeSerializers.BARREL_COMPOST.get(); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java index 201e55ef..e3f4fc28 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java @@ -19,16 +19,15 @@ package thedarkcolour.exdeorum.recipe.barrel; import com.google.gson.JsonObject; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.level.material.Fluid; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; +import thedarkcolour.exdeorum.recipe.RecipeUtil; import thedarkcolour.exdeorum.registry.ERecipeSerializers; -public class FinishedBarrelFluidMixingRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedBarrelFluidMixingRecipe extends EFinishedRecipe { private final Fluid baseFluid; private final int baseFluidAmount; private final Fluid additiveFluid; @@ -36,7 +35,7 @@ public class FinishedBarrelFluidMixingRecipe implements EFinishedRecipe { private final boolean consumesAdditive; public FinishedBarrelFluidMixingRecipe(ResourceLocation id, Fluid baseFluid, int baseFluidAmount, Fluid additiveFluid, Item result, boolean consumesAdditive) { - this.id = id; + super(id); this.baseFluid = baseFluid; this.baseFluidAmount = baseFluidAmount; this.additiveFluid = additiveFluid; @@ -46,16 +45,11 @@ public class FinishedBarrelFluidMixingRecipe implements EFinishedRecipe { @Override public void serializeRecipeData(JsonObject json) { - json.addProperty("base_fluid", BuiltInRegistries.FLUID.getKey(this.baseFluid).toString()); + json.addProperty("base_fluid", RecipeUtil.getFluidId(this.baseFluid)); json.addProperty("base_fluid_amount", this.baseFluidAmount); - json.addProperty("additive_fluid", BuiltInRegistries.FLUID.getKey(this.additiveFluid).toString()); + json.addProperty("additive_fluid", RecipeUtil.getFluidId(this.additiveFluid)); json.addProperty("consumes_additive", this.consumesAdditive); - json.addProperty("result", BuiltInRegistries.ITEM.getKey(this.result).toString()); - } - - @Override - public ResourceLocation getId() { - return this.id; + json.addProperty("result", RecipeUtil.writeItemJson(this.result)); } @Override diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java index 9a9194d7..132f04f3 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java @@ -28,15 +28,14 @@ import net.minecraft.world.level.material.Fluid; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; import thedarkcolour.exdeorum.registry.ERecipeSerializers; -public class FinishedBarrelMixingRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedBarrelMixingRecipe extends EFinishedRecipe { private final Ingredient ingredient; private final Fluid fluid; private final int fluidAmount; private final Item result; public FinishedBarrelMixingRecipe(ResourceLocation id, Ingredient ingredient, Fluid fluid, int fluidAmount, Item result) { - this.id = id; + super(id); this.ingredient = ingredient; this.fluid = fluid; this.fluidAmount = fluidAmount; @@ -51,11 +50,6 @@ public class FinishedBarrelMixingRecipe implements EFinishedRecipe { json.addProperty("result", BuiltInRegistries.ITEM.getKey(this.result).toString()); } - @Override - public ResourceLocation getId() { - return this.id; - } - @Override public RecipeSerializer getType() { return ERecipeSerializers.BARREL_MIXING.get(); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedFluidTransformationRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedFluidTransformationRecipe.java new file mode 100644 index 00000000..3314629c --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedFluidTransformationRecipe.java @@ -0,0 +1,64 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.recipe.barrel; + +import com.google.gson.JsonObject; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import thedarkcolour.exdeorum.recipe.BlockPredicate; +import thedarkcolour.exdeorum.recipe.EFinishedRecipe; +import thedarkcolour.exdeorum.recipe.RecipeUtil; +import thedarkcolour.exdeorum.recipe.WeightedList; +import thedarkcolour.exdeorum.registry.ERecipeSerializers; + +public class FinishedFluidTransformationRecipe extends EFinishedRecipe { + private final Fluid baseFluid; + private final Fluid resultFluid; + private final int resultColor; + private final BlockPredicate catalyst; + private final WeightedList byproducts; + private final int duration; + + public FinishedFluidTransformationRecipe(ResourceLocation id, Fluid baseFluid, Fluid resultFluid, int resultColor, BlockPredicate catalyst, WeightedList byproducts, int duration) { + super(id); + this.baseFluid = baseFluid; + this.resultFluid = resultFluid; + this.resultColor = resultColor; + this.catalyst = catalyst; + this.byproducts = byproducts; + this.duration = duration; + } + + @Override + public void serializeRecipeData(JsonObject json) { + json.addProperty("base_fluid", RecipeUtil.getFluidId(this.baseFluid)); + json.addProperty("result_fluid", RecipeUtil.getFluidId(this.resultFluid)); + json.addProperty("result_color", this.resultColor); + json.addProperty("duration", this.duration); + json.add("catalyst", this.catalyst.toJson()); + json.add("byproducts", this.byproducts.toJson(RecipeUtil::writeBlockState)); + } + + @Override + public RecipeSerializer getType() { + return ERecipeSerializers.BARREL_FLUID_TRANSFORMATION.get(); + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FluidTransformationRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FluidTransformationRecipe.java new file mode 100644 index 00000000..8d2cce2b --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FluidTransformationRecipe.java @@ -0,0 +1,165 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.recipe.barrel; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import net.minecraft.core.RegistryAccess; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.Nullable; +import thedarkcolour.exdeorum.ExDeorum; +import thedarkcolour.exdeorum.recipe.BlockPredicate; +import thedarkcolour.exdeorum.recipe.RecipeUtil; +import thedarkcolour.exdeorum.recipe.WeightedList; +import thedarkcolour.exdeorum.registry.ERecipeSerializers; +import thedarkcolour.exdeorum.registry.ERecipeTypes; + +import java.util.Objects; + +// todo consider NBT tag of input fluid? +public class FluidTransformationRecipe implements Recipe { + private final ResourceLocation id; + + public final Fluid baseFluid; + public final Fluid resultFluid; + public final int resultColor; + public final BlockPredicate catalyst; + public final WeightedList byproducts; + public final int duration; + + public FluidTransformationRecipe(ResourceLocation id, Fluid baseFluid, Fluid resultFluid, int resultColor, BlockPredicate catalyst, WeightedList byproducts, int duration) { + this.id = id; + this.baseFluid = baseFluid; + this.resultFluid = resultFluid; + this.resultColor = resultColor; + this.catalyst = catalyst; + this.byproducts = byproducts; + this.duration = duration; + } + + @Override + public boolean matches(Container pContainer, Level pLevel) { + return false; + } + + @Override + public ItemStack assemble(Container pContainer, RegistryAccess pRegistryAccess) { + return ItemStack.EMPTY; + } + + @Override + public boolean canCraftInDimensions(int pWidth, int pHeight) { + return false; + } + + @Override + public ItemStack getResultItem(RegistryAccess pRegistryAccess) { + return ItemStack.EMPTY; + } + + @Override + public ResourceLocation getId() { + return this.id; + } + + @Override + public RecipeSerializer getSerializer() { + return ERecipeSerializers.BARREL_FLUID_TRANSFORMATION.get(); + } + + @Override + public RecipeType getType() { + return ERecipeTypes.BARREL_FLUID_TRANSFORMATION.get(); + } + + public static class Serializer implements RecipeSerializer { + @Override + public FluidTransformationRecipe fromJson(ResourceLocation id, JsonObject json) { + Fluid baseFluid = RecipeUtil.readFluid(json, "base_fluid"); + Fluid resultFluid = RecipeUtil.readFluid(json, "result_fluid"); + int resultColor = GsonHelper.getAsInt(json, "result_color"); + int duration = GsonHelper.getAsInt(json, "duration"); + BlockPredicate catalyst = RecipeUtil.readBlockPredicate(id, json, "catalyst"); + var byproducts = WeightedList.fromJson(json.getAsJsonArray("byproducts"), element -> { + if (element.isJsonPrimitive()) { + return RecipeUtil.parseBlockState(element.getAsString()); + } else { + return null; + } + }); + if (catalyst == null) { + throw new JsonSyntaxException("Failed to read barrel fluid transformation recipe catalyst"); + } + if (byproducts == null) { + throw new JsonSyntaxException("Failed to read barrel fluid transformation recipe byproducts"); + } + return new FluidTransformationRecipe(id, baseFluid, resultFluid, resultColor, catalyst, byproducts, duration); + } + + @Override + public void toNetwork(FriendlyByteBuf buffer, FluidTransformationRecipe recipe) { + buffer.writeRegistryId(ForgeRegistries.FLUIDS, recipe.baseFluid); + buffer.writeRegistryId(ForgeRegistries.FLUIDS, recipe.resultFluid); + buffer.writeInt(recipe.resultColor); + recipe.catalyst.toNetwork(buffer); + recipe.byproducts.toNetwork(buffer, (buf, state) -> buf.writeId(Block.BLOCK_STATE_REGISTRY, state)); + buffer.writeVarInt(recipe.duration); + } + + @Override + public @Nullable FluidTransformationRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) { + Fluid baseFluid = buffer.readRegistryId(); + Fluid resultFluid = buffer.readRegistryId(); + int resultColor = buffer.readInt(); + BlockPredicate catalyst = RecipeUtil.readBlockPredicateNetwork(id, buffer); + if (catalyst == null) { + return null; + } + WeightedList byproducts = WeightedList.fromNetwork(buffer, buf -> buf.readById(Block.BLOCK_STATE_REGISTRY)); + int duration = buffer.readVarInt(); + return new FluidTransformationRecipe(id, baseFluid, resultFluid, resultColor, catalyst, byproducts, duration); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FluidTransformationRecipe that = (FluidTransformationRecipe) o; + return this.resultColor == that.resultColor && this.duration == that.duration && Objects.equals(this.id, that.id) && Objects.equals(this.baseFluid, that.baseFluid) && Objects.equals(this.resultFluid, that.resultFluid) && Objects.equals(this.catalyst, that.catalyst) && Objects.equals(this.byproducts, that.byproducts); + } + + @Override + public int hashCode() { + return Objects.hash(this.id, this.baseFluid, this.resultFluid, this.resultColor, this.catalyst, this.byproducts, this.duration); + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/cache/FluidTransformationRecipeCache.java b/src/main/java/thedarkcolour/exdeorum/recipe/cache/FluidTransformationRecipeCache.java new file mode 100644 index 00000000..6e31f605 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/cache/FluidTransformationRecipeCache.java @@ -0,0 +1,69 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.recipe.cache; + +import net.minecraft.world.item.crafting.RecipeManager; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import org.jetbrains.annotations.Nullable; +import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; +import thedarkcolour.exdeorum.registry.ERecipeTypes; + +import java.util.HashMap; +import java.util.Map; + +public class FluidTransformationRecipeCache { + private RecipeManager recipeManager; + @Nullable + private Map> recipes; + + public FluidTransformationRecipeCache(RecipeManager manager) { + this.recipeManager = manager; + } + + @Nullable + public FluidTransformationRecipe getRecipe(Fluid baseFluid, BlockState catalystState) { + if (this.recipes == null) { + buildRecipes(); + } + var recipesForBase = this.recipes.get(catalystState); + if (recipesForBase != null) { + return recipesForBase.get(baseFluid); + } + return null; + } + + private void buildRecipes() { + this.recipes = new HashMap<>(); + + for (var recipe : this.recipeManager.byType(ERecipeTypes.BARREL_FLUID_TRANSFORMATION.get()).values()) { + recipe.catalyst.possibleStates().forEach(state -> { + this.recipes.computeIfAbsent(state, key -> new HashMap<>()).put(recipe.baseFluid, recipe); + }); + } + + var dedupe = new HashMap, Map>(); + for (var entry : this.recipes.entrySet()) { + entry.setValue(dedupe.computeIfAbsent(entry.getValue(), Map::copyOf)); + } + this.recipes = Map.copyOf(this.recipes); + + this.recipeManager = null; + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crook/CrookRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crook/CrookRecipe.java index f070919e..0ffb2a95 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/crook/CrookRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crook/CrookRecipe.java @@ -76,7 +76,7 @@ public record CrookRecipe(ResourceLocation id, BlockPredicate blockPredicate, It public static class Serializer implements RecipeSerializer { @Override public CrookRecipe fromJson(ResourceLocation id, JsonObject json) { - BlockPredicate blockPredicate = RecipeUtil.readBlockPredicate(id, json); + BlockPredicate blockPredicate = RecipeUtil.readBlockPredicate(id, json, "block_predicate"); if (blockPredicate == null) return null; Item result = RecipeUtil.readItem(json, "result"); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crook/FinishedCrookRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crook/FinishedCrookRecipe.java index 31b42ae6..1bbd21ef 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/crook/FinishedCrookRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crook/FinishedCrookRecipe.java @@ -27,14 +27,13 @@ import thedarkcolour.exdeorum.recipe.BlockPredicate; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; import thedarkcolour.exdeorum.registry.ERecipeSerializers; -public class FinishedCrookRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedCrookRecipe extends EFinishedRecipe { private final BlockPredicate predicate; private final Item result; private final float chance; public FinishedCrookRecipe(ResourceLocation id, BlockPredicate predicate, Item result, float chance) { - this.id = id; + super(id); this.predicate = predicate; this.result = result; this.chance = chance; @@ -47,11 +46,6 @@ public class FinishedCrookRecipe implements EFinishedRecipe { json.addProperty("chance", this.chance); } - @Override - public ResourceLocation getId() { - return this.id; - } - @Override public RecipeSerializer getType() { return ERecipeSerializers.CROOK.get(); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleHeatRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleHeatRecipe.java index 4b1486f3..8d0c4b2b 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleHeatRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleHeatRecipe.java @@ -72,7 +72,7 @@ public record CrucibleHeatRecipe(ResourceLocation id, BlockPredicate blockPredic public static class Serializer implements RecipeSerializer { @Override public CrucibleHeatRecipe fromJson(ResourceLocation id, JsonObject json) { - BlockPredicate blockPredicate = RecipeUtil.readBlockPredicate(id, json); + BlockPredicate blockPredicate = RecipeUtil.readBlockPredicate(id, json, "block_predicate"); if (blockPredicate == null) return null; int heatValue = json.get("heat_value").getAsInt(); return new CrucibleHeatRecipe(id, blockPredicate, heatValue); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleRecipe.java index 781f86ac..05ee26df 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/CrucibleRecipe.java @@ -26,7 +26,6 @@ import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; import net.minecraftforge.fluids.FluidStack; import thedarkcolour.exdeorum.recipe.RecipeUtil; -import thedarkcolour.exdeorum.recipe.CodecUtil; import thedarkcolour.exdeorum.recipe.SingleIngredientRecipe; import thedarkcolour.exdeorum.registry.ERecipeSerializers; @@ -42,7 +41,7 @@ public class CrucibleRecipe extends SingleIngredientRecipe { this.result = result; if (this.dependsOnNbt) { - throw new IllegalArgumentException("Cannot use NBT to determine Ex Nihilo Reborn Crucible output"); + throw new IllegalArgumentException("Cannot use NBT to determine Ex Deorum Crucible output"); } } @@ -70,7 +69,7 @@ public class CrucibleRecipe extends SingleIngredientRecipe { @Override public CrucibleRecipe fromJson(ResourceLocation id, JsonObject json) { Ingredient ingredient = RecipeUtil.readIngredient(json, "ingredient"); - FluidStack stack = CodecUtil.decode(FluidStack.CODEC, json.get("fluid")); + FluidStack stack = RecipeUtil.readFluidStack(json, "fluid"); return new CrucibleRecipe(id, this.type, ingredient, stack); } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleHeatRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleHeatRecipe.java index ef5af76c..7178a7d6 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleHeatRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleHeatRecipe.java @@ -25,13 +25,12 @@ import thedarkcolour.exdeorum.recipe.BlockPredicate; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; import thedarkcolour.exdeorum.registry.ERecipeSerializers; -public class FinishedCrucibleHeatRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedCrucibleHeatRecipe extends EFinishedRecipe { private final BlockPredicate blockPredicate; private final int heatValue; public FinishedCrucibleHeatRecipe(ResourceLocation id, BlockPredicate blockPredicate, int heatValue) { - this.id = id; + super(id); this.blockPredicate = blockPredicate; this.heatValue = heatValue; } @@ -42,11 +41,6 @@ public class FinishedCrucibleHeatRecipe implements EFinishedRecipe { json.addProperty("heat_value", this. heatValue); } - @Override - public ResourceLocation getId() { - return this.id; - } - @Override public RecipeSerializer getType() { return ERecipeSerializers.CRUCIBLE_HEAT_SOURCE.get(); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleRecipe.java index dbcfad74..4bc5bc1d 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crucible/FinishedCrucibleRecipe.java @@ -24,11 +24,10 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.level.material.Fluid; import net.minecraftforge.fluids.FluidStack; -import thedarkcolour.exdeorum.recipe.CodecUtil; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; +import thedarkcolour.exdeorum.recipe.RecipeUtil; -public class FinishedCrucibleRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedCrucibleRecipe extends EFinishedRecipe { private final RecipeSerializer serializer; private final Ingredient ingredient; private final FluidStack fluidStack; @@ -38,7 +37,7 @@ public class FinishedCrucibleRecipe implements EFinishedRecipe { } public FinishedCrucibleRecipe(ResourceLocation id, RecipeSerializer serializer, Ingredient ingredient, FluidStack fluidStack) { - this.id = id; + super(id); this.serializer = serializer; this.ingredient = ingredient; this.fluidStack = fluidStack; @@ -47,12 +46,8 @@ public class FinishedCrucibleRecipe implements EFinishedRecipe { @Override public void serializeRecipeData(JsonObject json) { json.add("ingredient", this.ingredient.toJson()); - json.add("fluid", CodecUtil.encode(FluidStack.CODEC, this.fluidStack)); - } - - @Override - public ResourceLocation getId() { - return this.id; + JsonObject fluidObj = new JsonObject(); + json.add("fluid", RecipeUtil.writeFluidStackJson(this.fluidStack)); } @Override diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java index 7ac47031..c6df501a 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java @@ -29,14 +29,13 @@ import net.minecraft.world.level.storage.loot.providers.number.NumberProvider; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; import thedarkcolour.exdeorum.registry.ERecipeSerializers; -public class FinishedHammerRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedHammerRecipe extends EFinishedRecipe { private final Ingredient ingredient; private final Item result; private final NumberProvider resultAmount; public FinishedHammerRecipe(ResourceLocation id, Ingredient ingredient, Item result, NumberProvider resultAmount) { - this.id = id; + super(id); this.ingredient = ingredient; this.result = result; this.resultAmount = resultAmount; @@ -49,11 +48,6 @@ public class FinishedHammerRecipe implements EFinishedRecipe { object.add("result_amount", LootDataType.PREDICATE.parser().toJsonTree(this.resultAmount)); } - @Override - public ResourceLocation getId() { - return this.id; - } - @Override public RecipeSerializer getType() { return ERecipeSerializers.HAMMER.get(); diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java index 9c06acac..e1d86d1e 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java @@ -31,15 +31,14 @@ import net.minecraft.world.level.storage.loot.providers.number.NumberProvider; import thedarkcolour.exdeorum.recipe.EFinishedRecipe; import thedarkcolour.exdeorum.registry.ERecipeSerializers; -public class FinishedSieveRecipe implements EFinishedRecipe { - private final ResourceLocation id; +public class FinishedSieveRecipe extends EFinishedRecipe { private final Ingredient ingredient; private final Item mesh; private final Either> result; private final NumberProvider resultAmount; public FinishedSieveRecipe(ResourceLocation id, Item mesh, Ingredient ingredient, Either> result, NumberProvider resultAmount) { - this.id = id; + super(id); this.mesh = mesh; this.ingredient = ingredient; this.result = result; @@ -58,11 +57,6 @@ public class FinishedSieveRecipe implements EFinishedRecipe { object.add("result_amount", LootDataType.PREDICATE.parser().toJsonTree(this.resultAmount)); } - @Override - public ResourceLocation getId() { - return this.id; - } - @Override public RecipeSerializer getType() { return ERecipeSerializers.SIEVE.get(); diff --git a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java index 387a7092..9352a5b3 100644 --- a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java +++ b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java @@ -26,6 +26,7 @@ import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.recipe.TagResultRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe; +import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe; import thedarkcolour.exdeorum.recipe.crook.CrookRecipe; import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe; @@ -39,6 +40,7 @@ public class ERecipeSerializers { public static final RegistryObject> BARREL_COMPOST = RECIPE_SERIALIZERS.register("barrel_compost", BarrelCompostRecipe.Serializer::new); public static final RegistryObject> BARREL_MIXING = RECIPE_SERIALIZERS.register("barrel_mixing", BarrelMixingRecipe.Serializer::new); public static final RegistryObject> BARREL_FLUID_MIXING = RECIPE_SERIALIZERS.register("barrel_fluid_mixing", BarrelFluidMixingRecipe.Serializer::new); + public static final RegistryObject> BARREL_FLUID_TRANSFORMATION = RECIPE_SERIALIZERS.register("barrel_fluid_transformation", FluidTransformationRecipe.Serializer::new); public static final RegistryObject> HAMMER = RECIPE_SERIALIZERS.register("hammer", HammerRecipe.Serializer::new); public static final RegistryObject> CROOK = RECIPE_SERIALIZERS.register("crook", CrookRecipe.Serializer::new); diff --git a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java index 3bcf1e88..9c431ae8 100644 --- a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java +++ b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java @@ -25,6 +25,7 @@ import net.minecraftforge.registries.RegistryObject; import thedarkcolour.exdeorum.ExDeorum; import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe; +import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe; import thedarkcolour.exdeorum.recipe.crook.CrookRecipe; import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe; @@ -38,6 +39,7 @@ public class ERecipeTypes { public static final RegistryObject> BARREL_COMPOST = RECIPE_TYPES.register("barrel_compost", () -> RecipeType.simple(ERecipeTypes.BARREL_COMPOST.getId())); public static final RegistryObject> BARREL_MIXING = RECIPE_TYPES.register("barrel_mixing", () -> RecipeType.simple(ERecipeTypes.BARREL_MIXING.getId())); public static final RegistryObject> BARREL_FLUID_MIXING = RECIPE_TYPES.register("barrel_fluid_mixing", () -> RecipeType.simple(ERecipeTypes.BARREL_FLUID_MIXING.getId())); + public static final RegistryObject> BARREL_FLUID_TRANSFORMATION = RECIPE_TYPES.register("barrel_fluid_transformation", () -> RecipeType.simple(ERecipeTypes.BARREL_FLUID_TRANSFORMATION.getId())); public static final RegistryObject> LAVA_CRUCIBLE = RECIPE_TYPES.register("lava_crucible", () -> RecipeType.simple(ERecipeTypes.LAVA_CRUCIBLE.getId())); public static final RegistryObject> WATER_CRUCIBLE = RECIPE_TYPES.register("water_crucible", () -> RecipeType.simple(ERecipeTypes.WATER_CRUCIBLE.getId())); diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeSerializationTests.java b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeSerializationTests.java index 1867cebc..672465d3 100644 --- a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeSerializationTests.java +++ b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeSerializationTests.java @@ -18,6 +18,7 @@ package thedarkcolour.exdeorum.recipe; +import com.google.gson.JsonObject; import io.netty.buffer.Unpooled; import net.minecraft.SharedConstants; import net.minecraft.network.FriendlyByteBuf; @@ -26,10 +27,17 @@ import net.minecraft.tags.BlockTags; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import thedarkcolour.exdeorum.recipe.barrel.FinishedFluidTransformationRecipe; +import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; import thedarkcolour.exdeorum.recipe.crook.CrookRecipe; import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe; +import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleHeatRecipe; + +import java.util.function.Function; import static org.junit.jupiter.api.Assertions.*; @@ -48,7 +56,21 @@ public class RecipeSerializationTests { @Test void crucibleHeatSourceJson() { - fail(); + testJson(new CrucibleHeatRecipe(null, BlockPredicate.blockTag(BlockTags.DIRT), 3), new CrucibleHeatRecipe.Serializer(), recipe -> { + return new FinishedCrucibleHeatRecipe(recipe.id(), recipe.blockPredicate(), recipe.heatValue()); + }); + } + + @Test + void barrelFluidTransformationNetwork() { + testNetwork(new FluidTransformationRecipe(null, Fluids.WATER, Fluids.LAVA, 1, BlockPredicate.blockTag(BlockTags.DIRT), WeightedList.builder().build(), 1000), new FluidTransformationRecipe.Serializer()); + } + + @Test + void barrelFluidTransformationJson() { + testJson(new FluidTransformationRecipe(null, Fluids.WATER, Fluids.LAVA, 1, BlockPredicate.blockTag(BlockTags.DIRT), WeightedList.builder().build(), 1000), new FluidTransformationRecipe.Serializer(), recipe -> { + return new FinishedFluidTransformationRecipe(recipe.getId(), recipe.baseFluid, recipe.resultFluid, recipe.resultColor, recipe.catalyst, recipe.byproducts, recipe.duration); + }); } @Test @@ -64,4 +86,12 @@ public class RecipeSerializationTests { serializer.toNetwork(buffer, recipe); assertEquals(recipe, serializer.fromNetwork(id, buffer)); } + + private static > void testJson(T recipe, RecipeSerializer serializer, Function toJson) { + var id = recipe.getId(); + var finishedRecipe = toJson.apply(recipe); + var json = new JsonObject(); + finishedRecipe.serializeRecipeData(json); + assertEquals(recipe, serializer.fromJson(id, json)); + } } diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java index 5e86d255..fab6c275 100644 --- a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java +++ b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java @@ -18,11 +18,17 @@ package thedarkcolour.exdeorum.recipe; +import com.google.gson.JsonObject; import net.minecraft.SharedConstants; +import net.minecraft.core.Direction; import net.minecraft.server.Bootstrap; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.material.Fluids; import net.minecraftforge.common.Tags; +import net.minecraftforge.fluids.FluidStack; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,6 +41,19 @@ class RecipeUtilTest { Bootstrap.bootStrap(); } + @Test + void jsonFluidStack() { + var fluidStack = new FluidStack(Fluids.LAVA, 345); + var root = new JsonObject(); + root.add("test", RecipeUtil.writeFluidStackJson(fluidStack)); + var testStack = RecipeUtil.readFluidStack(root, "test"); + assertTrue( + testStack.getAmount() == fluidStack.getAmount() && + testStack.getFluid() == fluidStack.getFluid() && + testStack.getTag() == fluidStack.getTag() + ); + } + @Test void areIngredientsEqual() { assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB), Ingredient.of(Items.OAK_SLAB))); @@ -45,4 +64,10 @@ class RecipeUtilTest { assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB, Items.SPRUCE_SLAB), Ingredient.of(Items.SPRUCE_SLAB, Items.OAK_SLAB))); assertFalse(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB, Items.SPRUCE_SLAB), Ingredient.of(Items.SPRUCE_SLAB, Items.OAK_SLAB, Items.OAK_SLAB))); } + + @Test + void stringBlockState() { + var state = Blocks.ACACIA_LOG.defaultBlockState().setValue(BlockStateProperties.AXIS, Direction.Axis.Z); + assertEquals(state, RecipeUtil.parseBlockState(RecipeUtil.writeBlockState(state).getAsString())); + } } \ No newline at end of file diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/WeightedListTest.java b/src/test/java/thedarkcolour/exdeorum/recipe/WeightedListTest.java new file mode 100644 index 00000000..2c0d9868 --- /dev/null +++ b/src/test/java/thedarkcolour/exdeorum/recipe/WeightedListTest.java @@ -0,0 +1,105 @@ +/* + * Ex Deorum + * Copyright (c) 2024 thedarkcolour + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package thedarkcolour.exdeorum.recipe; + +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.XoroshiroRandomSource; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class WeightedListTest { + + @Test + void isEmpty() { + WeightedList.Builder list = WeightedList.builder(); + assertTrue(list.build().isEmpty()); + } + + @Test + void getRandom() { + RandomSource rand = new XoroshiroRandomSource(123, 123); + // An equal list should give all elements a roughly equal chance of appearing randomly + WeightedList equalList = WeightedList.builder() + .add(20, "Hello") + .add(20, "Hi") + .add(20, "How ya doin") + .build(); + + int hellos = 0; + int his = 0; + int howYaDoins = 0; + + for (int i = 0; i < 1_000_000; i++) { + String choice = equalList.getRandom(rand); + switch (choice) { + case "Hello" -> hellos++; + case "Hi" -> his++; + case "How ya doin" -> howYaDoins++; + default -> fail("Bad test"); + } + } + + System.out.println("Hello: " + hellos + String.format(" (%.2f)", (float) hellos / 1000000)); + System.out.println("Hi: " + his + String.format(" (%.2f)", (float) his / 1000000)); + System.out.println("How ya doin: " + howYaDoins + String.format(" (%.2f)", (float) howYaDoins / 1000000)); + + // Ensure that these two elements have roughly the same frequency + assertTrue(Mth.abs((float) hellos / 1_000_000f - (float) his / 1_000_000f) < 0.025f); + + // Test that the weights specified in the list roughly match the random results + WeightedList unbalanced = WeightedList.builder() + .add(60, "Hello") + .add(20, "Hi") + .add(20, "How ya doin") + .build(); + + hellos = 0; + his = 0; + howYaDoins = 0; + + for (int i = 0; i < 1_000_000; i++) { + String choice = unbalanced.getRandom(rand); + switch (choice) { + case "Hello" -> hellos++; + case "Hi" -> his++; + case "How ya doin" -> howYaDoins++; + default -> fail("Bad test"); + } + } + + // Ensure the dominant element has the 60% frequency, just as its 60/100 weight specifies + assertTrue(Mth.abs((float) hellos / 1_000_000f - 0.6f) < 0.025f); + } + + @Test + void testEquals() { + // regular equality + assertNotEquals( + WeightedList.builder().add(20, new Object()).add(30, new Object()).build(), + WeightedList.builder().add(20, new Object()).add(30, new Object()).build() + ); + // deep equality + assertEquals( + WeightedList.builder().add(20, "Hi").add(30, "Hello").build(), + WeightedList.builder().add(20, "Hi").add(30, "Hello").build() + ); + } +} \ No newline at end of file