From 67c0a36b385f67857746c9f776c9c01702105002 Mon Sep 17 00:00:00 2001 From: cech12 Date: Fri, 29 Dec 2023 10:15:24 +0100 Subject: [PATCH] dd neoforge --- .../api/item/UniversalBucketItem.java | 8 +- .../bucketlib/mixin/AxolotlAiMixin.java | 4 +- .../cech12/bucketlib/platform/Services.java | 4 +- .../platform/services/IBucketHelper.java | 14 + .../cech12/bucketlib/util/BucketLibUtil.java | 22 -- .../cech12/bucketlib/util/RegistryUtil.java | 4 +- .../bucketlib/platform/ForgeBucketHelper.java | 34 +++ ....bucketlib.platform.services.IBucketHelper | 1 + .../models/item/universal_bucket.json | 0 .../cech12/bucketlib/BucketLibTestHelper.java | 2 +- .../cech12/bucketlib/BucketLibTestMod.java | 3 +- .../cech12/bucketlib/CauldronTests.java | 2 +- .../cech12/bucketlib/EntityTests.java | 2 +- .../cech12/bucketlib/FluidHandlerTests.java | 2 +- .../bucketlib/PlayerInteractionResult.java | 2 +- .../cech12/bucketlib/WaterloggedTests.java | 2 +- .../bucketlib/WorldInteractionTests.java | 2 +- neoforge/build.gradle | 76 +++++ .../de/cech12/bucketlib/BucketLibMod.java | 166 +++++++++++ .../de/cech12/bucketlib/api/BucketLibApi.java | 14 + .../api/crafting/FluidIngredient.java | 129 +++++++++ .../api/crafting/MilkIngredient.java | 67 +++++ .../cech12/bucketlib/client/ClientEvents.java | 21 ++ .../client/model/UniversalBucketModel.java | 268 ++++++++++++++++++ .../item/UniversalBucketFluidHandler.java | 101 +++++++ .../bucketlib/mixin/NeoforgeItemMixin.java | 76 +++++ .../platform/NeoforgeBucketHelper.java | 34 +++ .../platform/NeoforgeConfigHelper.java | 56 ++++ .../platform/NeoforgeFluidHelper.java | 97 +++++++ .../platform/NeoforgePlatformHelper.java | 39 +++ .../platform/NeoforgeRegistryHelper.java | 54 ++++ .../src/main/resources/META-INF/mods.toml | 28 ++ ....bucketlib.platform.services.IBucketHelper | 1 + ....bucketlib.platform.services.IConfigHelper | 1 + ...2.bucketlib.platform.services.IFluidHelper | 1 + ...ucketlib.platform.services.IPlatformHelper | 1 + ...ucketlib.platform.services.IRegistryHelper | 1 + .../models/item/universal_bucket.json | 12 + .../resources/bucketlib.neoforge.mixins.json | 13 + .../bucketlib/aquaculture/turtle_soup.json | 2 +- .../de/cech12/bucketlib/BucketLibTestMod.java | 65 +++++ .../src/test/resources/META-INF/mods.toml | 11 + .../assets/bucketlibtest/lang/en_us.json | 64 +++++ .../models/item/anti_milk_bucket.json | 7 + .../models/item/anti_salmon_bucket.json | 7 + .../models/item/burning_bucket.json | 7 + .../models/item/colored_bucket.json | 7 + .../models/item/cracking_bucket.json | 7 + .../models/item/durability_bucket.json | 7 + .../models/item/freezing_bucket.json | 7 + .../models/item/no_blocks_bucket.json | 7 + .../models/item/no_entities_bucket.json | 6 + .../models/item/only_puffer_bucket.json | 7 + .../models/item/temperature_bucket.json | 7 + .../models/item/test_bucket.json | 7 + .../models/item/water_allowing_bucket.json | 7 + .../item/water_allowing_tag_bucket.json | 7 + .../models/item/water_denying_bucket.json | 7 + .../models/item/water_denying_tag_bucket.json | 7 + .../textures/item/lower_test_bucket.png | Bin 0 -> 261 bytes .../textures/item/test_bucket.png | Bin 0 -> 266 bytes .../recipes/emptybucketrecipe.json | 12 + .../recipes/emptybucketrecipe_shaped.json | 15 + .../bucketlibtest/recipes/fluidrecipe.json | 17 ++ .../bucketlibtest/recipes/milkrecipe.json | 15 + .../data/bucketlibtest/tags/fluids/water.json | 6 + settings.gradle | 2 +- 67 files changed, 1642 insertions(+), 42 deletions(-) create mode 100644 common/src/main/java/de/cech12/bucketlib/platform/services/IBucketHelper.java create mode 100644 forge/src/main/java/de/cech12/bucketlib/platform/ForgeBucketHelper.java create mode 100644 forge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper rename {common => forge}/src/main/resources/assets/bucketlib/models/item/universal_bucket.json (100%) rename forge/src/test/java/{ => de}/cech12/bucketlib/BucketLibTestHelper.java (99%) rename forge/src/test/java/{ => de}/cech12/bucketlib/BucketLibTestMod.java (98%) rename forge/src/test/java/{ => de}/cech12/bucketlib/CauldronTests.java (99%) rename forge/src/test/java/{ => de}/cech12/bucketlib/EntityTests.java (99%) rename forge/src/test/java/{ => de}/cech12/bucketlib/FluidHandlerTests.java (99%) rename forge/src/test/java/{ => de}/cech12/bucketlib/PlayerInteractionResult.java (96%) rename forge/src/test/java/{ => de}/cech12/bucketlib/WaterloggedTests.java (99%) rename forge/src/test/java/{ => de}/cech12/bucketlib/WorldInteractionTests.java (99%) create mode 100644 neoforge/build.gradle create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/BucketLibMod.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/api/BucketLibApi.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/api/crafting/FluidIngredient.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/api/crafting/MilkIngredient.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/client/ClientEvents.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/client/model/UniversalBucketModel.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/item/UniversalBucketFluidHandler.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/mixin/NeoforgeItemMixin.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeBucketHelper.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeConfigHelper.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeFluidHelper.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgePlatformHelper.java create mode 100644 neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeRegistryHelper.java create mode 100644 neoforge/src/main/resources/META-INF/mods.toml create mode 100644 neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper create mode 100644 neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IConfigHelper create mode 100644 neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IFluidHelper create mode 100644 neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IPlatformHelper create mode 100644 neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IRegistryHelper create mode 100644 neoforge/src/main/resources/assets/bucketlib/models/item/universal_bucket.json create mode 100644 neoforge/src/main/resources/bucketlib.neoforge.mixins.json rename {forge => neoforge}/src/main/resources/data/bucketlib/aquaculture/turtle_soup.json (91%) create mode 100644 neoforge/src/test/java/de/cech12/bucketlib/BucketLibTestMod.java create mode 100644 neoforge/src/test/resources/META-INF/mods.toml create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/lang/en_us.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_milk_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_salmon_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/burning_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/colored_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/cracking_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/durability_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/freezing_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/no_blocks_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/no_entities_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/only_puffer_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/temperature_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/test_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_tag_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_tag_bucket.json create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/textures/item/lower_test_bucket.png create mode 100644 neoforge/src/test/resources/assets/bucketlibtest/textures/item/test_bucket.png create mode 100644 neoforge/src/test/resources/data/bucketlibtest/recipes/emptybucketrecipe.json create mode 100644 neoforge/src/test/resources/data/bucketlibtest/recipes/emptybucketrecipe_shaped.json create mode 100644 neoforge/src/test/resources/data/bucketlibtest/recipes/fluidrecipe.json create mode 100644 neoforge/src/test/resources/data/bucketlibtest/recipes/milkrecipe.json create mode 100644 neoforge/src/test/resources/data/bucketlibtest/tags/fluids/water.json diff --git a/common/src/main/java/de/cech12/bucketlib/api/item/UniversalBucketItem.java b/common/src/main/java/de/cech12/bucketlib/api/item/UniversalBucketItem.java index cd5988f..fb357f4 100644 --- a/common/src/main/java/de/cech12/bucketlib/api/item/UniversalBucketItem.java +++ b/common/src/main/java/de/cech12/bucketlib/api/item/UniversalBucketItem.java @@ -112,7 +112,7 @@ public boolean canHoldFluid(Fluid fluid) { if (bucket instanceof MilkBucketItem && fluid != Services.FLUID.getMilkFluid()) { return false; } - if (!(bucket instanceof MilkBucketItem) && (!(bucket instanceof BucketItem) || BucketLibUtil.getFluidOfBucketItem((BucketItem) bucket) != fluid)) { + if (!(bucket instanceof MilkBucketItem) && (!(bucket instanceof BucketItem) || Services.BUCKET.getFluidOfBucketItem((BucketItem) bucket) != fluid)) { return false; } if (this.properties.allowedFluidsTag != null || this.properties.allowedFluids != null) { @@ -308,8 +308,8 @@ public InteractionResult interactLivingEntity(@Nonnull ItemStack itemStack, @Non if (entity instanceof Axolotl axolotl && BucketLibUtil.containsEntityType(itemStack) && Arrays.stream(AxolotlAi.getTemptations().getItems()).anyMatch( stack -> stack.getItem() instanceof MobBucketItem mobBucketItem - && BucketLibUtil.getFluid(itemStack) == BucketLibUtil.getFluidOfBucketItem(mobBucketItem) - && BucketLibUtil.getEntityType(itemStack) == BucketLibUtil.getEntityTypeOfMobBucketItem(mobBucketItem) + && BucketLibUtil.getFluid(itemStack) == Services.BUCKET.getFluidOfBucketItem(mobBucketItem) + && BucketLibUtil.getEntityType(itemStack) == Services.BUCKET.getEntityTypeOfMobBucketItem(mobBucketItem) )) { int age = axolotl.getAge(); if (!axolotl.level().isClientSide && age == 0 && axolotl.canFallInLove()) { @@ -336,7 +336,7 @@ public InteractionResult interactLivingEntity(@Nonnull ItemStack itemStack, @Non private InteractionResult pickupEntityWithBucket(Player player, InteractionHand interactionHand, T entity) { ItemStack itemStack = player.getItemInHand(interactionHand).copy(); //copy to avoid changing the real item stack Fluid containedFluid = Services.FLUID.getContainedFluid(itemStack); - Fluid entityBucketFluid = BucketLibUtil.getFluidOfBucketItem((BucketItem) entity.getBucketItemStack().getItem()); + Fluid entityBucketFluid = Services.BUCKET.getFluidOfBucketItem((BucketItem) entity.getBucketItemStack().getItem()); if (itemStack.getItem() instanceof UniversalBucketItem && entity.isAlive() && entityBucketFluid == containedFluid) { diff --git a/common/src/main/java/de/cech12/bucketlib/mixin/AxolotlAiMixin.java b/common/src/main/java/de/cech12/bucketlib/mixin/AxolotlAiMixin.java index 026db91..5348979 100644 --- a/common/src/main/java/de/cech12/bucketlib/mixin/AxolotlAiMixin.java +++ b/common/src/main/java/de/cech12/bucketlib/mixin/AxolotlAiMixin.java @@ -30,8 +30,8 @@ private static void getTemptationsProxy(CallbackInfoReturnable cir) for (ItemStack stack : cir.getReturnValue().getItems()) { temptationStacks.add(stack); if (stack.getItem() instanceof MobBucketItem mobBucketItem) { - Fluid fluid = BucketLibUtil.getFluidOfBucketItem(mobBucketItem); - EntityType entityType = BucketLibUtil.getEntityTypeOfMobBucketItem(mobBucketItem); + Fluid fluid = Services.BUCKET.getFluidOfBucketItem(mobBucketItem); + EntityType entityType = Services.BUCKET.getEntityTypeOfMobBucketItem(mobBucketItem); for (UniversalBucketItem bucketItem : Services.REGISTRY.getRegisteredBuckets()) { if (bucketItem.canHoldFluid(fluid) && bucketItem.canHoldEntity(entityType)) { ItemStack bucket = new ItemStack(bucketItem); diff --git a/common/src/main/java/de/cech12/bucketlib/platform/Services.java b/common/src/main/java/de/cech12/bucketlib/platform/Services.java index b2770c8..702f1d2 100644 --- a/common/src/main/java/de/cech12/bucketlib/platform/Services.java +++ b/common/src/main/java/de/cech12/bucketlib/platform/Services.java @@ -1,7 +1,7 @@ package de.cech12.bucketlib.platform; import de.cech12.bucketlib.CommonLoader; -import de.cech12.bucketlib.api.BucketLib; +import de.cech12.bucketlib.platform.services.IBucketHelper; import de.cech12.bucketlib.platform.services.IConfigHelper; import de.cech12.bucketlib.platform.services.IFluidHelper; import de.cech12.bucketlib.platform.services.IPlatformHelper; @@ -16,6 +16,8 @@ */ public class Services { + /** bucket helper instance */ + public static final IBucketHelper BUCKET = load(IBucketHelper.class); /** Config helper instance */ public static final IConfigHelper CONFIG = load(IConfigHelper.class); /** Fluid helper instance */ diff --git a/common/src/main/java/de/cech12/bucketlib/platform/services/IBucketHelper.java b/common/src/main/java/de/cech12/bucketlib/platform/services/IBucketHelper.java new file mode 100644 index 0000000..f174e5e --- /dev/null +++ b/common/src/main/java/de/cech12/bucketlib/platform/services/IBucketHelper.java @@ -0,0 +1,14 @@ +package de.cech12.bucketlib.platform.services; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.BucketItem; +import net.minecraft.world.item.MobBucketItem; +import net.minecraft.world.level.material.Fluid; + +public interface IBucketHelper { + + Fluid getFluidOfBucketItem(BucketItem bucket); + + EntityType getEntityTypeOfMobBucketItem(MobBucketItem mobBucketItem); + +} diff --git a/common/src/main/java/de/cech12/bucketlib/util/BucketLibUtil.java b/common/src/main/java/de/cech12/bucketlib/util/BucketLibUtil.java index 6eb02ad..04ea2e5 100644 --- a/common/src/main/java/de/cech12/bucketlib/util/BucketLibUtil.java +++ b/common/src/main/java/de/cech12/bucketlib/util/BucketLibUtil.java @@ -283,26 +283,4 @@ public static ItemStack removeBlock(ItemStack itemStack) { return itemStack.copy(); } - public static Fluid getFluidOfBucketItem(BucketItem bucket) { - try { - Field fluidField = BucketItem.class.getDeclaredField("content"); - fluidField.setAccessible(true); - return (Fluid) fluidField.get(bucket); - } catch (IllegalAccessException | NoSuchFieldException ex) { - CommonLoader.LOG.error("Could not get entity type of MobBucketItem.", ex); - } - return Fluids.EMPTY; - } - - public static EntityType getEntityTypeOfMobBucketItem(MobBucketItem mobBucketItem) { - try { - Field entityTypeField = MobBucketItem.class.getDeclaredField("type"); - entityTypeField.setAccessible(true); - return (EntityType) entityTypeField.get(mobBucketItem); - } catch (IllegalAccessException | NoSuchFieldException ex) { - CommonLoader.LOG.error("Could not get entity type of MobBucketItem.", ex); - } - return null; - } - } diff --git a/common/src/main/java/de/cech12/bucketlib/util/RegistryUtil.java b/common/src/main/java/de/cech12/bucketlib/util/RegistryUtil.java index 6768498..a443ce7 100644 --- a/common/src/main/java/de/cech12/bucketlib/util/RegistryUtil.java +++ b/common/src/main/java/de/cech12/bucketlib/util/RegistryUtil.java @@ -29,9 +29,9 @@ private static void readRegistry() { bucketBlocks.add(new BucketBlock(bucket.getBlock(), bucket)); } if (item instanceof MobBucketItem bucket) { - EntityType entityType = BucketLibUtil.getEntityTypeOfMobBucketItem(bucket); + EntityType entityType = Services.BUCKET.getEntityTypeOfMobBucketItem(bucket); if (entityType != null && level != null && entityType.create(level) instanceof Bucketable) { - bucketEntities.add(new BucketEntity(entityType, BucketLibUtil.getFluidOfBucketItem(bucket), bucket)); + bucketEntities.add(new BucketEntity(entityType, Services.BUCKET.getFluidOfBucketItem(bucket), bucket)); } } } diff --git a/forge/src/main/java/de/cech12/bucketlib/platform/ForgeBucketHelper.java b/forge/src/main/java/de/cech12/bucketlib/platform/ForgeBucketHelper.java new file mode 100644 index 0000000..ad85ae7 --- /dev/null +++ b/forge/src/main/java/de/cech12/bucketlib/platform/ForgeBucketHelper.java @@ -0,0 +1,34 @@ +package de.cech12.bucketlib.platform; + +import de.cech12.bucketlib.CommonLoader; +import de.cech12.bucketlib.platform.services.IBucketHelper; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.BucketItem; +import net.minecraft.world.item.MobBucketItem; +import net.minecraft.world.level.material.Fluid; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * The bucket helper implementation for Forge. + */ +public class ForgeBucketHelper implements IBucketHelper { + + @Override + public Fluid getFluidOfBucketItem(BucketItem bucket) { + return bucket.getFluid(); + } + + @Override + public EntityType getEntityTypeOfMobBucketItem(MobBucketItem mobBucketItem) { + try { + Method entityTypeMethod = MobBucketItem.class.getDeclaredMethod("getFishType"); + entityTypeMethod.setAccessible(true); + return (EntityType) entityTypeMethod.invoke(mobBucketItem); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) { + CommonLoader.LOG.error("Could not get entity type of MobBucketItem.", ex); + } + return null; + } +} diff --git a/forge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper b/forge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper new file mode 100644 index 0000000..e934e53 --- /dev/null +++ b/forge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper @@ -0,0 +1 @@ +de.cech12.bucketlib.platform.ForgeBucketHelper \ No newline at end of file diff --git a/common/src/main/resources/assets/bucketlib/models/item/universal_bucket.json b/forge/src/main/resources/assets/bucketlib/models/item/universal_bucket.json similarity index 100% rename from common/src/main/resources/assets/bucketlib/models/item/universal_bucket.json rename to forge/src/main/resources/assets/bucketlib/models/item/universal_bucket.json diff --git a/forge/src/test/java/cech12/bucketlib/BucketLibTestHelper.java b/forge/src/test/java/de/cech12/bucketlib/BucketLibTestHelper.java similarity index 99% rename from forge/src/test/java/cech12/bucketlib/BucketLibTestHelper.java rename to forge/src/test/java/de/cech12/bucketlib/BucketLibTestHelper.java index 588e77c..185f36f 100644 --- a/forge/src/test/java/cech12/bucketlib/BucketLibTestHelper.java +++ b/forge/src/test/java/de/cech12/bucketlib/BucketLibTestHelper.java @@ -1,4 +1,4 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; import com.mojang.authlib.GameProfile; import net.minecraft.core.BlockPos; diff --git a/forge/src/test/java/cech12/bucketlib/BucketLibTestMod.java b/forge/src/test/java/de/cech12/bucketlib/BucketLibTestMod.java similarity index 98% rename from forge/src/test/java/cech12/bucketlib/BucketLibTestMod.java rename to forge/src/test/java/de/cech12/bucketlib/BucketLibTestMod.java index 33f2cda..aca6a8f 100644 --- a/forge/src/test/java/cech12/bucketlib/BucketLibTestMod.java +++ b/forge/src/test/java/de/cech12/bucketlib/BucketLibTestMod.java @@ -1,6 +1,5 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; -import de.cech12.bucketlib.api.BucketLib; import de.cech12.bucketlib.api.BucketLibApi; import de.cech12.bucketlib.api.item.UniversalBucketItem; import net.minecraft.resources.ResourceLocation; diff --git a/forge/src/test/java/cech12/bucketlib/CauldronTests.java b/forge/src/test/java/de/cech12/bucketlib/CauldronTests.java similarity index 99% rename from forge/src/test/java/cech12/bucketlib/CauldronTests.java rename to forge/src/test/java/de/cech12/bucketlib/CauldronTests.java index 1570d4d..49282b6 100644 --- a/forge/src/test/java/cech12/bucketlib/CauldronTests.java +++ b/forge/src/test/java/de/cech12/bucketlib/CauldronTests.java @@ -1,4 +1,4 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; import de.cech12.bucketlib.api.BucketLib; import de.cech12.bucketlib.util.BucketLibUtil; diff --git a/forge/src/test/java/cech12/bucketlib/EntityTests.java b/forge/src/test/java/de/cech12/bucketlib/EntityTests.java similarity index 99% rename from forge/src/test/java/cech12/bucketlib/EntityTests.java rename to forge/src/test/java/de/cech12/bucketlib/EntityTests.java index 5bc352e..b8832ca 100644 --- a/forge/src/test/java/cech12/bucketlib/EntityTests.java +++ b/forge/src/test/java/de/cech12/bucketlib/EntityTests.java @@ -1,4 +1,4 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; import de.cech12.bucketlib.api.BucketLib; import net.minecraft.core.BlockPos; diff --git a/forge/src/test/java/cech12/bucketlib/FluidHandlerTests.java b/forge/src/test/java/de/cech12/bucketlib/FluidHandlerTests.java similarity index 99% rename from forge/src/test/java/cech12/bucketlib/FluidHandlerTests.java rename to forge/src/test/java/de/cech12/bucketlib/FluidHandlerTests.java index 9dae4a2..227c5ba 100644 --- a/forge/src/test/java/cech12/bucketlib/FluidHandlerTests.java +++ b/forge/src/test/java/de/cech12/bucketlib/FluidHandlerTests.java @@ -1,4 +1,4 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; import de.cech12.bucketlib.api.BucketLib; import net.minecraft.world.level.material.Fluid; diff --git a/forge/src/test/java/cech12/bucketlib/PlayerInteractionResult.java b/forge/src/test/java/de/cech12/bucketlib/PlayerInteractionResult.java similarity index 96% rename from forge/src/test/java/cech12/bucketlib/PlayerInteractionResult.java rename to forge/src/test/java/de/cech12/bucketlib/PlayerInteractionResult.java index 03a0f1d..0e7d8a6 100644 --- a/forge/src/test/java/cech12/bucketlib/PlayerInteractionResult.java +++ b/forge/src/test/java/de/cech12/bucketlib/PlayerInteractionResult.java @@ -1,4 +1,4 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; diff --git a/forge/src/test/java/cech12/bucketlib/WaterloggedTests.java b/forge/src/test/java/de/cech12/bucketlib/WaterloggedTests.java similarity index 99% rename from forge/src/test/java/cech12/bucketlib/WaterloggedTests.java rename to forge/src/test/java/de/cech12/bucketlib/WaterloggedTests.java index efe34a9..9d86900 100644 --- a/forge/src/test/java/cech12/bucketlib/WaterloggedTests.java +++ b/forge/src/test/java/de/cech12/bucketlib/WaterloggedTests.java @@ -1,4 +1,4 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; import de.cech12.bucketlib.api.BucketLib; import de.cech12.bucketlib.util.BucketLibUtil; diff --git a/forge/src/test/java/cech12/bucketlib/WorldInteractionTests.java b/forge/src/test/java/de/cech12/bucketlib/WorldInteractionTests.java similarity index 99% rename from forge/src/test/java/cech12/bucketlib/WorldInteractionTests.java rename to forge/src/test/java/de/cech12/bucketlib/WorldInteractionTests.java index fb626a6..24a17c0 100644 --- a/forge/src/test/java/cech12/bucketlib/WorldInteractionTests.java +++ b/forge/src/test/java/de/cech12/bucketlib/WorldInteractionTests.java @@ -1,4 +1,4 @@ -package cech12.bucketlib; +package de.cech12.bucketlib; import de.cech12.bucketlib.api.BucketLib; import net.minecraft.core.BlockPos; diff --git a/neoforge/build.gradle b/neoforge/build.gradle new file mode 100644 index 0000000..c990ac0 --- /dev/null +++ b/neoforge/build.gradle @@ -0,0 +1,76 @@ +plugins { + id 'idea' + id 'maven-publish' + id 'net.neoforged.gradle.userdev' version '7.0.41' + id 'java-library' +} +base { + archivesName = "${mod_id}-neoforge-${minecraft_version}" +} + +// Automatically enable neoforge AccessTransformers if the file exists +// This location is hardcoded in FML and can not be changed. +// https://github.com/neoforged/FancyModLoader/blob/a952595eaaddd571fbc53f43847680b00894e0c1/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/ModFile.java#L118 +if (file('src/main/resources/META-INF/accesstransformer.cfg').exists()) { + minecraft.accessTransformers.file file('src/main/resources/META-INF/accesstransformer.cfg') +} +runs { + configureEach { + modSource project.sourceSets.main + modSource project.sourceSets.test + } + client { + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + server { + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + programArgument '--nogui' + } + gameTestServer { + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + data { + programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() + } +} + +sourceSets.main.resources { srcDir 'src/generated/resources' } + +dependencies { + implementation "net.neoforged:neoforge:${neoforge_version}" + compileOnly project(":common") + testCompileOnly project(":common") +} + +// NeoGradle compiles the game, but we don't want to add our common code to the game's code +Spec notNeoTask = { Task it -> !it.name.startsWith("neo") } as Spec + +tasks.withType(JavaCompile).matching(notNeoTask).configureEach { + source(project(":common").sourceSets.main.allSource) +} + +tasks.withType(Javadoc).matching(notNeoTask).configureEach { + source(project(":common").sourceSets.main.allJava) +} + +tasks.named("sourcesJar", Jar) { + from(project(":common").sourceSets.main.allSource) +} + +tasks.withType(ProcessResources).matching(notNeoTask).configureEach { + from project(":common").sourceSets.main.resources +} + +publishing { + publications { + mavenJava(MavenPublication) { + artifactId base.archivesName.get() + from components.java + } + } + repositories { + maven { + url "file://" + System.getenv("local_maven") + } + } +} \ No newline at end of file diff --git a/neoforge/src/main/java/de/cech12/bucketlib/BucketLibMod.java b/neoforge/src/main/java/de/cech12/bucketlib/BucketLibMod.java new file mode 100644 index 0000000..856f47a --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/BucketLibMod.java @@ -0,0 +1,166 @@ +package de.cech12.bucketlib; + +import de.cech12.bucketlib.api.BucketLib; +import de.cech12.bucketlib.api.BucketLibApi; +import de.cech12.bucketlib.api.BucketLibTags; +import de.cech12.bucketlib.api.crafting.FluidIngredient; +import de.cech12.bucketlib.api.crafting.MilkIngredient; +import de.cech12.bucketlib.api.item.UniversalBucketItem; +import de.cech12.bucketlib.item.UniversalBucketDispenseBehaviour; +import de.cech12.bucketlib.item.crafting.BucketDyeingRecipe; +import de.cech12.bucketlib.util.BucketLibUtil; +import de.cech12.bucketlib.util.ColorUtil; +import de.cech12.bucketlib.util.RegistryUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.level.block.DispenserBlock; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.DistExecutor; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.fml.event.lifecycle.InterModProcessEvent; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.common.NeoForgeMod; +import net.neoforged.neoforge.common.crafting.IngredientType; +import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; +import net.neoforged.neoforge.fluids.FluidUtil; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.neoforged.neoforge.registries.NeoForgeRegistries; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +@Mod(BucketLib.MOD_ID) +public class BucketLibMod { + + public static DeferredRegister> RECIPE_SERIALIZERS = DeferredRegister.create(BuiltInRegistries.RECIPE_SERIALIZER, BucketLib.MOD_ID); + public static DeferredRegister> INGREDIENT_TYPES = DeferredRegister.create(NeoForgeRegistries.Keys.INGREDIENT_TYPES, BucketLib.MOD_ID); + + static { + RECIPE_SERIALIZERS.register("bucket_dyeing", () -> BucketDyeingRecipe.Serializer.INSTANCE); + INGREDIENT_TYPES.register("fluid", () -> FluidIngredient.TYPE); + INGREDIENT_TYPES.register("milk", () -> MilkIngredient.TYPE); + } + + private static final Logger LOGGER = LogManager.getLogger(); + + private static final List buckets = new ArrayList<>(); + + public BucketLibMod(IEventBus eventBus) { + CommonLoader.init(); + + eventBus.addListener(this::commonSetup); + eventBus.addListener(this::processIMC); + eventBus.addListener(this::addItemsToTabs); + + //dye recipe serializer + RECIPE_SERIALIZERS.register(eventBus); + //ingredient serializer + INGREDIENT_TYPES.register(eventBus); + } + + public static List getRegisteredBuckets() { + return Collections.unmodifiableList(buckets); + } + + private void commonSetup(FMLCommonSetupEvent event) { + //Ensure that the tags are initialized + BucketLibTags.init(); + } + + private void processIMC(final InterModProcessEvent event) { + event.getIMCStream().forEach(imcMessage -> { + if (!BucketLib.MOD_ID.equals(imcMessage.modId())) { + LOGGER.warn("Bucket could not be registered. The mod id \"{}\" of the IMCMessage is not \"{}\"", imcMessage.modId(), BucketLib.MOD_ID); + return; + } + if (!BucketLibApi.REGISTER_BUCKET.equals(imcMessage.method())) { + LOGGER.warn("Bucket could not be registered. The method \"{}\" of the IMCMessage is not \"{}\"", imcMessage.method(), BucketLibApi.REGISTER_BUCKET); + return; + } + if (imcMessage.messageSupplier().get() instanceof ResourceLocation bucketLocation && bucketLocation != null) { + Optional bucketItem = BuiltInRegistries.ITEM.getOptional(bucketLocation); + if (bucketItem.isEmpty()) { + LOGGER.info("Bucket could not be registered. The given ResourceLocation \"{}\" does not match any registered item in Forge registry.", bucketLocation); + return; + } + if (bucketItem.get() instanceof UniversalBucketItem bucket) { + registerBucket(bucket); + } else { + LOGGER.info("Bucket could not be registered. The item \"{}\" is not a {}.", bucketLocation, UniversalBucketItem.class.getName()); + } + } else { + LOGGER.warn("Bucket could not be registered. The message supplier of the IMCMessage does not contain a ResourceLocation"); + } + }); + } + + private void registerBucket(UniversalBucketItem bucket) { + buckets.add(bucket); + //register dispense behaviour + DispenserBlock.registerBehavior(bucket, UniversalBucketDispenseBehaviour.getInstance()); + //register color + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> Minecraft.getInstance().getItemColors().register((stack, layer) -> { + if (layer == 0 && bucket.isDyeable()) { + return ColorUtil.getColor(stack, bucket.getDefaultColor()); + } + if (layer == 1) { + return FluidUtil.getFluidContained(stack) + .map(fluidStack -> IClientFluidTypeExtensions.of(fluidStack.getFluid()).getTintColor(fluidStack)) + .orElse(-1); + } + return -1; + }, bucket)); + } + + private void addItemsToTabs(BuildCreativeModeTabContentsEvent event) { + buckets.forEach(bucket -> { + if (event.getTabKey() == bucket.getCreativeTab()) { + ItemStack emptyBucket = new ItemStack(bucket); + //add empty bucket + event.accept(emptyBucket); + //add fluid buckets + for (Fluid fluid : BuiltInRegistries.FLUID) { + if (fluid == Fluids.EMPTY) { + continue; + } + if (NeoForgeMod.MILK.isBound() && NeoForgeMod.MILK.get().isSame(fluid)) { + //skip milk fluid + continue; + } + if (bucket.canHoldFluid(fluid)) { + event.accept(BucketLibUtil.addFluid(emptyBucket, fluid)); + } + } + //add milk bucket + event.accept(BucketLibUtil.addMilk(emptyBucket)); + //add entity buckets + for (RegistryUtil.BucketEntity bucketEntity : RegistryUtil.getBucketEntities()) { + if (bucket.canHoldEntity(bucketEntity.entityType()) && bucket.canHoldFluid(bucketEntity.fluid())) { + ItemStack filledBucket = BucketLibUtil.addFluid(emptyBucket, bucketEntity.fluid()); + filledBucket = BucketLibUtil.addEntityType(filledBucket, bucketEntity.entityType()); + event.accept(filledBucket); + } + } + //add block buckets + for (RegistryUtil.BucketBlock bucketBlock : RegistryUtil.getBucketBlocks()) { + if (bucket.canHoldBlock(bucketBlock.block())) { + event.accept(BucketLibUtil.addBlock(emptyBucket, bucketBlock.block())); + } + } + } + }); + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/api/BucketLibApi.java b/neoforge/src/main/java/de/cech12/bucketlib/api/BucketLibApi.java new file mode 100644 index 0000000..d3d70db --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/api/BucketLibApi.java @@ -0,0 +1,14 @@ +package de.cech12.bucketlib.api; + +import net.minecraft.resources.ResourceLocation; +import net.neoforged.fml.InterModComms; + +public class BucketLibApi { + + public static final String REGISTER_BUCKET = "register_bucket"; + + public static void registerBucket(ResourceLocation bucket) { + InterModComms.sendTo(BucketLib.MOD_ID, REGISTER_BUCKET, () -> bucket); + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/api/crafting/FluidIngredient.java b/neoforge/src/main/java/de/cech12/bucketlib/api/crafting/FluidIngredient.java new file mode 100644 index 0000000..ebfe13d --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/api/crafting/FluidIngredient.java @@ -0,0 +1,129 @@ +package de.cech12.bucketlib.api.crafting; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import de.cech12.bucketlib.BucketLibMod; +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.BucketItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.common.crafting.IngredientType; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidType; +import net.neoforged.neoforge.fluids.FluidUtil; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.items.ItemHandlerHelper; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +public class FluidIngredient extends Ingredient { + + protected final Fluid fluid; + protected final TagKey tag; + private ItemStack[] matchingStacks; + + private FluidIngredient(Fluid fluid, TagKey tag) { + super(Stream.of()); + this.fluid = fluid; + this.tag = tag; + } + + public FluidIngredient(Optional fluidOptional, Optional> tagOptional) { + this(fluidOptional.map(BuiltInRegistries.FLUID::get).orElse(null), tagOptional.orElse(null)); + } + + public FluidIngredient(Fluid fluid) { + this(fluid, null); + } + + public FluidIngredient(TagKey tag) { + this((Fluid)null, tag); + } + + private boolean isFluidCorrect(Fluid fluid) { + return fluid != null && ( + (this.fluid != null && fluid.isSame(this.fluid)) + || (this.tag != null && fluid.defaultFluidState().is(this.tag)) + ); + } + + @Override + public boolean test(ItemStack itemStack) { + if (itemStack == null || itemStack.isEmpty()) { + return false; + } + ItemStack container = ItemHandlerHelper.copyStackWithSize(itemStack, 1); + Optional drainedFluidOptional = FluidUtil.getFluidHandler(container) + .map(fluidHandler -> fluidHandler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.SIMULATE)); + if (drainedFluidOptional.isPresent() && !drainedFluidOptional.get().isEmpty()) { + FluidStack drainedFluid = drainedFluidOptional.get(); + return this.isFluidCorrect(drainedFluid.getFluid()) && drainedFluid.getAmount() == FluidType.BUCKET_VOLUME; + } + return false; + } + + @Override + @Nonnull + public ItemStack[] getItems() { + if (this.matchingStacks == null) { + ArrayList stacks = new ArrayList<>(); + BucketLibMod.getRegisteredBuckets().forEach(universalBucketItem -> { + ItemStack stack = new ItemStack(universalBucketItem); + List fluids = new ArrayList<>(); + Optional> fluidTag = Optional.empty(); + if (this.tag != null) { + fluidTag = BuiltInRegistries.FLUID.getTag(this.tag); + } + if (fluidTag.isPresent()) { + fluidTag.get().forEach(fluid -> fluids.add(fluid.value())); + } else if (this.fluid != null) { + fluids.add(this.fluid); + } + for (Fluid fluid : fluids) { + Item bucketItem = fluid.getBucket(); + if (!(bucketItem instanceof BucketItem) || ((BucketItem) bucketItem).getFluid() != fluid) { + continue; + } + stacks.add(new ItemStack(fluid.getBucket())); + FluidStack fluidStack = new FluidStack(fluid, FluidType.BUCKET_VOLUME); + FluidUtil.getFluidHandler(stack).ifPresent(fluidHandler -> { + int filledAmount = fluidHandler.fill(fluidStack, IFluidHandler.FluidAction.EXECUTE); + if (filledAmount == FluidType.BUCKET_VOLUME) { + stacks.add(fluidHandler.getContainer()); + } + }); + } + }); + this.matchingStacks = stacks.toArray(new ItemStack[0]); + } + return this.matchingStacks; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean isSimple() { + return false; + } + + public static final Codec CODEC = RecordCodecBuilder.create(builder -> + builder.group( + ResourceLocation.CODEC.optionalFieldOf("fluid").forGetter(i -> Optional.of(BuiltInRegistries.FLUID.getKey(i.fluid))), + TagKey.codec(BuiltInRegistries.FLUID.key()).optionalFieldOf("tag").forGetter(i -> Optional.ofNullable(i.tag)) + ).apply(builder, FluidIngredient::new) + ); + + public static final IngredientType TYPE = new IngredientType<>(CODEC); + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/api/crafting/MilkIngredient.java b/neoforge/src/main/java/de/cech12/bucketlib/api/crafting/MilkIngredient.java new file mode 100644 index 0000000..8081412 --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/api/crafting/MilkIngredient.java @@ -0,0 +1,67 @@ +package de.cech12.bucketlib.api.crafting; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.Decoder; +import com.mojang.serialization.Encoder; +import com.mojang.serialization.MapCodec; +import de.cech12.bucketlib.BucketLibMod; +import de.cech12.bucketlib.util.BucketLibUtil; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.neoforged.neoforge.common.crafting.IngredientType; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.stream.Stream; + +public class MilkIngredient extends Ingredient { + + private ItemStack[] matchingStacks; + + public MilkIngredient() { + super(Stream.of()); + } + + @Override + public boolean test(ItemStack itemStack) { + if (itemStack == null || itemStack.isEmpty()) { + return false; + } + if (itemStack.getItem() == Items.MILK_BUCKET) { + return true; + } + return BucketLibUtil.containsMilk(itemStack.copy()); + } + + @Override + @Nonnull + public ItemStack[] getItems() { + if (this.matchingStacks == null) { + ArrayList stacks = new ArrayList<>(); + stacks.add(new ItemStack(Items.MILK_BUCKET)); + BucketLibMod.getRegisteredBuckets().forEach(universalBucketItem -> { + if (universalBucketItem.canMilkEntities()) { + stacks.add(BucketLibUtil.addMilk(new ItemStack(universalBucketItem))); + } + }); + this.matchingStacks = stacks.toArray(new ItemStack[0]); + } + return this.matchingStacks; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean isSimple() { + return false; + } + + public static final Codec CODEC = MapCodec.of(Encoder.empty(), Decoder.unit(new MilkIngredient())).codec(); + + public static final IngredientType TYPE = new IngredientType<>(CODEC); + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/client/ClientEvents.java b/neoforge/src/main/java/de/cech12/bucketlib/client/ClientEvents.java new file mode 100644 index 0000000..2c2813e --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/client/ClientEvents.java @@ -0,0 +1,21 @@ +package de.cech12.bucketlib.client; + +import de.cech12.bucketlib.api.BucketLib; +import de.cech12.bucketlib.client.model.UniversalBucketModel; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.client.event.ModelEvent; + +@Mod.EventBusSubscriber(modid= BucketLib.MOD_ID, bus= Mod.EventBusSubscriber.Bus.MOD, value= Dist.CLIENT) +public class ClientEvents { + + private ClientEvents() {} + + @SubscribeEvent + public static void clientSetup(ModelEvent.RegisterGeometryLoaders event) { + event.register(new ResourceLocation(BucketLib.MOD_ID, "universal_bucket"), UniversalBucketModel.Loader.INSTANCE); + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/client/model/UniversalBucketModel.java b/neoforge/src/main/java/de/cech12/bucketlib/client/model/UniversalBucketModel.java new file mode 100644 index 0000000..951f9b6 --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/client/model/UniversalBucketModel.java @@ -0,0 +1,268 @@ +package de.cech12.bucketlib.client.model; + +import de.cech12.bucketlib.api.BucketLib; +import de.cech12.bucketlib.api.item.UniversalBucketItem; +import de.cech12.bucketlib.util.BucketLibUtil; +import com.google.common.collect.Maps; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonObject; +import com.mojang.math.Transformation; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.BlockModelRotation; +import net.minecraft.client.resources.model.Material; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.client.ClientHooks; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.client.model.CompositeModel; +import net.neoforged.neoforge.client.model.DynamicFluidContainerModel; +import net.neoforged.neoforge.client.model.IQuadTransformer; +import net.neoforged.neoforge.client.model.QuadTransformers; +import net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext; +import net.neoforged.neoforge.client.model.geometry.IGeometryLoader; +import net.neoforged.neoforge.client.model.SimpleModelState; +import net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry; +import net.neoforged.neoforge.client.model.geometry.StandaloneGeometryBakingContext; +import net.neoforged.neoforge.client.model.geometry.UnbakedGeometryHelper; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Map; +import java.util.function.Function; + +/** + * This implementation is based on net.neoforged.neoforge.client.model.DynamicFluidContainerModel. + * Multiple changes were done to simplify the class + */ +public class UniversalBucketModel implements IUnbakedGeometry { + + private static final Map TEXTURE_MAP = Maps.newHashMap(); + // Depth offsets to prevent Z-fighting + private static final Transformation DEPTH_OFFSET_TRANSFORM = new Transformation(new Vector3f(), new Quaternionf(), new Vector3f(1, 1, 1.002f), new Quaternionf()); + // Transformer to set quads to max brightness + private static final IQuadTransformer MAX_LIGHTMAP_TRANSFORMER = QuadTransformers.applyingLightmap(0x00F000F0); + + private static final Material MISSING_LOWER_CONTENT_MATERIAL = new Material(InventoryMenu.BLOCK_ATLAS, getContentTexture(new ResourceLocation(BucketLib.MOD_ID, "missing_lower_content"))); + + @Nonnull + private final Fluid fluid; + @Nullable + private final ResourceLocation otherContent; + + private final boolean isCracked; + private final boolean isLower; + + public UniversalBucketModel(@Nonnull Fluid fluid, @Nullable ResourceLocation otherContent, boolean isCracked, boolean isLower) { + this.fluid = fluid; + this.otherContent = otherContent; + this.isCracked = isCracked; + this.isLower = isLower; + } + + /** + * Returns a new UniversalBucketModel with the given fluid. + */ + public UniversalBucketModel withFluid(Fluid newFluid, boolean isCracked) { + return new UniversalBucketModel(newFluid, null, isCracked, false); + } + + /** + * Returns a new UniversalBucketModel with the given other content. + */ + public UniversalBucketModel withOtherContent(ResourceLocation otherContent, boolean isCracked, boolean isLower) { + return new UniversalBucketModel(Fluids.EMPTY, otherContent, isCracked, isLower); + } + + public static ResourceLocation getContentTexture(ResourceLocation otherContentLocation) { + ResourceLocation texture = TEXTURE_MAP.get(otherContentLocation); + if (texture == null) { + String textureLocation = String.format("item/bucket_content/%s", otherContentLocation.getPath()); + texture = new ResourceLocation(otherContentLocation.getNamespace(), textureLocation); + TEXTURE_MAP.put(otherContentLocation, texture); + } + return texture; + } + + @Override + public BakedModel bake(IGeometryBakingContext owner, ModelBaker baker, Function spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation) { + Material particleLocation = owner.hasMaterial("particle") ? owner.getMaterial("particle") : null; + + Material baseLocation = null; + if (this.isLower) { + if (this.isCracked && owner.hasMaterial("crackedLowerBase")) { + baseLocation = owner.getMaterial("crackedLowerBase"); + } + if (baseLocation == null && owner.hasMaterial("lowerBase")) { + baseLocation = owner.getMaterial("lowerBase"); + } + } else { + if (this.isCracked && owner.hasMaterial("crackedBase")) { + baseLocation = owner.getMaterial("crackedBase"); + } + if (baseLocation == null && owner.hasMaterial("base")) { + baseLocation = owner.getMaterial("base"); + } + } + + Material otherContentLocation = null; + Material fluidMaskLocation = null; + if (this.otherContent != null) { + otherContentLocation = new Material(InventoryMenu.BLOCK_ATLAS, getContentTexture(this.otherContent)); + } else if (this.fluid != Fluids.EMPTY) { + if (this.isCracked && owner.hasMaterial("crackedFluidMask")) { + fluidMaskLocation = owner.getMaterial("crackedFluidMask"); + } + if (fluidMaskLocation == null && owner.hasMaterial("fluidMask")) { + fluidMaskLocation = owner.getMaterial("fluidMask"); + } + } + + TextureAtlasSprite baseSprite = baseLocation != null ? spriteGetter.apply(baseLocation) : null; + TextureAtlasSprite otherContentSprite = null; + if (otherContentLocation != null) { + otherContentSprite = spriteGetter.apply(otherContentLocation); + //if content texture is missing - fallback to pink content texture + if (MissingTextureAtlasSprite.getLocation().equals(otherContentSprite.contents().name())) { + otherContentSprite = spriteGetter.apply(MISSING_LOWER_CONTENT_MATERIAL); + } + } + TextureAtlasSprite fluidSprite = fluid != Fluids.EMPTY ? spriteGetter.apply(ClientHooks.getBlockMaterial(IClientFluidTypeExtensions.of(fluid).getStillTexture())) : null; + TextureAtlasSprite particleSprite = particleLocation != null ? spriteGetter.apply(particleLocation) : null; + if (particleSprite == null) particleSprite = baseSprite; + if (particleSprite == null) particleSprite = otherContentSprite; + if (particleSprite == null) particleSprite = fluidSprite; + + // if the fluid is lighter than air, will manipulate the initial state to be rotated 180deg to turn it upside down + if (fluid != Fluids.EMPTY && fluid.getFluidType().isLighterThanAir()) { + modelState = new SimpleModelState( + modelState.getRotation().compose( + new Transformation(null, new Quaternionf(0, 0, 1, 0), null, null))); + } + + // We need to disable GUI 3D and block lighting for this to render properly + var itemContext = StandaloneGeometryBakingContext.builder(owner).withGui3d(false).withUseBlockLight(false).build(modelLocation); + var modelBuilder = CompositeModel.Baked.builder(itemContext, particleSprite, new ContainedFluidOverrideHandler(overrides, baker, itemContext, this), owner.getTransforms()); + + var normalRenderTypes = DynamicFluidContainerModel.getLayerRenderTypes(false); + + if (baseSprite != null) { + // build base (insidest) + var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(0, baseSprite.contents()); + var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> baseSprite, modelState, modelLocation); + modelBuilder.addQuads(normalRenderTypes, quads); + } + + if (otherContentSprite != null) { + //layer 2 to avoid coloring the entity layer + var transformedState = new SimpleModelState(modelState.getRotation().compose(DEPTH_OFFSET_TRANSFORM), modelState.isUvLocked()); + var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(2, otherContentSprite.contents()); + TextureAtlasSprite finalOtherContentSprite = otherContentSprite; + var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> finalOtherContentSprite, transformedState, modelLocation); + modelBuilder.addQuads(normalRenderTypes, quads); + } else if (fluidMaskLocation != null && fluidSprite != null) { + TextureAtlasSprite templateSprite = spriteGetter.apply(fluidMaskLocation); + if (templateSprite != null) { + // build liquid layer (inside) + var transformedState = new SimpleModelState(modelState.getRotation().compose(DEPTH_OFFSET_TRANSFORM), modelState.isUvLocked()); + var unbaked = UnbakedGeometryHelper.createUnbakedItemMaskElements(1, templateSprite.contents()); // Use template as mask + var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> fluidSprite, transformedState, modelLocation); // Bake with fluid texture + + var unlit = fluid.getFluidType().getLightLevel() > 0; + var renderTypes = DynamicFluidContainerModel.getLayerRenderTypes(unlit); + if (unlit) MAX_LIGHTMAP_TRANSFORMER.processInPlace(quads); + + modelBuilder.addQuads(renderTypes, quads); + } + } + + modelBuilder.setParticle(particleSprite); + + return modelBuilder.build(); + } + + public static final class Loader implements IGeometryLoader + { + public static final Loader INSTANCE = new Loader(); + + @Override + @Nonnull + public UniversalBucketModel read(JsonObject jsonObject, JsonDeserializationContext deserializationContext) + { + // create new model + return new UniversalBucketModel(Fluids.EMPTY, null, false, false); + } + } + + private static final class ContainedFluidOverrideHandler extends ItemOverrides + { + private static final ResourceLocation REBAKE_LOCATION = new ResourceLocation(BucketLib.MOD_ID, "bucket_override"); + + private final Map cache = Maps.newHashMap(); // contains all the baked models since they'll never change + private final ItemOverrides nested; + private final ModelBaker baker; + private final IGeometryBakingContext owner; + private final UniversalBucketModel parent; + + private boolean isCracked; + + private ContainedFluidOverrideHandler(ItemOverrides nested, ModelBaker baker, IGeometryBakingContext owner, UniversalBucketModel parent) + { + this.nested = nested; + this.baker = baker; + this.owner = owner; + this.parent = parent; + } + + @Nullable + @Override + public BakedModel resolve(@Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientLevel world, @Nullable LivingEntity entity, int number) + { + BakedModel overridden = nested.resolve(originalModel, stack, world, entity, number); + if (overridden != originalModel) return overridden; + if (stack.getItem() instanceof UniversalBucketItem bucket) { + ResourceLocation content = null; + EntityType entityType = BucketLibUtil.getEntityType(stack); + if (entityType != null) { + content = BuiltInRegistries.ENTITY_TYPE.getKey(entityType); + } + if (content == null) { + content = BucketLibUtil.getContent(stack); + } + Fluid fluid = null; + if (content == null) { + fluid = BucketLibUtil.getFluid(stack); + content = BuiltInRegistries.FLUID.getKey(fluid); + } + //reset cache if temperature config changed + boolean isCracked = bucket.isCracked(stack); + if (this.isCracked != isCracked) { + this.isCracked = isCracked; + cache.clear(); + } + if (!cache.containsKey(content)) { + UniversalBucketModel unbaked = (entityType != null || fluid == null) ? this.parent.withOtherContent(content, isCracked, entityType != null) : this.parent.withFluid(fluid, isCracked); + BakedModel bakedModel = unbaked.bake(owner, baker, Material::sprite, BlockModelRotation.X0_Y0, this, REBAKE_LOCATION); + cache.put(content, bakedModel); + return bakedModel; + } + return cache.get(content); + } + return originalModel; + } + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/item/UniversalBucketFluidHandler.java b/neoforge/src/main/java/de/cech12/bucketlib/item/UniversalBucketFluidHandler.java new file mode 100644 index 0000000..4328934 --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/item/UniversalBucketFluidHandler.java @@ -0,0 +1,101 @@ +package de.cech12.bucketlib.item; + +import de.cech12.bucketlib.api.item.UniversalBucketItem; +import de.cech12.bucketlib.util.BucketLibUtil; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.common.NeoForgeMod; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidType; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.fluids.capability.templates.FluidHandlerItemStack; + +import javax.annotation.Nonnull; + +public class UniversalBucketFluidHandler extends FluidHandlerItemStack { + + public UniversalBucketFluidHandler(@Nonnull ItemStack container) { + super(container, FluidType.BUCKET_VOLUME); + } + + @Nonnull + @Override + public FluidStack getFluid() { + FluidStack fluidStack = super.getFluid(); + //fill milk bucket with milk fluid if it is enabled + if (fluidStack.isEmpty() && NeoForgeMod.MILK.isBound()) { + ResourceLocation bucketContent = BucketLibUtil.getContent(this.container); + if (bucketContent != null && bucketContent.equals(BucketLibUtil.MILK_LOCATION)) { + fluidStack = new FluidStack(NeoForgeMod.MILK.get(), FluidType.BUCKET_VOLUME); + setFluid(fluidStack); + } + } + return fluidStack; + } + + @Override + public int fill(FluidStack resource, IFluidHandler.FluidAction doFill) { + //only fill the bucket, if there is no milk inside it. + if (BucketLibUtil.containsMilk(getContainer())) { + return 0; + } + //only fill the bucket, if there is enough fluid to fill the bucket completely + if (resource.getAmount() < capacity) { + return 0; + } + return super.fill(resource, doFill); + } + + @Nonnull + @Override + public FluidStack drain(int maxDrain, FluidAction action) { + //only drain the bucket, if there is no entity in the bucket + if (BucketLibUtil.containsEntityType(getContainer())) { + return FluidStack.EMPTY; + } + //only drain milk if the fluid is active + if (!NeoForgeMod.MILK.isBound() && BucketLibUtil.containsMilk(getContainer())) { + return FluidStack.EMPTY; + } + //only drain the bucket, if there is enough space to drain the bucket completely + if (maxDrain < capacity) { + return FluidStack.EMPTY; + } + if (action == FluidAction.EXECUTE + && BucketLibUtil.isAffectedByInfinityEnchantment(this.container)) { + //simulate drain to simulate infinity effect + return super.drain(maxDrain, FluidAction.SIMULATE); + } + return super.drain(maxDrain, action); + } + + @Override + protected void setContainerToEmpty() { + boolean wasCracked = false; + Item item = container.getItem(); + if (item instanceof UniversalBucketItem bucketItem) { + wasCracked = bucketItem.isCracked(container); + } + super.setContainerToEmpty(); + if (wasCracked) { + container.shrink(1); + } else { + if (BucketLibUtil.containsContent(container)) { //remove milk content tag + BucketLibUtil.removeContentNoCopy(container, false); + } + BucketLibUtil.damageByOne(container); + } + } + + @Override + public boolean canFillFluidType(FluidStack fluid) { + Item item = container.getItem(); + if (item instanceof UniversalBucketItem bucketItem) { + return fluid.getFluid() != Fluids.EMPTY && bucketItem.canHoldFluid(fluid.getFluid()); + } + return super.canFillFluidType(fluid); + } + +} \ No newline at end of file diff --git a/neoforge/src/main/java/de/cech12/bucketlib/mixin/NeoforgeItemMixin.java b/neoforge/src/main/java/de/cech12/bucketlib/mixin/NeoforgeItemMixin.java new file mode 100644 index 0000000..3cffb28 --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/mixin/NeoforgeItemMixin.java @@ -0,0 +1,76 @@ +package de.cech12.bucketlib.mixin; + +import de.cech12.bucketlib.api.BucketLibTags; +import de.cech12.bucketlib.api.item.UniversalBucketItem; +import de.cech12.bucketlib.item.UniversalBucketFluidHandler; +import de.cech12.bucketlib.platform.Services; +import de.cech12.bucketlib.util.BucketLibUtil; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.common.CommonHooks; +import net.neoforged.neoforge.common.capabilities.ICapabilityProvider; +import net.neoforged.neoforge.items.wrapper.ShulkerItemStackInvWrapper; +import net.neoforged.neoforge.common.extensions.IItemExtension; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(value = IItemExtension.class, remap = false) +public interface NeoforgeItemMixin { + + /** + * @author Cech12 + * @reason BucketLib class re-usability + */ + @Overwrite + default int getBurnTime(ItemStack itemStack, @Nullable RecipeType recipeType) { + if (this instanceof UniversalBucketItem) { + //entity buckets should not use the burn time of its fluid + if (!BucketLibUtil.containsEntityType(itemStack)) { + Fluid fluid = Services.FLUID.getContainedFluid(itemStack); + if (fluid != Fluids.EMPTY) { + //all fluids have their burn time in their bucket item. + //get the burn time via ForgeHooks.getBurnTime to let other mods change burn times of buckets of vanilla and other fluids. + return CommonHooks.getBurnTime(new ItemStack(fluid.getBucket()), recipeType); + } + } + } + return -1; + } + + /** + * @author Cech12 + * @reason BucketLib class re-usability + */ + @Overwrite + default boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + if (this instanceof UniversalBucketItem) { + if (enchantment == Enchantments.INFINITY_ARROWS + && Services.CONFIG.isInfinityEnchantmentEnabled() + && EnchantmentHelper.getTagEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) <= 0 + && Services.FLUID.getContainedFluid(stack).defaultFluidState().is(BucketLibTags.Fluids.INFINITY_ENCHANTABLE)) { + return true; + } + } + return enchantment.category.canEnchant(stack.getItem()); + } + + /** + * @author Cech12 + * @reason BucketLib class re-usability + */ + @Overwrite + default @Nullable ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) { + if (this instanceof UniversalBucketItem) { + return new UniversalBucketFluidHandler(stack); + } + return ShulkerItemStackInvWrapper.createDefaultProvider(stack); + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeBucketHelper.java b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeBucketHelper.java new file mode 100644 index 0000000..832ec11 --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeBucketHelper.java @@ -0,0 +1,34 @@ +package de.cech12.bucketlib.platform; + +import de.cech12.bucketlib.CommonLoader; +import de.cech12.bucketlib.platform.services.IBucketHelper; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.BucketItem; +import net.minecraft.world.item.MobBucketItem; +import net.minecraft.world.level.material.Fluid; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * The bucket helper implementation for NeoForge. + */ +public class NeoforgeBucketHelper implements IBucketHelper { + + @Override + public Fluid getFluidOfBucketItem(BucketItem bucket) { + return bucket.getFluid(); + } + + @Override + public EntityType getEntityTypeOfMobBucketItem(MobBucketItem mobBucketItem) { + try { + Method entityTypeMethod = MobBucketItem.class.getDeclaredMethod("getFishType"); + entityTypeMethod.setAccessible(true); + return (EntityType) entityTypeMethod.invoke(mobBucketItem); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) { + CommonLoader.LOG.error("Could not get entity type of MobBucketItem.", ex); + } + return null; + } +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeConfigHelper.java b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeConfigHelper.java new file mode 100644 index 0000000..ea0f357 --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeConfigHelper.java @@ -0,0 +1,56 @@ +package de.cech12.bucketlib.platform; + +import com.electronwill.nightconfig.core.file.CommentedFileConfig; +import com.electronwill.nightconfig.core.io.WritingMode; +import de.cech12.bucketlib.api.BucketLib; +import de.cech12.bucketlib.platform.services.IConfigHelper; +import net.neoforged.fml.ModLoadingContext; +import net.neoforged.fml.config.ModConfig; +import net.neoforged.fml.loading.FMLConfig; +import net.neoforged.fml.loading.FMLPaths; +import net.neoforged.neoforge.common.ModConfigSpec; + +import java.nio.file.Path; + +/** + * The config service implementation for NeoForge. + */ +public class NeoforgeConfigHelper implements IConfigHelper { + + private static final ModConfigSpec SERVER_CONFIG; + + public static final ModConfigSpec.BooleanValue INFINITY_ENCHANTMENT_ENABLED; + + static { + final ModConfigSpec.Builder builder = new ModConfigSpec.Builder(); + + builder.push("Balance Options"); + + INFINITY_ENCHANTMENT_ENABLED = builder + .comment(INFINITY_ENCHANTMENT_ENABLED_DESCRIPTION) + .define("infinityEnchantmentEnabled", INFINITY_ENCHANTMENT_ENABLED_DEFAULT); + + builder.pop(); + + SERVER_CONFIG = builder.build(); + } + + @Override + public void init() { + ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_CONFIG); + Path path = FMLPaths.GAMEDIR.get().resolve(FMLConfig.defaultConfigPath()).resolve(BucketLib.MOD_ID + "-server.toml"); + final CommentedFileConfig configData = CommentedFileConfig.builder(path).sync().autosave().writingMode(WritingMode.REPLACE).build(); + configData.load(); + SERVER_CONFIG.setConfig(configData); + } + + @Override + public boolean isInfinityEnchantmentEnabled() { + try { + return INFINITY_ENCHANTMENT_ENABLED.get(); + } catch (IllegalStateException ex) { + return INFINITY_ENCHANTMENT_ENABLED_DEFAULT; + } + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeFluidHelper.java b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeFluidHelper.java new file mode 100644 index 0000000..24879ba --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeFluidHelper.java @@ -0,0 +1,97 @@ +package de.cech12.bucketlib.platform; + +import de.cech12.bucketlib.platform.services.IFluidHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.BlockSource; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Tuple; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.common.NeoForgeMod; +import net.neoforged.neoforge.fluids.*; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; + +import java.util.concurrent.atomic.AtomicReference; + +/** + * The fluid service implementation for NeoForge. + */ +public class NeoforgeFluidHelper implements IFluidHelper { + + private static final DispenseFluidContainer dispenseFluidBehavior = DispenseFluidContainer.getInstance(); + + @Override + public Component getFluidDescription(Fluid fluid) { + return fluid.getFluidType().getDescription(); + } + + @Override + public int getFluidTemperature(Fluid fluid) { + return fluid.getFluidType().getTemperature(); + } + + @Override + public boolean hasMilkFluid() { + return NeoForgeMod.MILK.isBound(); + } + + @Override + public Fluid getMilkFluid() { + return NeoForgeMod.MILK.get(); + } + + @Override + public ItemStack dispenseFluidContainer(BlockSource source, ItemStack stack) { + return dispenseFluidBehavior.execute(source, stack); + } + + @Override + public Fluid getContainedFluid(ItemStack stack) { + return FluidUtil.getFluidContained(stack).orElse(FluidStack.EMPTY).getFluid(); + } + + @Override + public ItemStack addFluid(ItemStack stack, Fluid fluid) { + AtomicReference resultItemStack = new AtomicReference<>(stack.copy()); + FluidUtil.getFluidHandler(resultItemStack.get()).ifPresent(fluidHandler -> { + fluidHandler.fill(new FluidStack(fluid, FluidType.BUCKET_VOLUME), IFluidHandler.FluidAction.EXECUTE); + resultItemStack.set(fluidHandler.getContainer()); + }); + return resultItemStack.get(); + } + + @Override + public ItemStack removeFluid(ItemStack stack) { + AtomicReference resultItemStack = new AtomicReference<>(stack.copy()); + FluidUtil.getFluidHandler(resultItemStack.get()).ifPresent(fluidHandler -> { + fluidHandler.drain(new FluidStack(fluidHandler.getFluidInTank(0).getFluid(), FluidType.BUCKET_VOLUME), IFluidHandler.FluidAction.EXECUTE); + //damaging is done by fluid handler + resultItemStack.set(fluidHandler.getContainer()); + }); + return resultItemStack.get(); + } + + @Override + public Tuple tryPickUpFluid(ItemStack stack, Player player, Level level, InteractionHand interactionHand, BlockPos pos, Direction direction) { + FluidActionResult fluidActionResult = FluidUtil.tryPickUpFluid(stack, player, level, pos, direction); + return new Tuple<>(fluidActionResult.isSuccess(), fluidActionResult.getResult()); + } + + @Override + public Tuple tryPlaceFluid(ItemStack stack, Player player, Level level, InteractionHand interactionHand, BlockPos pos) { + FluidStack fluidStack = FluidUtil.getFluidHandler(stack).map(fluidHandler -> fluidHandler.getFluidInTank(0)).orElse(FluidStack.EMPTY); + FluidActionResult fluidActionResult = FluidUtil.tryPlaceFluid(player, level, interactionHand, pos, stack, fluidStack); + return new Tuple<>(fluidActionResult.isSuccess(), fluidActionResult.getResult()); + } + + @Override + public void curePotionEffects(LivingEntity entity, ItemStack curativeItem) { + entity.curePotionEffects(curativeItem); + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgePlatformHelper.java b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgePlatformHelper.java new file mode 100644 index 0000000..35ce3ad --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgePlatformHelper.java @@ -0,0 +1,39 @@ +package de.cech12.bucketlib.platform; + +import de.cech12.bucketlib.platform.services.IPlatformHelper; +import net.minecraft.world.level.Level; +import net.neoforged.fml.LogicalSide; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.neoforge.common.util.LogicalSidedProvider; +import net.neoforged.neoforge.server.ServerLifecycleHooks; + +/** + * The platform service implementation for NeoForge. + */ +public class NeoforgePlatformHelper implements IPlatformHelper { + + @Override + public String getPlatformName() { + return "NeoForge"; + } + + @Override + public boolean isModLoaded(String modId) { + return ModList.get().isLoaded(modId); + } + + @Override + public boolean isDevelopmentEnvironment() { + return !FMLLoader.isProduction(); + } + + @Override + public Level getCurrentLevel() { + if (ServerLifecycleHooks.getCurrentServer() != null) { + return ServerLifecycleHooks.getCurrentServer().overworld(); + } + return LogicalSidedProvider.CLIENTWORLD.get(LogicalSide.CLIENT).orElse(null); + } + +} diff --git a/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeRegistryHelper.java b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeRegistryHelper.java new file mode 100644 index 0000000..2ef48d3 --- /dev/null +++ b/neoforge/src/main/java/de/cech12/bucketlib/platform/NeoforgeRegistryHelper.java @@ -0,0 +1,54 @@ +package de.cech12.bucketlib.platform; + +import de.cech12.bucketlib.BucketLibMod; +import de.cech12.bucketlib.api.item.UniversalBucketItem; +import de.cech12.bucketlib.platform.services.IRegistryHelper; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.material.Fluid; + +import java.util.List; +import java.util.Objects; + +/** + * The registry service implementation for NeoForge. + */ +public class NeoforgeRegistryHelper implements IRegistryHelper { + @Override + public List getRegisteredBuckets() { + return BucketLibMod.getRegisteredBuckets(); + } + + @Override + public EntityType getEntityType(ResourceLocation location) { + return BuiltInRegistries.ENTITY_TYPE.get(location); + } + + @Override + public ResourceLocation getEntityTypeLocation(EntityType entityType) { + return Objects.requireNonNull(BuiltInRegistries.ENTITY_TYPE.getKey(entityType)); + } + + @Override + public Block getBlock(ResourceLocation location) { + return null; + } + + @Override + public ResourceLocation getBlockLocation(Block block) { + return null; + } + + @Override + public Iterable getAllItems() { + return BuiltInRegistries.ITEM; + } + + @Override + public Iterable getAllFluids() { + return BuiltInRegistries.FLUID; + } +} diff --git a/neoforge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..c061172 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,28 @@ +modLoader="javafml" +loaderVersion="${neoforge_loader_version_range}" +issueTrackerURL="${mod_issue_tracker}" +license="${mod_license}" +[[mods]] +modId="${mod_id}" +version="${minecraft_version}-${version}" +displayName="${mod_name}" +displayURL="${mod_url}" +logoFile="logo.png" +authors="${mod_author}" +description='''${mod_description}''' +[[mixins]] +config = "${mod_id}.mixins.json" +[[mixins]] +config = "${mod_id}.neoforge.mixins.json" +[[dependencies.${mod_id}]] +modId="neoforge" +mandatory=true +versionRange="${neoforge_version_range}" +ordering="NONE" +side="BOTH" +[[dependencies.${mod_id}]] +modId="minecraft" +mandatory=true +versionRange="${minecraft_version_range}" +ordering="NONE" +side="BOTH" \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper new file mode 100644 index 0000000..cc06b60 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IBucketHelper @@ -0,0 +1 @@ +de.cech12.bucketlib.platform.NeoforgeBucketHelper \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IConfigHelper b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IConfigHelper new file mode 100644 index 0000000..771c852 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IConfigHelper @@ -0,0 +1 @@ +de.cech12.bucketlib.platform.NeoforgeConfigHelper \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IFluidHelper b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IFluidHelper new file mode 100644 index 0000000..8c7cb85 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IFluidHelper @@ -0,0 +1 @@ +de.cech12.bucketlib.platform.NeoforgeFluidHelper \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IPlatformHelper b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IPlatformHelper new file mode 100644 index 0000000..c9a9d91 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IPlatformHelper @@ -0,0 +1 @@ +de.cech12.bucketlib.platform.NeoforgePlatformHelper \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IRegistryHelper b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IRegistryHelper new file mode 100644 index 0000000..59711c9 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/de.cech12.bucketlib.platform.services.IRegistryHelper @@ -0,0 +1 @@ +de.cech12.bucketlib.platform.NeoforgeRegistryHelper \ No newline at end of file diff --git a/neoforge/src/main/resources/assets/bucketlib/models/item/universal_bucket.json b/neoforge/src/main/resources/assets/bucketlib/models/item/universal_bucket.json new file mode 100644 index 0000000..3a1e94e --- /dev/null +++ b/neoforge/src/main/resources/assets/bucketlib/models/item/universal_bucket.json @@ -0,0 +1,12 @@ +{ + "loader": "bucketlib:universal_bucket", + "parent": "neoforge:item/default", + "textures": { + "base": "bucketlib:item/universal_bucket_base", + "lowerBase": "bucketlib:item/universal_bucket_lower_base", + "fluidMask": "neoforge:item/mask/bucket_fluid", + "crackedBase": "bucketlib:item/universal_bucket_cracked_base", + "crackedLowerBase": "bucketlib:item/universal_bucket_cracked_lower_base", + "crackedFluidMask": "neoforge:item/mask/bucket_fluid" + } +} \ No newline at end of file diff --git a/neoforge/src/main/resources/bucketlib.neoforge.mixins.json b/neoforge/src/main/resources/bucketlib.neoforge.mixins.json new file mode 100644 index 0000000..a7063d9 --- /dev/null +++ b/neoforge/src/main/resources/bucketlib.neoforge.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "de.cech12.bucketlib.mixin", + "compatibilityLevel": "JAVA_17", + "refmap": "mixins.bucketlib.refmap.json", + "mixins": [ + "NeoforgeItemMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" +} \ No newline at end of file diff --git a/forge/src/main/resources/data/bucketlib/aquaculture/turtle_soup.json b/neoforge/src/main/resources/data/bucketlib/aquaculture/turtle_soup.json similarity index 91% rename from forge/src/main/resources/data/bucketlib/aquaculture/turtle_soup.json rename to neoforge/src/main/resources/data/bucketlib/aquaculture/turtle_soup.json index a05c884..679160d 100644 --- a/forge/src/main/resources/data/bucketlib/aquaculture/turtle_soup.json +++ b/neoforge/src/main/resources/data/bucketlib/aquaculture/turtle_soup.json @@ -1,7 +1,7 @@ { "conditions": [ { - "type": "forge:mod_loaded", + "type": "neoforge:mod_loaded", "modid": "aquaculture" } ], diff --git a/neoforge/src/test/java/de/cech12/bucketlib/BucketLibTestMod.java b/neoforge/src/test/java/de/cech12/bucketlib/BucketLibTestMod.java new file mode 100644 index 0000000..2904e39 --- /dev/null +++ b/neoforge/src/test/java/de/cech12/bucketlib/BucketLibTestMod.java @@ -0,0 +1,65 @@ +package de.cech12.bucketlib; + +import de.cech12.bucketlib.api.BucketLibApi; +import de.cech12.bucketlib.api.item.UniversalBucketItem; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.InterModEnqueueEvent; +import net.neoforged.neoforge.common.NeoForgeMod; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +import java.util.Collections; + +@Mod(BucketLibTestMod.MOD_ID) +@Mod.EventBusSubscriber(modid= BucketLibTestMod.MOD_ID, bus= Mod.EventBusSubscriber.Bus.MOD) +public class BucketLibTestMod { + + public static final String MOD_ID = "bucketlibtest"; + public static final boolean MILK_ENABLED = Boolean.parseBoolean(System.getProperty("bucketlibtest.milkEnabled", "false")); + + public static final TagKey WATER_TAG = TagKey.create(BuiltInRegistries.FLUID.key(), new ResourceLocation(MOD_ID, "water")); + + public static final DeferredRegister ITEMS = DeferredRegister.create(BuiltInRegistries.ITEM, BucketLibTestMod.MOD_ID); + + public static final DeferredHolder TEST_BUCKET = ITEMS.register("test_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties())); + public static final DeferredHolder TEMPERATURE_BUCKET = ITEMS.register("temperature_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().maxTemperature(1000))); + public static final DeferredHolder WATER_ALLOWING_BUCKET = ITEMS.register("water_allowing_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().allowedFluids(Collections.singletonList(Fluids.WATER)))); + public static final DeferredHolder WATER_ALLOWING_TAG_BUCKET = ITEMS.register("water_allowing_tag_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().allowedFluids(WATER_TAG))); + public static final DeferredHolder WATER_DENYING_BUCKET = ITEMS.register("water_denying_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().deniedFluids(Collections.singletonList(Fluids.WATER)))); + public static final DeferredHolder WATER_DENYING_TAG_BUCKET = ITEMS.register("water_denying_tag_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().deniedFluids(WATER_TAG))); + public static final DeferredHolder CRACKING_BUCKET = ITEMS.register("cracking_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().upperCrackingTemperature(1000))); + public static final DeferredHolder COLORED_BUCKET = ITEMS.register("colored_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().dyeable(255, 0 ,0))); + public static final DeferredHolder ANTI_MILK_BUCKET = ITEMS.register("anti_milk_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().disableMilking())); + public static final DeferredHolder NO_ENTITIES_BUCKET = ITEMS.register("no_entities_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().disableEntityObtaining())); + public static final DeferredHolder ANTI_SALMON_BUCKET = ITEMS.register("anti_salmon_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().deniedEntities(Collections.singletonList(EntityType.SALMON)))); + public static final DeferredHolder ONLY_PUFFER_BUCKET = ITEMS.register("only_puffer_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().allowedEntities(Collections.singletonList(EntityType.PUFFERFISH)))); + public static final DeferredHolder NO_BLOCKS_BUCKET = ITEMS.register("no_blocks_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().disableBlockObtaining())); + public static final DeferredHolder DURABILITY_BUCKET = ITEMS.register("durability_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().durability(5))); + public static final DeferredHolder BURNING_BUCKET = ITEMS.register("burning_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().durability(20).burningTemperature(1000).burningBlocks(Collections.singletonList(Blocks.POWDER_SNOW)))); + public static final DeferredHolder FREEZING_BUCKET = ITEMS.register("freezing_bucket", () -> new UniversalBucketItem(new UniversalBucketItem.Properties().durability(20).freezingTemperature(500).freezingBlocks(Collections.singletonList(Blocks.POWDER_SNOW)))); + + public BucketLibTestMod(IEventBus modEventBus) { + ITEMS.register(modEventBus); + if (MILK_ENABLED) { + NeoForgeMod.enableMilkFluid(); + } + } + + @SubscribeEvent + public static void sendImc(InterModEnqueueEvent evt) { + for (DeferredHolder item : ITEMS.getEntries()) { + BucketLibApi.registerBucket(item.getId()); + } + } + +} diff --git a/neoforge/src/test/resources/META-INF/mods.toml b/neoforge/src/test/resources/META-INF/mods.toml new file mode 100644 index 0000000..2097a72 --- /dev/null +++ b/neoforge/src/test/resources/META-INF/mods.toml @@ -0,0 +1,11 @@ +modLoader="javafml" +loaderVersion="[1,)" +license="The MIT License (MIT)" +[[mods]] + modId="bucketlib" +[[mods]] + modId="bucketlibtest" +[[mixins]] +config = "bucketlib.mixins.json" +[[mixins]] +config = "bucketlib.neoforge.mixins.json" diff --git a/neoforge/src/test/resources/assets/bucketlibtest/lang/en_us.json b/neoforge/src/test/resources/assets/bucketlibtest/lang/en_us.json new file mode 100644 index 0000000..f109d25 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/lang/en_us.json @@ -0,0 +1,64 @@ +{ + "item.bucketlibtest.test_bucket": "Test Bucket", + "item.bucketlibtest.test_bucket.entity": "Test Bucket of %s", + "item.bucketlibtest.test_bucket.filled": "Test %s Bucket", + + "item.bucketlibtest.temperature_bucket": "Temperature Bucket", + "item.bucketlibtest.temperature_bucket.entity": "Temperature Bucket of %s", + "item.bucketlibtest.temperature_bucket.filled": "Temperature %s Bucket", + + "item.bucketlibtest.water_allowing_bucket": "Water Allowing Bucket", + "item.bucketlibtest.water_allowing_bucket.entity": "Water Allowing Bucket of %s", + "item.bucketlibtest.water_allowing_bucket.filled": "Water Allowing %s Bucket", + + "item.bucketlibtest.water_allowing_tag_bucket": "Water Allowing (Tag) Bucket", + "item.bucketlibtest.water_allowing_tag_bucket.entity": "Water Allowing (Tag) Bucket of %s", + "item.bucketlibtest.water_allowing_tag_bucket.filled": "Water Allowing (Tag) %s Bucket", + + "item.bucketlibtest.water_denying_bucket": "Water Denying Bucket", + "item.bucketlibtest.water_denying_bucket.entity": "Water Denying Bucket of %s", + "item.bucketlibtest.water_denying_bucket.filled": "Water Denying %s Bucket", + + "item.bucketlibtest.water_denying_tag_bucket": "Water Denying (Tag) Bucket", + "item.bucketlibtest.water_denying_tag_bucket.entity": "Water Denying (Tag) Bucket of %s", + "item.bucketlibtest.water_denying_tag_bucket.filled": "Water Denying (Tag) %s Bucket", + + "item.bucketlibtest.cracking_bucket": "Cracking Bucket", + "item.bucketlibtest.cracking_bucket.entity": "Cracking Bucket of %s", + "item.bucketlibtest.cracking_bucket.filled": "Cracking %s Bucket", + + "item.bucketlibtest.colored_bucket": "Colored Bucket", + "item.bucketlibtest.colored_bucket.entity": "Colored Bucket of %s", + "item.bucketlibtest.colored_bucket.filled": "Colored %s Bucket", + + "item.bucketlibtest.anti_milk_bucket": "Anti Milk Bucket", + "item.bucketlibtest.anti_milk_bucket.entity": "Anti Milk Bucket of %s", + "item.bucketlibtest.anti_milk_bucket.filled": "Anti Milk %s Bucket", + + "item.bucketlibtest.no_entities_bucket": "No Entity Bucket", + "item.bucketlibtest.no_entities_bucket.filled": "No Entity %s Bucket", + + "item.bucketlibtest.anti_salmon_bucket": "Anti Salmon Bucket", + "item.bucketlibtest.anti_salmon_bucket.entity": "Anti Salmon Bucket of %s", + "item.bucketlibtest.anti_salmon_bucket.filled": "Anti Salmon %s Bucket", + + "item.bucketlibtest.only_puffer_bucket": "Only Pufferfish Bucket", + "item.bucketlibtest.only_puffer_bucket.entity": "Only Pufferfish Bucket of %s", + "item.bucketlibtest.only_puffer_bucket.filled": "Only Pufferfish %s Bucket", + + "item.bucketlibtest.no_blocks_bucket": "No Blocks Bucket", + "item.bucketlibtest.no_blocks_bucket.entity": "No Blocks Bucket of %s", + "item.bucketlibtest.no_blocks_bucket.filled": "No Blocks %s Bucket", + + "item.bucketlibtest.durability_bucket": "Durability Bucket", + "item.bucketlibtest.durability_bucket.entity": "Durability Bucket of %s", + "item.bucketlibtest.durability_bucket.filled": "Durability %s Bucket", + + "item.bucketlibtest.burning_bucket": "Burning Bucket", + "item.bucketlibtest.burning_bucket.entity": "Burning Bucket of %s", + "item.bucketlibtest.burning_bucket.filled": "Burning %s Bucket", + + "item.bucketlibtest.freezing_bucket": "Freezing Bucket", + "item.bucketlibtest.freezing_bucket.entity": "Freezing Bucket of %s", + "item.bucketlibtest.freezing_bucket.filled": "Freezing %s Bucket" +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_milk_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_milk_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_milk_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_salmon_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_salmon_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/anti_salmon_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/burning_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/burning_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/burning_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/colored_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/colored_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/colored_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/cracking_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/cracking_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/cracking_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/durability_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/durability_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/durability_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/freezing_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/freezing_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/freezing_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/no_blocks_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/no_blocks_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/no_blocks_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/no_entities_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/no_entities_bucket.json new file mode 100644 index 0000000..c3fd8a1 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/no_entities_bucket.json @@ -0,0 +1,6 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/only_puffer_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/only_puffer_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/only_puffer_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/temperature_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/temperature_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/temperature_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/test_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/test_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/test_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_tag_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_tag_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_allowing_tag_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_tag_bucket.json b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_tag_bucket.json new file mode 100644 index 0000000..0a54631 --- /dev/null +++ b/neoforge/src/test/resources/assets/bucketlibtest/models/item/water_denying_tag_bucket.json @@ -0,0 +1,7 @@ +{ + "parent": "bucketlib:item/universal_bucket", + "textures": { + "base": "bucketlibtest:item/test_bucket", + "lowerBase": "bucketlibtest:item/lower_test_bucket" + } +} \ No newline at end of file diff --git a/neoforge/src/test/resources/assets/bucketlibtest/textures/item/lower_test_bucket.png b/neoforge/src/test/resources/assets/bucketlibtest/textures/item/lower_test_bucket.png new file mode 100644 index 0000000000000000000000000000000000000000..359180d2110c824061760572cd9e99b2e41d6ccf GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}H0G|+72UEQ{O@-U0w_I2^vn?-4UQ+bg{uS~5u3s7I;J!GcfS&2Vq7F)?gK&V3eneV~9p@>A6O(1_hp$hda;ay#Ie_ zZh2(Lm*xj{AzP}xG9TOW^oET9=V_@T7NI9SB~6`|)^MBMnb*6Kp>_Ki?r-`>nCGzP s&FJSa;Qp|*v^n4y^BmTzl4hao%weouv4uj;KwB6*UHx3vIVCg!09Nl@Z2$lO literal 0 HcmV?d00001 diff --git a/neoforge/src/test/resources/assets/bucketlibtest/textures/item/test_bucket.png b/neoforge/src/test/resources/assets/bucketlibtest/textures/item/test_bucket.png new file mode 100644 index 0000000000000000000000000000000000000000..246f17a632ec2dc2eb18f41162e5c67844cae46c GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}T0G|+7AnjnPH>as^+w_(T>t?p)CCN*QKHI+{-rx1>d<}C1tEM{QfI{?CrS=Tx_fr8PVE{-7@!Kvpi3Nj zN2+=5s^2Q