From 9ea39424ce62239263d3a9dc93f80b4983402195 Mon Sep 17 00:00:00 2001 From: Sara Freimer Date: Mon, 29 Apr 2024 12:46:17 -0500 Subject: [PATCH] Fix usage of FluidStack as keys in maps or sets not properly comparing --- .../render/tileentity/RenderFluidTank.java | 7 +++--- .../transmitter/RenderMechanicalPipe.java | 6 ++--- .../inventory/slot/IFluidHandlerSlot.java | 15 ++++++------- .../lib/collection/FluidHashStrategy.java | 22 +++++++++++++++++++ 4 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 src/main/java/mekanism/common/lib/collection/FluidHashStrategy.java diff --git a/src/main/java/mekanism/client/render/tileentity/RenderFluidTank.java b/src/main/java/mekanism/client/render/tileentity/RenderFluidTank.java index 4efdecbe846..771e0549213 100644 --- a/src/main/java/mekanism/client/render/tileentity/RenderFluidTank.java +++ b/src/main/java/mekanism/client/render/tileentity/RenderFluidTank.java @@ -4,7 +4,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.util.HashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import java.util.Map; import mekanism.api.annotations.NothingNullByDefault; import mekanism.client.render.MekanismRenderer; @@ -13,6 +13,7 @@ import mekanism.client.render.ModelRenderer; import mekanism.client.render.RenderResizableCuboid.FaceDisplay; import mekanism.common.base.ProfilerConstants; +import mekanism.common.lib.collection.FluidHashStrategy; import mekanism.common.tile.TileEntityFluidTank; import mekanism.common.util.MekanismUtils; import net.minecraft.client.renderer.MultiBufferSource; @@ -26,8 +27,8 @@ @NothingNullByDefault public class RenderFluidTank extends MekanismTileEntityRenderer { - private static final Map> cachedCenterFluids = new HashMap<>(); - private static final Map> cachedValveFluids = new HashMap<>(); + private static final Map> cachedCenterFluids = new Object2ObjectOpenCustomHashMap<>(FluidHashStrategy.INSTANCE); + private static final Map> cachedValveFluids = new Object2ObjectOpenCustomHashMap<>(FluidHashStrategy.INSTANCE); private static final int stages = 1_400; diff --git a/src/main/java/mekanism/client/render/transmitter/RenderMechanicalPipe.java b/src/main/java/mekanism/client/render/transmitter/RenderMechanicalPipe.java index e3bbf172199..fb8c7b218c7 100644 --- a/src/main/java/mekanism/client/render/transmitter/RenderMechanicalPipe.java +++ b/src/main/java/mekanism/client/render/transmitter/RenderMechanicalPipe.java @@ -5,8 +5,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -20,6 +20,7 @@ import mekanism.common.base.ProfilerConstants; import mekanism.common.content.network.FluidNetwork; import mekanism.common.content.network.transmitter.MechanicalPipe; +import mekanism.common.lib.collection.FluidHashStrategy; import mekanism.common.lib.transmitter.ConnectionType; import mekanism.common.tile.transmitter.TileEntityMechanicalPipe; import mekanism.common.util.EnumUtils; @@ -43,7 +44,6 @@ public class RenderMechanicalPipe extends RenderTransmitterBase>> cachedLiquids = new Int2ObjectArrayMap<>(8); public RenderMechanicalPipe(BlockEntityRendererProvider.Context context) { @@ -142,7 +142,7 @@ private Model3D getModel(@Nullable Direction side, FluidStack fluid, int stage, } else { sideOrdinal = side.ordinal(); } - Int2ObjectMap modelMap = cachedLiquids.computeIfAbsent(sideOrdinal, s -> new HashMap<>()) + Int2ObjectMap modelMap = cachedLiquids.computeIfAbsent(sideOrdinal, s -> new Object2ObjectOpenCustomHashMap<>(FluidHashStrategy.INSTANCE)) .computeIfAbsent(fluid, f -> new Int2ObjectOpenHashMap<>()); Model3D model = modelMap.get(stage); if (model == null) { diff --git a/src/main/java/mekanism/common/inventory/slot/IFluidHandlerSlot.java b/src/main/java/mekanism/common/inventory/slot/IFluidHandlerSlot.java index d481750dd86..4885ef81af0 100644 --- a/src/main/java/mekanism/common/inventory/slot/IFluidHandlerSlot.java +++ b/src/main/java/mekanism/common/inventory/slot/IFluidHandlerSlot.java @@ -1,13 +1,14 @@ package mekanism.common.inventory.slot; -import java.util.HashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; +import java.util.Collection; import java.util.Map; -import java.util.Set; import mekanism.api.Action; import mekanism.api.AutomationType; import mekanism.api.fluid.IExtendedFluidTank; import mekanism.api.inventory.IInventorySlot; import mekanism.common.capabilities.Capabilities; +import mekanism.common.lib.collection.FluidHashStrategy; import mekanism.common.tile.interfaces.IFluidContainerManager.ContainerEditMode; import mekanism.common.util.MekanismUtils; import net.minecraft.world.item.ItemStack; @@ -15,7 +16,6 @@ import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.fluids.capability.IFluidHandler.FluidAction; import net.neoforged.neoforge.fluids.capability.IFluidHandlerItem; -import net.neoforged.neoforge.items.ItemHandlerHelper; public interface IFluidHandlerSlot extends IInventorySlot { @@ -88,9 +88,8 @@ default void fillTank(IInventorySlot outputSlot) { //If we have more than one tank in our item then handle calculating the different drains that will occur for filling our fluid handler // We start by gathering all the fluids in the item that we are able to drain and are valid for the tank, // combining same fluid types into a single fluid stack - Set knownFluids = gatherKnownFluids(itemFluidHandler, itemTanks); //If we found any fluids that we can drain, attempt to drain them into our item - for (FluidStack knownFluid : knownFluids) { + for (FluidStack knownFluid : gatherKnownFluids(itemFluidHandler, itemTanks)) { if (drainItemAndMove(outputSlot, knownFluid) && isEmpty()) { //If we moved the item after draining it and we now don't have an item to try and fill // then just exit instead of checking the other types of fluids @@ -261,7 +260,7 @@ default boolean fillTank() { //If we have more than one tank in our item then handle calculating the different drains that will occur for filling our fluid handler // We start by gathering all the fluids in the item that we are able to drain and are valid for the tank, // combining same fluid types into a single fluid stack - Set knownFluids = gatherKnownFluids(itemFluidHandler, tanks); + Collection knownFluids = gatherKnownFluids(itemFluidHandler, tanks); if (!knownFluids.isEmpty()) { //If we found any fluids that we can drain, attempt to drain them into our item boolean changed = false; @@ -282,8 +281,8 @@ default boolean fillTank() { return false; } - private Set gatherKnownFluids(IFluidHandlerItem itemFluidHandler, int tanks) { - Map knownFluids = new HashMap<>(); + private Collection gatherKnownFluids(IFluidHandlerItem itemFluidHandler, int tanks) { + Map knownFluids = new Object2ObjectOpenCustomHashMap<>(FluidHashStrategy.INSTANCE); for (int tank = 0; tank < tanks; tank++) { FluidStack fluidInItem = itemFluidHandler.getFluidInTank(tank); if (!fluidInItem.isEmpty()) { diff --git a/src/main/java/mekanism/common/lib/collection/FluidHashStrategy.java b/src/main/java/mekanism/common/lib/collection/FluidHashStrategy.java new file mode 100644 index 00000000000..41f1cb5cca2 --- /dev/null +++ b/src/main/java/mekanism/common/lib/collection/FluidHashStrategy.java @@ -0,0 +1,22 @@ +package mekanism.common.lib.collection; + +import it.unimi.dsi.fastutil.Hash.Strategy; +import net.neoforged.neoforge.fluids.FluidStack; + +public class FluidHashStrategy implements Strategy { + + public static final FluidHashStrategy INSTANCE = new FluidHashStrategy(); + + private FluidHashStrategy() { + } + + @Override + public int hashCode(FluidStack stack) { + return FluidStack.hashFluidAndComponents(stack); + } + + @Override + public boolean equals(FluidStack a, FluidStack b) { + return FluidStack.isSameFluidSameComponents(a, b); + } +} \ No newline at end of file