From 97edac430d4efbb1e522ff36ac348811f8161e77 Mon Sep 17 00:00:00 2001 From: cech12 Date: Thu, 6 Jul 2023 00:01:04 +0200 Subject: [PATCH] Fix placing fluids into waterlogged blocks with FluidUtil::tryPlaceFluid. To behave more like vanilla MC-127110 (#9586) --- .../capability/wrappers/BlockWrapper.java | 8 +- .../debug/item/CustomFluidContainerTest.java | 135 ++++++++++++++++++ src/test/resources/META-INF/mods.toml | 3 +- .../models/item/custom_fluid_container.json | 6 + 4 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 src/test/java/net/minecraftforge/debug/item/CustomFluidContainerTest.java create mode 100644 src/test/resources/assets/custom_fluid_container_test/models/item/custom_fluid_container.json diff --git a/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java b/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java index 5af80dd486..f59ce76181 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java +++ b/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java @@ -15,8 +15,6 @@ import net.minecraftforge.fluids.FluidType; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.templates.VoidFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; - /** * Wrapper around any block, only accounts for fluid placement, otherwise the block acts a void. * If the block in question inherits from the Forge implementations, @@ -73,11 +71,11 @@ public class BlockWrapper extends VoidFluidHandler BlockState state = world.getBlockState(blockPos); if (liquidContainer.canPlaceLiquid(world, blockPos, state, resource.getFluid())) { - //If we are executing try to actually fill the container, if it failed return that we failed - if (action.simulate() || liquidContainer.placeLiquid(world, blockPos, state, resource.getFluid().getFluidType().getStateForPlacement(world, blockPos, resource))) + if (action.execute()) { - return FluidType.BUCKET_VOLUME; + liquidContainer.placeLiquid(world, blockPos, state, resource.getFluid().getFluidType().getStateForPlacement(world, blockPos, resource)); } + return FluidType.BUCKET_VOLUME; } } return 0; diff --git a/src/test/java/net/minecraftforge/debug/item/CustomFluidContainerTest.java b/src/test/java/net/minecraftforge/debug/item/CustomFluidContainerTest.java new file mode 100644 index 0000000000..f3e283f5d3 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/item/CustomFluidContainerTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.debug.item; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.CreativeModeTabs; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fluids.FluidActionResult; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidType; +import net.minecraftforge.fluids.FluidUtil; +import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStackSimple; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + +@Mod(CustomFluidContainerTest.MODID) +public class CustomFluidContainerTest +{ + public static final String MODID = "custom_fluid_container_test"; + public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); + + public static final boolean ENABLED = true; + + public static final RegistryObject CUSTOM_FLUID_CONTAINER = ITEMS.register("custom_fluid_container", () -> new CustomFluidContainer((new Item.Properties()).stacksTo(1))); + + public CustomFluidContainerTest() + { + if (ENABLED) + { + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); + ITEMS.register(modEventBus); + modEventBus.addListener(this::addCreative); + } + } + + private void addCreative(BuildCreativeModeTabContentsEvent event) + { + if (event.getTabKey() == CreativeModeTabs.INGREDIENTS) + event.accept(CUSTOM_FLUID_CONTAINER); + } + + /** + * A custom fluid container item with a capacity of a vanilla bucket which uses the FluidUtil functionalities to pickup and place fluids. + */ + private static class CustomFluidContainer extends Item + { + + public CustomFluidContainer(Properties properties) + { + super(properties); + } + + @Override + @Nonnull + public Component getName(@Nonnull ItemStack itemStack) { + AtomicReference name = new AtomicReference<>("Custom Fluid Container"); + FluidUtil.getFluidHandler(itemStack).ifPresent(fluidHandler -> + { + FluidStack fluidStack = fluidHandler.getFluidInTank(0); + if (fluidStack.isEmpty()) + { + name.set(name.get() + " (empty)"); + } + else + { + name.set(name.get() + " (" + fluidStack.getFluid().getFluidType().getDescription().getString() + ")"); + } + }); + return Component.literal(name.get()); + } + + @Override + public InteractionResultHolder use(Level level, Player player, InteractionHand hand) + { + var itemStack = player.getItemInHand(hand); + var result = new AtomicReference(); + FluidUtil.getFluidHandler(itemStack).ifPresent(fluidHandler -> + { + var fluidStack = fluidHandler.getFluidInTank(0); + if (fluidStack.isEmpty()) + { + var blockHitResult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.SOURCE_ONLY); + result.set(FluidUtil.tryPickUpFluid(itemStack, player, level, blockHitResult.getBlockPos(), blockHitResult.getDirection())); + } + else + { + var blockHitResult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.NONE); + //try to place fluid in hit block (waterlogging, fill tank, ...). When no success try the block on the hit side. + for (BlockPos pos : Arrays.asList(blockHitResult.getBlockPos(), blockHitResult.getBlockPos().relative(blockHitResult.getDirection()))) + { + result.set(FluidUtil.tryPlaceFluid(player, level, hand, pos, itemStack, fluidStack)); + if (result.get().isSuccess()) + { + break; + } + } + } + }); + if (result.get() != null && result.get().isSuccess()) + { + return InteractionResultHolder.sidedSuccess(result.get().getResult(), level.isClientSide()); + } + return super.use(level, player, hand); + } + + @Override + public ICapabilityProvider initCapabilities(@Nonnull ItemStack stack, @Nullable CompoundTag nbt) + { + return new FluidHandlerItemStackSimple(stack, FluidType.BUCKET_VOLUME); + } + + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index bc7a65099e..751ba90319 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -293,6 +293,7 @@ modId="render_level_stages_test" modId="trade_with_villager_event_test" [[mods]] modId="chunk_event_load_new_chunk_test" - +[[mods]] +modId="custom_fluid_container_test" # ADD ABOVE THIS LINE diff --git a/src/test/resources/assets/custom_fluid_container_test/models/item/custom_fluid_container.json b/src/test/resources/assets/custom_fluid_container_test/models/item/custom_fluid_container.json new file mode 100644 index 0000000000..7481fe4a13 --- /dev/null +++ b/src/test/resources/assets/custom_fluid_container_test/models/item/custom_fluid_container.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "item/bucket" + } +}