Make fluids scrollable in the pattern (#73)

This commit is contained in:
Kogepan229 authored and GitHub committed 2026-07-04 20:54:04 +02:00
1 parent 5cfd5ce1b2
commit 220e96c0e7
4 files changed
+83 -35

No files matched your search

@@ -12,6 +12,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
@@ -20,6 +23,7 @@ import net.minecraft.client.resources.I18n;
import net.minecraft.inventory.Slot; import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.fluids.FluidStack;
import org.lwjgl.input.Mouse; import org.lwjgl.input.Mouse;
@@ -31,10 +35,13 @@ import com.github.vfyjxf.nee.network.NEENetworkHandler;
import com.github.vfyjxf.nee.network.packet.PacketSlotStackChange; import com.github.vfyjxf.nee.network.packet.PacketSlotStackChange;
import com.github.vfyjxf.nee.network.packet.PacketStackCountChange; import com.github.vfyjxf.nee.network.packet.PacketStackCountChange;
import com.github.vfyjxf.nee.network.packet.PacketValueConfigServer; import com.github.vfyjxf.nee.network.packet.PacketValueConfigServer;
import com.github.vfyjxf.nee.processor.GregTech5RecipeProcessor;
import com.github.vfyjxf.nee.utils.ItemUtils; import com.github.vfyjxf.nee.utils.ItemUtils;
import com.github.vfyjxf.nee.utils.ModIDs;
import com.glodblock.github.client.gui.GuiLevelMaintainer; import com.glodblock.github.client.gui.GuiLevelMaintainer;
import appeng.api.events.GuiScrollEvent; import appeng.api.events.GuiScrollEvent;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
import appeng.client.gui.AEBaseGui; import appeng.client.gui.AEBaseGui;
@@ -46,6 +53,7 @@ import appeng.client.gui.slots.VirtualMESlot;
import appeng.container.AEBaseContainer; import appeng.container.AEBaseContainer;
import appeng.container.implementations.ContainerPatternTerm; import appeng.container.implementations.ContainerPatternTerm;
import appeng.container.slot.SlotFake; import appeng.container.slot.SlotFake;
import appeng.util.item.AEFluidStack;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import codechicken.lib.gui.GuiDraw; import codechicken.lib.gui.GuiDraw;
import codechicken.nei.NEIClientConfig; import codechicken.nei.NEIClientConfig;
@@ -59,6 +67,7 @@ import codechicken.nei.recipe.RecipeInfo;
import codechicken.nei.util.NEIMouseUtils; import codechicken.nei.util.NEIMouseUtils;
import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import gregtech.api.enums.ItemList;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -218,7 +227,7 @@ public class GuiEventHandler extends INEIGuiAdapter implements IContainerTooltip
} }
if (sendPacket) { if (sendPacket) {
Int2ObjectMap<IAEItemStack> map = new Int2ObjectOpenHashMap<IAEItemStack>(); Int2ObjectMap<IAEStack<?>> map = new Int2ObjectOpenHashMap<>();
map.put(currentSlot.slotNumber, AEItemStack.create(copyStack)); map.put(currentSlot.slotNumber, AEItemStack.create(copyStack));
NEENetworkHandler.getInstance().sendToServer(new PacketSlotStackChange(map)); NEENetworkHandler.getInstance().sendToServer(new PacketSlotStackChange(map));
if (!NEEConfig.keepGhostitems) { if (!NEEConfig.keepGhostitems) {
@@ -340,54 +349,75 @@ public class GuiEventHandler extends INEIGuiAdapter implements IContainerTooltip
if (currentStackIndex < 0) return; if (currentStackIndex < 0) return;
final ItemStack nextStack = items.get(Math.floorMod(currentStackIndex - dWheel, items.size())).copy(); final ItemStack nextStack = items.get(Math.floorMod(currentStackIndex - dWheel, items.size())).copy();
final Int2ObjectMap<IAEItemStack> craftingSlotss = new Int2ObjectOpenHashMap<>(); final FluidStack nextFluidStack = getFluidStackOrNull(nextStack);
final ItemStack baseStack = baseIngredients.item;
final FluidStack baseFluidStack = getFluidStackOrNull(baseStack);
final long baseStackSize = baseFluidStack == null ? baseStack.stackSize : baseFluidStack.amount;
final Int2ObjectMap<IAEStack<?>> craftingSlots = new Int2ObjectOpenHashMap<>();
if (NEEConfig.allowSynchronousSwitchIngredient) { if (NEEConfig.allowSynchronousSwitchIngredient) {
final ItemStack baseStack = baseIngredients.item;
for (VirtualMEPatternSlot slot : gui.getCraftingSlots()) { for (VirtualMEPatternSlot slot : gui.getCraftingSlots()) {
IAEStack<?> slotAEStack = slot.getAEStack(); IAEStack<?> slotAEStack = slot.getAEStack();
if (!(slotAEStack instanceof IAEItemStack ais)) continue; if (!(slotAEStack instanceof IAEItemStack) && !(slotAEStack instanceof IAEFluidStack)) continue;
final ItemStack slotStack = ais.getItemStackForNEI(); final ItemStack slotStack = slotAEStack.getItemStackForNEI();
if (slotStack == null) continue; if (slotStack == null) continue;
final FluidStack slotFluidStack = getFluidStackOrNull(slotStack);
final long slotStackSize = slotFluidStack == null ? slotStack.stackSize : slotFluidStack.amount;
final PositionedStack slotIngredients = NEEPatternTerminalHandler.ingredients final PositionedStack slotIngredients = NEEPatternTerminalHandler.ingredients
.get(INPUT_KEY + slot.getSlotIndex()); .get(INPUT_KEY + slot.getSlotIndex());
if (slotIngredients != null && slotIngredients.containsWithNBT(nextStack) if (slotIngredients != null && slotIngredients.containsWithNBT(nextStack)
&& NEIServerUtils.areStacksSameTypeCraftingWithNBT(slotStack, baseStack) && ItemUtils.areStacksSameType(slotStack, baseStack)
&& NEIServerUtils.areStacksSameTypeCraftingWithNBT(slotIngredients.item, baseStack)) { && ItemUtils.areStacksSameType(slotIngredients.item, baseStack)) {
// If the current slot's stack size is a multiple of the recipe's default, apply that multiplier // If the current slot's stack size is a multiple of the recipe's default, apply that multiplier
// to nextStack. // to nextStack.
long nextStackAmount; final long nextStackAmount;
if (slotStack.stackSize % baseStack.stackSize == 0) { if (baseStackSize > 0 && slotStackSize % baseStackSize == 0) {
nextStackAmount = (long) nextStack.stackSize * (slotStack.stackSize / baseStack.stackSize); long nextSize = nextFluidStack != null ? nextFluidStack.amount : nextStack.stackSize;
nextStackAmount = nextSize * (slotStackSize / baseStackSize);
} else { } else {
nextStackAmount = slotAEStack.getStackSize(); nextStackAmount = slotAEStack.getStackSize();
} }
craftingSlotss IAEStack<?> nextAEStack = slotAEStack instanceof IAEItemStack ? AEItemStack.create(nextStack)
.put(slot.getSlotIndex(), AEItemStack.create(nextStack).setStackSize(nextStackAmount)); : AEFluidStack.create(nextFluidStack);
if (nextAEStack == null) continue;
nextAEStack.setStackSize(nextStackAmount);
craftingSlots.put(slot.getSlotIndex(), nextAEStack);
slotIngredients.setPermutationToRender(nextStack); slotIngredients.setPermutationToRender(nextStack);
} }
} }
} else { } else {
FluidStack baseSlotFluidStack = getFluidStackOrNull(baseSlotStack);
final long baseSlotStackSize = baseSlotFluidStack == null ? baseSlotStack.stackSize
: baseSlotFluidStack.amount;
// If the current slot's stack size is a multiple of the recipe's default, apply that multiplier to // If the current slot's stack size is a multiple of the recipe's default, apply that multiplier to
// nextStack. // nextStack.
long nextStackAmount; long nextStackAmount;
if (baseSlotStack.stackSize % baseIngredients.item.stackSize == 0) { if (baseStackSize > 0 && baseSlotStackSize % baseStackSize == 0) {
nextStackAmount = (long) nextStack.stackSize long nextSize = nextFluidStack == null ? nextStack.stackSize : nextFluidStack.amount;
* (baseSlotStack.stackSize / baseIngredients.item.stackSize); nextStackAmount = nextSize * (baseSlotStackSize / baseStackSize);
} else { } else {
nextStackAmount = aes.getStackSize(); nextStackAmount = aes.getStackSize();
} }
craftingSlotss IAEStack<?> nextAEStack = nextFluidStack == null ? AEItemStack.create(nextStack)
.put(currentSlot.getSlotIndex(), AEItemStack.create(nextStack).setStackSize(nextStackAmount)); : AEFluidStack.create(nextFluidStack);
if (nextAEStack == null) return;
nextAEStack.setStackSize(nextStackAmount);
craftingSlots.put(currentSlot.getSlotIndex(), nextAEStack);
baseIngredients.setPermutationToRender(nextStack); baseIngredients.setPermutationToRender(nextStack);
} }
if (!craftingSlotss.isEmpty()) { if (!craftingSlots.isEmpty()) {
NEENetworkHandler.getInstance().sendToServer(new PacketSlotStackChange(craftingSlotss)); NEENetworkHandler.getInstance().sendToServer(new PacketSlotStackChange(craftingSlots));
} }
} }
} }
@@ -410,4 +440,13 @@ public class GuiEventHandler extends INEIGuiAdapter implements IContainerTooltip
return uniqueItems; return uniqueItems;
} }
@Nullable
private FluidStack getFluidStackOrNull(@Nonnull ItemStack displayStack) {
if (Loader.isModLoaded(ModIDs.GT) && displayStack.getItem() == ItemList.Display_Fluid.getItem()) {
return GregTech5RecipeProcessor.getFluidFromDisplayStack(displayStack);
}
return null;
}
} }
@@ -7,9 +7,8 @@ import javax.annotation.Nonnull;
import com.github.vfyjxf.nee.NotEnoughEnergistics; import com.github.vfyjxf.nee.NotEnoughEnergistics;
import appeng.api.storage.StorageName; import appeng.api.storage.StorageName;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack;
import appeng.container.implementations.ContainerPatternTerm; import appeng.container.implementations.ContainerPatternTerm;
import appeng.util.item.AEItemStack;
import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext; import cpw.mods.fml.common.network.simpleimpl.MessageContext;
@@ -22,20 +21,15 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
*/ */
public class PacketSlotStackChange implements IMessage { public class PacketSlotStackChange implements IMessage {
private IAEItemStack stack; private Int2ObjectMap<IAEStack<?>> slotStacks;
private Int2ObjectMap<IAEItemStack> slotStacks;
public PacketSlotStackChange() {} public PacketSlotStackChange() {}
public PacketSlotStackChange(@Nonnull Int2ObjectMap<IAEItemStack> slotStacks) { public PacketSlotStackChange(@Nonnull Int2ObjectMap<IAEStack<?>> slotStacks) {
this.slotStacks = slotStacks; this.slotStacks = slotStacks;
} }
public IAEItemStack getStack() { public Int2ObjectMap<IAEStack<?>> getSlotStacks() {
return stack;
}
public Int2ObjectMap<IAEItemStack> getSlotStacks() {
return slotStacks; return slotStacks;
} }
@@ -46,7 +40,7 @@ public class PacketSlotStackChange implements IMessage {
for (int i = 0; i < mapSize; i++) { for (int i = 0; i < mapSize; i++) {
int slotNumber = buf.readInt(); int slotNumber = buf.readInt();
try { try {
IAEItemStack stack = AEItemStack.loadItemStackFromPacket(buf); IAEStack<?> stack = IAEStack.fromPacketGeneric(buf);
this.slotStacks.put(slotNumber, stack); this.slotStacks.put(slotNumber, stack);
} catch (IOException e) { } catch (IOException e) {
NotEnoughEnergistics.logger.error(e); NotEnoughEnergistics.logger.error(e);
@@ -57,10 +51,10 @@ public class PacketSlotStackChange implements IMessage {
@Override @Override
public void toBytes(ByteBuf buf) { public void toBytes(ByteBuf buf) {
buf.writeInt(this.slotStacks.size()); buf.writeInt(this.slotStacks.size());
for (Int2ObjectMap.Entry<IAEItemStack> entry : this.slotStacks.int2ObjectEntrySet()) { for (Int2ObjectMap.Entry<IAEStack<?>> entry : this.slotStacks.int2ObjectEntrySet()) {
buf.writeInt(entry.getIntKey()); buf.writeInt(entry.getIntKey());
try { try {
entry.getValue().writeToPacket(buf); IAEStack.writeToPacketGeneric(buf, entry.getValue());
} catch (IOException e) { } catch (IOException e) {
NotEnoughEnergistics.logger.error(e); NotEnoughEnergistics.logger.error(e);
} }
@@ -72,7 +66,7 @@ public class PacketSlotStackChange implements IMessage {
@Override @Override
public IMessage onMessage(PacketSlotStackChange message, MessageContext ctx) { public IMessage onMessage(PacketSlotStackChange message, MessageContext ctx) {
if (ctx.getServerHandler().playerEntity.openContainer instanceof ContainerPatternTerm cpt) { if (ctx.getServerHandler().playerEntity.openContainer instanceof ContainerPatternTerm cpt) {
for (Int2ObjectMap.Entry<IAEItemStack> entry : message.getSlotStacks().int2ObjectEntrySet()) { for (Int2ObjectMap.Entry<IAEStack<?>> entry : message.getSlotStacks().int2ObjectEntrySet()) {
cpt.updateVirtualSlot(StorageName.CRAFTING_INPUT, entry.getIntKey(), entry.getValue()); cpt.updateVirtualSlot(StorageName.CRAFTING_INPUT, entry.getIntKey(), entry.getValue());
} }
} }
@@ -25,6 +25,8 @@ import cpw.mods.fml.common.registry.GameRegistry;
public final class ItemUtils { public final class ItemUtils {
private static final String GT_DISPLAY_FLUID_ITEM_ID = "gt.GregTech_FluidDisplay";
public static Gson gson = new Gson(); public static Gson gson = new Gson();
public static List<StackProcessor> transformItemBlacklist = getTransformItemBlacklist(); public static List<StackProcessor> transformItemBlacklist = getTransformItemBlacklist();
public static List<StackProcessor> transformItemPriorityList = getTransformItemPriorityList(); public static List<StackProcessor> transformItemPriorityList = getTransformItemPriorityList();
@@ -183,10 +185,22 @@ public final class ItemUtils {
return null; return null;
} }
public static boolean areStacksSameType(ItemStack aStack, ItemStack bStack) {
if (Loader.isModLoaded(ModIDs.GT) && aStack != null && bStack != null) {
Item displayFluidItem = GameRegistry.findItem(ModIDs.GT, GT_DISPLAY_FLUID_ITEM_ID);
if (displayFluidItem != null && aStack.getItem() == displayFluidItem
&& bStack.getItem() == displayFluidItem) {
return displayFluidItem.getDamage(aStack) == displayFluidItem.getDamage(bStack);
}
}
return NEIServerUtils.areStacksSameTypeCraftingWithNBT(aStack, bStack);
}
public static int getPermutationIndex(ItemStack stack, List<ItemStack> items) { public static int getPermutationIndex(ItemStack stack, List<ItemStack> items) {
for (int index = 0; index < items.size(); index++) { for (int index = 0; index < items.size(); index++) {
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(items.get(index), stack)) { if (areStacksSameType(items.get(index), stack)) {
return index; return index;
} }
} }
@@ -252,7 +266,7 @@ public final class ItemUtils {
} }
public static void transformGTTool(ItemStack stack) { public static void transformGTTool(ItemStack stack) {
if (!Loader.isModLoaded("gregtech")) return; if (!Loader.isModLoaded(ModIDs.GT)) return;
if (GT_MetaGenerated_ToolClass != null if (GT_MetaGenerated_ToolClass != null
&& GT_MetaGenerated_ToolClass.isAssignableFrom(stack.getItem().getClass())) { && GT_MetaGenerated_ToolClass.isAssignableFrom(stack.getItem().getClass())) {
NBTTagCompound NBT = stack.getTagCompound(); NBTTagCompound NBT = stack.getTagCompound();
@@ -2,6 +2,7 @@ package com.github.vfyjxf.nee.utils;
public class ModIDs { public class ModIDs {
public static final String GT = "gregtech";
public static final String WCT = "ae2wct"; public static final String WCT = "ae2wct";
public static final String FC = "ae2fc"; public static final String FC = "ae2fc";
public static final String ThE = "thaumicenergistics"; public static final String ThE = "thaumicenergistics";