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