implement pins (#315)

Co-authored-by: Maya <10861407+serenibyss@users.noreply.github.com>
Co-authored-by: Martin Robertz <dream-master@gmx.net>
This commit is contained in:
authored and GitHub committed 2025-07-01 20:40:42 +02:00
1 parent 10fefc7996
commit c86370caf9
4 files changed
+253 -9

No files matched your search

@@ -17,6 +17,7 @@ import org.lwjgl.input.Mouse;
import com.glodblock.github.FluidCraft;
import com.glodblock.github.client.gui.FCGuiTextField;
import com.glodblock.github.client.gui.GuiFluidMonitor;
import com.glodblock.github.client.gui.GuiItemMonitor;
import com.glodblock.github.client.gui.container.base.FCContainerMonitor;
import com.glodblock.github.inventory.InventoryHandler;
@@ -26,12 +27,14 @@ import com.glodblock.github.util.Ae2ReflectClient;
import com.glodblock.github.util.ModAndClassUtil;
import appeng.api.config.CraftingStatus;
import appeng.api.config.PinsState;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.Settings;
import appeng.api.config.TerminalStyle;
import appeng.api.config.YesNo;
import appeng.api.implementations.tiles.IViewCellStorage;
import appeng.api.storage.ITerminalHost;
import appeng.api.storage.ITerminalPins;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IDisplayRepo;
@@ -43,6 +46,8 @@ import appeng.client.gui.widgets.GuiTabButton;
import appeng.client.gui.widgets.IDropToFillTextField;
import appeng.client.gui.widgets.ISortSource;
import appeng.client.me.InternalSlotME;
import appeng.client.me.ItemRepo;
import appeng.client.me.PinSlotME;
import appeng.client.me.SlotDisconnected;
import appeng.client.me.SlotME;
import appeng.container.AEBaseContainer;
@@ -60,7 +65,9 @@ import appeng.core.localization.ButtonToolTips;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.core.sync.packets.PacketPinsUpdate;
import appeng.core.sync.packets.PacketValueConfig;
import appeng.helpers.IPinsHandler;
import appeng.helpers.InventoryAction;
import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType;
@@ -72,7 +79,7 @@ import codechicken.nei.util.TextHistory;
// TODO why is this copy pasting all the UI code from AE2 instead of reusing it ???
public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
implements ISortSource, IConfigManagerHost, IDropToFillTextField {
implements ISortSource, IConfigManagerHost, IDropToFillTextField, IPinsHandler {
public static int craftingGridOffsetX;
public static int craftingGridOffsetY;
@@ -102,7 +109,10 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
protected GuiImgButton terminalStyleBox;
protected GuiImgButton searchStringSave;
protected GuiImgButton typeFilter;
protected GuiImgButton pinsStateButton;
protected boolean hasShiftKeyDown = false;
private PinsState pinsState;
public final boolean hasPinHost;
@SuppressWarnings("unchecked")
public FCGuiMonitor(final InventoryPlayer inventoryPlayer, final ITerminalHost te, final FCContainerMonitor<T> c) {
@@ -115,6 +125,8 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
this.configSrc = ((IConfigurableObject) this.inventorySlots).getConfigManager();
(this.monitorableContainer = (FCContainerMonitor<T>) this.inventorySlots).setGui(this);
this.viewCell = te instanceof IViewCellStorage;
pinsState = (PinsState) configSrc.getSetting(Settings.PINS_STATE);
hasPinHost = te instanceof ITerminalPins && !(this instanceof GuiFluidMonitor);
}
public int getOffsetY() {
@@ -131,7 +143,7 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
this.getScrollBar().setTop(18).setLeft(175).setHeight(this.rows * 18 - 2);
this.getScrollBar().setRange(
0,
(this.repo.size() + this.perRow - 1) / this.perRow - this.rows,
(this.repo.size() + pinsState.ordinal() * 9 + this.perRow - 1) / this.perRow - this.rows,
Math.max(1, this.rows / 6));
}
@@ -151,6 +163,15 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
AEConfig.instance.settings.putSetting(iBtn.getSetting(), next);
} else if (ModAndClassUtil.isSaveText && btn == this.searchStringSave) {
AEConfig.instance.preserveSearchBar = next == YesNo.YES;
} else if (btn == this.pinsStateButton) {
try {
if (next.ordinal() >= rows) return; // ignore to avoid hiding terminal inventory
final PacketPinsUpdate p = new PacketPinsUpdate((PinsState) next);
NetworkHandler.instance.sendToServer(p);
} catch (final IOException e) {
AELog.debug(e);
}
} else {
try {
NetworkHandler.instance
@@ -169,6 +190,19 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
super.actionPerformed(btn);
}
private void adjustPinsSize() {
final int pinMaxSize = rows - 1;
if (pinsState.ordinal() <= pinMaxSize) return;
try {
PinsState newState = PinsState.fromOrdinal(pinMaxSize);
final PacketPinsUpdate p = new PacketPinsUpdate(newState);
NetworkHandler.instance.sendToServer(p);
} catch (final IOException e) {
AELog.debug(e);
}
}
@Override
public void initGui() {
Keyboard.enableRepeatEvents(true);
@@ -199,10 +233,26 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
}
this.getMeSlots().clear();
for (int y = 0; y < this.rows; y++) {
// make sure we have space at least for one row of normal slots, because pins not adjusted by scroll bar
adjustPinsSize();
int pinsRows = pinsState.ordinal();
for (int y = 0; y < pinsRows; y++) {
for (int x = 0; x < this.perRow; x++) {
this.getMeSlots()
.add(new InternalSlotME(this.repo, x + y * this.perRow, this.offsetX + x * 18, 18 + y * 18));
.add(new PinSlotME(this.repo, x + y * this.perRow, this.offsetX + x * 18, y * 18 + 18));
}
}
for (int y = 0; y < this.rows - pinsRows; y++) {
for (int x = 0; x < this.perRow; x++) {
this.getMeSlots().add(
new InternalSlotME(
this.repo,
x + y * this.perRow,
this.offsetX + x * 18,
18 + y * 18 + pinsRows * 18));
}
}
@@ -224,6 +274,7 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
this.offsetY = this.guiTop + 8;
buttonList.clear();
if (this.customSortOrder) {
this.buttonList.add(
this.SortByBox = new GuiImgButton(
@@ -323,6 +374,15 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
}
}
if (hasPinHost) {
this.buttonList.add(
this.pinsStateButton = new GuiImgButton(
this.guiLeft + 177,
this.guiTop + 18 + (rows * 18) + 26,
Settings.PINS_STATE,
configSrc.getSetting(Settings.PINS_STATE)));
}
final Enum<?> setting = AEConfig.instance.settings.getSetting(Settings.SEARCH_MODE);
this.searchField.setFocused(SearchBoxMode.AUTOSEARCH == setting || SearchBoxMode.NEI_AUTOSEARCH == setting);
@@ -527,13 +587,22 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
return;
}
if (slot instanceof SlotME) {
if (slot instanceof SlotME sme) {
InventoryAction action = null;
IAEItemStack stack = null;
switch (mouseButton) {
case 0: // pickup / set-down.
action = ctrlDown == 1 ? InventoryAction.SPLIT_OR_PLACE_SINGLE : InventoryAction.PICKUP_OR_SET_DOWN;
stack = ((SlotME) slot).getAEStack();
if (sme.isPin() && player.inventory.getItemStack() != null) {
final PacketInventoryAction p = new PacketInventoryAction(
InventoryAction.SET_PIN,
sme.getPinIndex(),
0);
NetworkHandler.instance.sendToServer(p);
return;
}
stack = sme.getAEStack();
if (stack != null && action == InventoryAction.PICKUP_OR_SET_DOWN
&& stack.getStackSize() == 0
&& player.inventory.getItemStack() == null) {
@@ -541,6 +610,15 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
}
break;
case 1:
if (sme.isPin() && ctrlDown == 1) { // clear pin
final PacketInventoryAction p = new PacketInventoryAction(
InventoryAction.SET_PIN,
sme.getPinIndex(),
-1);
NetworkHandler.instance.sendToServer(p);
return;
}
action = ctrlDown == 1 ? InventoryAction.PICKUP_SINGLE : InventoryAction.SHIFT_CLICK;
stack = ((SlotME) slot).getAEStack();
break;
@@ -721,6 +799,13 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
this.typeFilter.set(this.configSrc.getSetting(Settings.TYPE_FILTER));
}
if (this.pinsStateButton != null) {
pinsState = (PinsState) this.configSrc.getSetting(Settings.PINS_STATE);
this.pinsStateButton.set(pinsState);
initGui();
}
this.repo.updateView();
}
@@ -786,4 +871,14 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
public boolean isOverTextField(int mousex, int mousey) {
return searchField.isMouseIn(mousex, mousey);
}
@Override
public void setAEPins(IAEItemStack[] pins) {
if (repo instanceof ItemRepo) repo.setAEPins(pins);
}
@Override
public void setPinsState(PinsState state) {
configSrc.putSetting(Settings.PINS_STATE, state);
}
}
@@ -1,6 +1,8 @@
package com.glodblock.github.client.gui.container.base;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
@@ -10,10 +12,15 @@ import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ICrafting;
import net.minecraft.item.ItemStack;
import com.glodblock.github.inventory.item.BaseWirelessInventory;
import com.glodblock.github.inventory.item.IWirelessTerminal;
import com.glodblock.github.network.SPacketMEUpdateBuffer;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import appeng.api.config.Actionable;
import appeng.api.config.CraftingAllow;
import appeng.api.config.PinsState;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.Settings;
@@ -22,10 +29,16 @@ import appeng.api.config.SortOrder;
import appeng.api.config.TypeFilter;
import appeng.api.config.ViewItems;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingCPU;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.security.PlayerSource;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.ITerminalHost;
import appeng.api.storage.ITerminalPins;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.util.IConfigManager;
import appeng.api.util.IConfigurableObject;
@@ -34,18 +47,22 @@ import appeng.container.slot.SlotRestrictedInput;
import appeng.core.AELog;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketValueConfig;
import appeng.helpers.IPinsHandler;
import appeng.helpers.WirelessTerminalGuiObject;
import appeng.items.contents.PinsHandler;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.Platform;
public abstract class FCContainerMonitor<T extends IAEStack<T>> extends FCBaseContainer
implements IConfigManagerHost, IConfigurableObject, IMEMonitorHandlerReceiver<T> {
implements IConfigManagerHost, IConfigurableObject, IMEMonitorHandlerReceiver<T>, IPinsHandler {
protected final SlotRestrictedInput[] cellView = new SlotRestrictedInput[5];
protected final IConfigManager clientCM;
protected final ITerminalHost host;
protected PinsHandler pinsHandler = null;
@GuiSync(99)
public boolean canAccessViewCells = false;
@@ -70,6 +87,14 @@ public abstract class FCContainerMonitor<T extends IAEStack<T>> extends FCBaseCo
this.clientCM.registerSetting(Settings.VIEW_MODE, ViewItems.ALL);
this.clientCM.registerSetting(Settings.SORT_DIRECTION, SortDir.ASCENDING);
this.clientCM.registerSetting(Settings.TYPE_FILTER, TypeFilter.ALL);
this.clientCM.registerSetting(Settings.PINS_STATE, PinsState.DISABLED); // use for GUI
if (Platform.isServer()) {
if (monitorable instanceof ITerminalPins t && !(monitorable instanceof BaseWirelessInventory bwi
&& bwi.getChannel() == StorageChannel.FLUIDS)) {
pinsHandler = t.getPinsHandler(ip.player);
}
}
}
public IMEMonitor<T> getMonitor() {
@@ -105,6 +130,16 @@ public abstract class FCContainerMonitor<T extends IAEStack<T>> extends FCBaseCo
}
}
}
if (pinsHandler != null) {
if (clientCM.getSetting(Settings.PINS_STATE) != pinsHandler.getPinsState()) {
this.clientCM.putSetting(Settings.PINS_STATE, pinsHandler.getPinsState());
updatePins(true);
} else {
updatePins(false);
}
}
processItemList();
this.updatePowerStatus();
final boolean oldAccessible = this.canAccessViewCells;
@@ -122,6 +157,84 @@ public abstract class FCContainerMonitor<T extends IAEStack<T>> extends FCBaseCo
}
}
private int lastUpdate = 0;
public void updatePins(boolean forceUpdate) {
if (pinsHandler == null || !(host instanceof ITerminalPins itp)) return;
boolean isActive = pinsHandler.getPinsState() != PinsState.DISABLED;
++lastUpdate;
if (!forceUpdate && lastUpdate <= 20) return;
lastUpdate = 0;
if (isActive) {
final ICraftingGrid cc = itp.getGrid().getCache(ICraftingGrid.class);
final ImmutableList<ICraftingCPU> cpuList = cc.getCpus().asList();
List<IAEItemStack> craftedItems = new ArrayList<>();
// fetch the first available crafting output
for (int i = 0; i < cpuList.size(); i++) {
ICraftingCPU cpu = cpuList.get(i);
if (cpu.getCraftingAllowMode() != CraftingAllow.ONLY_NONPLAYER && cpu.getFinalOutput() != null
&& cpu.getCurrentJobSource() instanceof PlayerSource src
&& src.player == pinsHandler.getPlayer()) {
if (craftedItems.contains(cpu.getFinalOutput())) {
continue; // skip if already added
}
if (cpu.isBusy()) craftedItems.add(0, cpu.getFinalOutput().copy());
else craftedItems.add(cpu.getFinalOutput().copy());
}
}
pinsHandler.addItemsToPins(craftedItems);
}
pinsHandler.update(forceUpdate);
onListUpdate(); // notify the repo that the pins have changed
}
@Override
public void setPin(ItemStack is, int idx) {
if (pinsHandler == null || !(host instanceof ITerminalPins itp)) return;
if (is == null) {
final ICraftingGrid cc = itp.getGrid().getCache(ICraftingGrid.class);
final ImmutableSet<ICraftingCPU> cpuSet = cc.getCpus();
for (ICraftingCPU cpu : cpuSet) {
if (cpu.getCraftingAllowMode() != CraftingAllow.ONLY_NONPLAYER && cpu.getFinalOutput() != null
&& cpu.getFinalOutput().isSameType(getPin(idx))) {
if (!cpu.isBusy()) {
cpu.resetFinalOutput();
} else {
return;
}
}
}
}
pinsHandler.setPin(idx, is);
updatePins(true);
}
@Override
public ItemStack getPin(int idx) {
if (pinsHandler == null) return null;
return pinsHandler.getPin(idx);
}
public void setPinsState(PinsState pinsState) {
if (pinsHandler == null) return;
clientCM.putSetting(Settings.PINS_STATE, pinsState);
pinsHandler.setPinsState(pinsState);
updatePins(true);
}
public PinsState getPinsState() {
return pinsHandler != null ? pinsHandler.getPinsState() : PinsState.DISABLED;
}
public PinsHandler getPinsHandler() {
return pinsHandler;
}
protected abstract void processItemList();
protected boolean isInvalid() {
@@ -3,6 +3,7 @@ package com.glodblock.github.common.parts.base;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -10,14 +11,19 @@ import net.minecraft.nbt.NBTTagCompound;
import com.glodblock.github.common.item.ItemFluidPacket;
import com.glodblock.github.inventory.item.IItemPatternTerminal;
import appeng.api.networking.IGrid;
import appeng.api.storage.ITerminalPins;
import appeng.api.storage.data.IAEItemStack;
import appeng.items.contents.PinsHandler;
import appeng.items.contents.PinsHolder;
import appeng.tile.inventory.AppEngInternalInventory;
public abstract class FCFluidEncodeTerminal extends FCPart implements IItemPatternTerminal {
public abstract class FCFluidEncodeTerminal extends FCPart implements IItemPatternTerminal, ITerminalPins {
protected AppEngInternalInventory crafting;
protected AppEngInternalInventory output;
protected final AppEngInternalInventory pattern = new AppEngInternalInventory(this, 2);
private final PinsHolder pinsInv = new PinsHolder(this);
protected boolean craftingMode = true;
protected boolean substitute = false;
@@ -56,6 +62,7 @@ public abstract class FCFluidEncodeTerminal extends FCPart implements IItemPatte
this.pattern.readFromNBT(data, "pattern");
this.output.readFromNBT(data, "outputList");
this.crafting.readFromNBT(data, "craftingGrid");
pinsInv.readFromNBT(data, "pins");
}
@Override
@@ -72,6 +79,7 @@ public abstract class FCFluidEncodeTerminal extends FCPart implements IItemPatte
this.pattern.writeToNBT(data, "pattern");
this.output.writeToNBT(data, "outputList");
this.crafting.writeToNBT(data, "craftingGrid");
pinsInv.writeToNBT(data, "pins");
}
@Override
@@ -217,4 +225,14 @@ public abstract class FCFluidEncodeTerminal extends FCPart implements IItemPatte
public void setAutoFillPattern(boolean canFill) {
this.autoFillPattern = canFill;
}
@Override
public PinsHandler getPinsHandler(EntityPlayer player) {
return pinsInv.getHandler(player);
}
@Override
public IGrid getGrid() {
return getGridNode().getGrid();
}
}
@@ -16,20 +16,25 @@ import com.glodblock.github.util.Util;
import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
import appeng.api.implementations.items.IAEItemPowerStorage;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.security.PlayerSource;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.ITerminalPins;
import appeng.api.storage.MEMonitorHandler;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.util.AECableType;
import appeng.items.contents.PinsHandler;
import appeng.items.contents.PinsHolder;
import appeng.items.tools.powered.ToolWirelessTerminal;
import appeng.me.storage.NullInventory;
import appeng.util.Platform;
public abstract class BaseWirelessInventory extends MEMonitorHandler implements IWirelessTerminal, IWirelessExtendCard {
public abstract class BaseWirelessInventory extends MEMonitorHandler
implements IWirelessTerminal, IWirelessExtendCard, ITerminalPins {
protected final ItemStack target;
protected final IAEItemPowerStorage ips;
@@ -42,6 +47,7 @@ public abstract class BaseWirelessInventory extends MEMonitorHandler implements
protected WirelessMagnet.Mode magnetMode = WirelessMagnet.Mode.Off;
protected EntityPlayer player;
protected boolean restock;
private final PinsHolder pinsInv;
@SuppressWarnings("unchecked")
public BaseWirelessInventory(final ItemStack is, final int slot, IGridNode gridNode, EntityPlayer player,
@@ -54,6 +60,7 @@ public abstract class BaseWirelessInventory extends MEMonitorHandler implements
this.inventorySlot = slot;
this.channel = channel;
this.source = new PlayerSource(player, this);
pinsInv = new PinsHolder(is);
this.readFromNBT();
}
@@ -68,6 +75,7 @@ public abstract class BaseWirelessInventory extends MEMonitorHandler implements
this.inventorySlot = slot;
this.channel = channel;
this.source = new PlayerSource(player, this);
pinsInv = new PinsHolder(is);
this.readFromNBT();
}
@@ -184,4 +192,14 @@ public abstract class BaseWirelessInventory extends MEMonitorHandler implements
data.setBoolean(restockItems, this.restock);
data.setInteger(modeKey, this.getMagnetCardMode().ordinal());
}
@Override
public PinsHandler getPinsHandler(EntityPlayer player) {
return pinsInv.getHandler(player);
}
@Override
public IGrid getGrid() {
return grid != null ? grid.getGrid() : null;
}
}