diff --git a/gradle.properties b/gradle.properties index 3c5d9b7..1d6a1a5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,7 +23,7 @@ org.gradle.jvmargs=-Xmx1G # Dependencies appeng_version=15.0.18 architectury_version=9.2.14 - gtceu_version=7.5.1 + gtceu_version=7.5.2 ldlib_version=1.0.40.b registrate_version=MC1.20-1.3.11 rhino_version=2001.2.3-build.6 diff --git a/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferPartMachine.java b/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferPartMachine.java index 97a8995..bbf7d36 100644 --- a/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferPartMachine.java +++ b/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferPartMachine.java @@ -1,206 +1,74 @@ package net.neganote.gtutilities.integration.ae2.machine; -import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.fancy.ConfiguratorPanel; import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity; -import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.api.machine.MultiblockMachineDefinition; -import com.gregtechceu.gtceu.api.machine.TickableSubscription; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.ButtonConfigurator; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.CircuitFancyConfigurator; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.FancyInvConfigurator; -import com.gregtechceu.gtceu.api.machine.fancyconfigurator.FancyTankConfigurator; -import com.gregtechceu.gtceu.api.machine.feature.IDataStickInteractable; -import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMultiController; -import com.gregtechceu.gtceu.api.machine.trait.NotifiableFluidTank; -import com.gregtechceu.gtceu.api.machine.trait.NotifiableItemStackHandler; -import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList; -import com.gregtechceu.gtceu.api.recipe.ingredient.FluidIngredient; -import com.gregtechceu.gtceu.api.recipe.ingredient.SizedIngredient; -import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler; -import com.gregtechceu.gtceu.common.data.machines.GTAEMachines; -import com.gregtechceu.gtceu.common.item.IntCircuitBehaviour; import com.gregtechceu.gtceu.integration.ae2.gui.widget.AETextInputButtonWidget; import com.gregtechceu.gtceu.integration.ae2.gui.widget.slot.AEPatternViewSlotWidget; -import com.gregtechceu.gtceu.integration.ae2.machine.MEBusPartMachine; -import com.gregtechceu.gtceu.utils.GTMath; -import com.gregtechceu.gtceu.utils.ItemStackHashStrategy; +import com.gregtechceu.gtceu.integration.ae2.machine.MEPatternBufferPartMachine; +import com.gregtechceu.gtceu.integration.ae2.machine.trait.InternalSlotRecipeHandler; -import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; -import com.lowdragmc.lowdraglib.gui.util.ClickData; import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; import com.lowdragmc.lowdraglib.gui.widget.Widget; import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.syncdata.IContentChangeAware; -import com.lowdragmc.lowdraglib.syncdata.ITagSerializable; -import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced; -import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; -import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; -import net.minecraft.server.TickTask; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidType; -import net.neganote.gtutilities.integration.ae2.machine.trait.ExpandedInternalSlotRecipeHandler; -import appeng.api.crafting.IPatternDetails; -import appeng.api.crafting.PatternDetailsHelper; -import appeng.api.implementations.blockentities.PatternContainerGroup; -import appeng.api.inventories.InternalInventory; -import appeng.api.networking.IGrid; -import appeng.api.networking.IGridNodeListener; -import appeng.api.networking.crafting.ICraftingProvider; -import appeng.api.stacks.*; -import appeng.api.storage.MEStorage; -import appeng.api.storage.StorageHelper; import appeng.crafting.pattern.EncodedPatternItem; -import appeng.crafting.pattern.ProcessingPatternItem; -import appeng.helpers.patternprovider.PatternContainer; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import it.unimi.dsi.fastutil.objects.*; -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.UnmodifiableView; -import java.util.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import javax.annotation.ParametersAreNonnullByDefault; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -public class ExpandedPatternBufferPartMachine extends MEBusPartMachine - implements ICraftingProvider, PatternContainer, IDataStickInteractable { +public class ExpandedPatternBufferPartMachine extends MEPatternBufferPartMachine { - protected static final ManagedFieldHolder MANAGED_FIELD_HOLDER = new ManagedFieldHolder( - ExpandedPatternBufferPartMachine.class, MEBusPartMachine.MANAGED_FIELD_HOLDER); + protected static final int EXPANDED_MAX_PATTERN_COUNT = 72; - protected static final int MAX_PATTERN_COUNT = 72; + public ExpandedPatternBufferPartMachine(IMachineBlockEntity info) { + super(info); + this.getPatternInventory().setSize(EXPANDED_MAX_PATTERN_COUNT); - private final InternalInventory internalPatternInventory = new InternalInventory() { + try { + Field internalInvField = MEPatternBufferPartMachine.class.getDeclaredField("internalInventory"); + internalInvField.setAccessible(true); - @Override - public int size() { - return MAX_PATTERN_COUNT; - } - - @Override - public ItemStack getStackInSlot(int slotIndex) { - return patternInventory.getStackInSlot(slotIndex); - } - - @Override - public void setItemDirect(int slotIndex, ItemStack stack) { - patternInventory.setStackInSlot(slotIndex, stack); - patternInventory.onContentsChanged(slotIndex); - onPatternChange(slotIndex); - } - }; - - @Getter - @Persisted - @DescSynced - private final CustomItemStackHandler patternInventory = new CustomItemStackHandler(MAX_PATTERN_COUNT); - - @Getter - @Persisted - protected final NotifiableItemStackHandler shareInventory; - - @Getter - @Persisted - protected final NotifiableFluidTank shareTank; - - @Getter - @Persisted - protected final InternalSlot[] internalInventory = new InternalSlot[MAX_PATTERN_COUNT]; - - private final BiMap detailsSlotMap = HashBiMap.create(MAX_PATTERN_COUNT); - - @DescSynced - @Persisted - @Setter - private String customName = ""; - - private boolean needPatternSync; - - @Persisted - private final Set proxies = new ObjectOpenHashSet<>(); - - private final Set proxyMachines = new ReferenceOpenHashSet<>(); - - @Getter - protected final ExpandedInternalSlotRecipeHandler internalRecipeHandler; + InternalSlot[] newInternalInv = new InternalSlot[EXPANDED_MAX_PATTERN_COUNT]; + for (int i = 0; i < EXPANDED_MAX_PATTERN_COUNT; i++) { + newInternalInv[i] = new InternalSlot(); + } + internalInvField.set(this, newInternalInv); - @Nullable - protected TickableSubscription updateSubs; + Field recipeHandlerField = MEPatternBufferPartMachine.class.getDeclaredField("internalRecipeHandler"); + recipeHandlerField.setAccessible(true); + recipeHandlerField.set(this, new InternalSlotRecipeHandler(this, newInternalInv)); - public ExpandedPatternBufferPartMachine(IMachineBlockEntity holder, Object... args) { - super(holder, IO.IN, args); - this.patternInventory.setFilter(stack -> stack.getItem() instanceof ProcessingPatternItem); - for (int i = 0; i < this.internalInventory.length; i++) { - this.internalInventory[i] = new InternalSlot(); + } catch (Exception e) { + throw new RuntimeException("FATAL: Failed to initialize Expanded Pattern Buffer via reflection.", e); } - getMainNode().addService(ICraftingProvider.class, this); - this.shareInventory = new NotifiableItemStackHandler(this, 9, IO.IN, IO.NONE); - this.shareTank = new NotifiableFluidTank(this, 9, 8 * FluidType.BUCKET_VOLUME, IO.IN, IO.NONE); - this.internalRecipeHandler = new ExpandedInternalSlotRecipeHandler(this, internalInventory); } - @Override - public void onLoad() { - super.onLoad(); - if (getLevel() instanceof ServerLevel serverLevel) { - serverLevel.getServer().tell(new TickTask(1, () -> { - for (int i = 0; i < patternInventory.getSlots(); i++) { - var pattern = patternInventory.getStackInSlot(i); - var patternDetails = PatternDetailsHelper.decodePattern(pattern, getLevel()); - if (patternDetails != null) { - this.detailsSlotMap.put(patternDetails, this.internalInventory[i]); - } - } - needPatternSync = true; - })); + private void callPrivatePatternChange(int index) { + try { + Method method = MEPatternBufferPartMachine.class.getDeclaredMethod("onPatternChange", int.class); + method.setAccessible(true); + method.invoke(this, index); + } catch (Exception e) { + throw new RuntimeException("Failed to invoke onPatternChange for index " + index, e); } } - @Override - public List getRecipeHandlers() { - return internalRecipeHandler.getSlotHandlers(); - } - - public void addProxy(ExpandedPatternBufferProxyPartMachine proxy) { - proxies.add(proxy.getPos()); - proxyMachines.add(proxy); - } - - public void removeProxy(ExpandedPatternBufferProxyPartMachine proxy) { - proxies.remove(proxy.getPos()); - proxyMachines.remove(proxy); - } - - @UnmodifiableView - public Set getProxies() { - if (proxyMachines.size() != proxies.size()) { - proxyMachines.clear(); - for (var pos : proxies) { - if (MetaMachine.getMachine(getLevel(), pos) instanceof ExpandedPatternBufferProxyPartMachine proxy) { - proxyMachines.add(proxy); - } - } + private String getCustomNameExpanded() { + try { + Field field = MEPatternBufferPartMachine.class.getDeclaredField("customName"); + field.setAccessible(true); + return (String) field.get(this); + } catch (Exception e) { + throw new RuntimeException("Failed to retrieve customName via reflection", e); } - return Collections.unmodifiableSet(proxyMachines); } @Override @@ -208,410 +76,34 @@ public Widget createUIWidget() { int rowSize = 9; int colSize = 8; var group = new WidgetGroup(0, 0, 18 * rowSize + 16, 18 * colSize + 16); - int index = 0; - for (int y = 0; y < colSize; ++y) { - for (int x = 0; x < rowSize; ++x) { - int finalI = index; - var slot = new AEPatternViewSlotWidget(patternInventory, index++, 8 + x * 18, 14 + y * 18) - .setOccupiedTexture(GuiTextures.SLOT) - .setItemHook(stack -> { - if (!stack.isEmpty() && stack.getItem() instanceof EncodedPatternItem iep) { - final ItemStack out = iep.getOutput(stack); - if (!out.isEmpty()) return out; - } - return stack; - }) - .setChangeListener(() -> onPatternChange(finalI)) - .setBackground(GuiTextures.SLOT, GuiTextures.PATTERN_OVERLAY); - group.addWidget(slot); - } + + for (int i = 0; i < EXPANDED_MAX_PATTERN_COUNT; i++) { + int index = i; + int x = i % rowSize; + int y = i / rowSize; + + var slot = new AEPatternViewSlotWidget(getPatternInventory(), index, 8 + x * 18, 14 + y * 18) + .setOccupiedTexture(GuiTextures.SLOT) + .setItemHook(stack -> { + if (!stack.isEmpty() && stack.getItem() instanceof EncodedPatternItem iep) { + final ItemStack out = iep.getOutput(stack); + if (!out.isEmpty()) return out; + } + return stack; + }) + .setChangeListener(() -> callPrivatePatternChange(index)) + .setBackground(GuiTextures.SLOT, GuiTextures.PATTERN_OVERLAY); + group.addWidget(slot); } + group.addWidget(new LabelWidget(8, 2, () -> this.isOnline ? "gtceu.gui.me_network.online" : "gtceu.gui.me_network.offline")); + group.addWidget(new AETextInputButtonWidget(18 * rowSize + 8 - 70, 2, 70, 10) - .setText(customName) + .setText(getCustomNameExpanded()) .setOnConfirm(this::setCustomName) .setButtonTooltips(Component.translatable("gui.gtceu.rename.desc"))); - return group; - } - - @Override - public boolean isWorkingEnabled() { - return true; - } - - @Override - public void setWorkingEnabled(boolean ignored) {} - - @Override - public boolean isDistinct() { - return true; - } - - @Override - public void setDistinct(boolean ignored) {} - - @Override - public void onMainNodeStateChanged(IGridNodeListener.State reason) { - super.onMainNodeStateChanged(reason); - this.updateSubscription(); - } - - protected void updateSubscription() { - if (getMainNode().isOnline()) { - updateSubs = subscribeServerTick(updateSubs, this::update); - } else if (updateSubs != null) { - updateSubs.unsubscribe(); - updateSubs = null; - } - } - - protected void update() { - if (needPatternSync) { - ICraftingProvider.requestUpdate(getMainNode()); - this.needPatternSync = false; - } - } - - private void refundAll(ClickData clickData) { - if (!clickData.isRemote) { - for (InternalSlot internalSlot : internalInventory) { - internalSlot.refund(); - } - } - } - - private void onPatternChange(int index) { - if (isRemote()) return; - var internalInv = internalInventory[index]; - var newPattern = patternInventory.getStackInSlot(index); - var newPatternDetails = PatternDetailsHelper.decodePattern(newPattern, getLevel()); - var oldPatternDetails = detailsSlotMap.inverse().get(internalInv); - detailsSlotMap.forcePut(newPatternDetails, internalInv); - if (oldPatternDetails != null && !oldPatternDetails.equals(newPatternDetails)) { - internalInv.refund(); - } - needPatternSync = true; - } - - @Override - public void attachConfigurators(ConfiguratorPanel configuratorPanel) { - configuratorPanel.attachConfigurators(new ButtonConfigurator( - new GuiTextureGroup(GuiTextures.BUTTON, GuiTextures.REFUND_OVERLAY), this::refundAll) - .setTooltips(List.of(Component.translatable("gui.gtceu.refund_all.desc")))); - if (isHasCircuitSlot() && isCircuitSlotEnabled()) { - configuratorPanel.attachConfigurators(new CircuitFancyConfigurator(circuitInventory.storage)); - } - configuratorPanel.attachConfigurators(new FancyInvConfigurator( - shareInventory.storage, Component.translatable("gui.gtceu.share_inventory.title")) - .setTooltips(List.of( - Component.translatable("gui.gtceu.share_inventory.desc.0"), - Component.translatable("gui.gtceu.share_inventory.desc.1")))); - configuratorPanel.attachConfigurators(new FancyTankConfigurator( - shareTank.getStorages(), Component.translatable("gui.gtceu.share_tank.title")) - .setTooltips(List.of( - Component.translatable("gui.gtceu.share_tank.desc.0"), - Component.translatable("gui.gtceu.share_inventory.desc.1")))); - } - - @Override - public List getAvailablePatterns() { - return detailsSlotMap.keySet().stream().filter(Objects::nonNull).toList(); - } - - @Override - public boolean pushPattern(IPatternDetails patternDetails, KeyCounter[] inputHolder) { - if (!isFormed() || !getMainNode().isActive() || !detailsSlotMap.containsKey(patternDetails) || - !checkInput(inputHolder)) { - return false; - } - var slot = detailsSlotMap.get(patternDetails); - if (slot != null) { - slot.pushPattern(patternDetails, inputHolder); - return true; - } - return false; - } - - @Override - public boolean isBusy() { - return false; - } - - private boolean checkInput(KeyCounter[] inputHolder) { - for (KeyCounter input : inputHolder) { - var illegal = input.keySet().stream() - .map(AEKey::getType) - .map(AEKeyType::getId) - .anyMatch(id -> !id.equals(AEKeyType.items().getId()) && !id.equals(AEKeyType.fluids().getId())); - if (illegal) return false; - } - return true; - } - - @Override - public ManagedFieldHolder getFieldHolder() { - return MANAGED_FIELD_HOLDER; - } - - @Override - public @Nullable IGrid getGrid() { - return getMainNode().getGrid(); - } - - @Override - public InternalInventory getTerminalPatternInventory() { - return internalPatternInventory; - } - - @Override - public PatternContainerGroup getTerminalGroup() { - if (isFormed()) { - IMultiController controller = getControllers().first(); - MultiblockMachineDefinition controllerDefinition = controller.self().getDefinition(); - if (!customName.isEmpty()) { - return new PatternContainerGroup(AEItemKey.of(controllerDefinition.asStack()), - Component.literal(customName), Collections.emptyList()); - } else { - ItemStack circuitStack = isHasCircuitSlot() ? circuitInventory.storage.getStackInSlot(0) : - ItemStack.EMPTY; - int circuitConfiguration = circuitStack.isEmpty() ? -1 : - IntCircuitBehaviour.getCircuitConfiguration(circuitStack); - Component groupName = circuitConfiguration != -1 ? - Component.translatable(controllerDefinition.getDescriptionId()) - .append(" - " + circuitConfiguration) : - Component.translatable(controllerDefinition.getDescriptionId()); - return new PatternContainerGroup(AEItemKey.of(controllerDefinition.asStack()), groupName, - Collections.emptyList()); - } - } else { - return new PatternContainerGroup(AEItemKey.of(GTAEMachines.ME_PATTERN_BUFFER.getItem()), - customName.isEmpty() ? - GTAEMachines.ME_PATTERN_BUFFER.get().getDefinition().getItem().getDescription() : - Component.literal(customName), - Collections.emptyList()); - } - } - - @Override - public void onMachineRemoved() { - clearInventory(patternInventory); - clearInventory(shareInventory); - } - - @Override - public InteractionResult onDataStickShiftUse(Player player, ItemStack dataStick) { - dataStick.getOrCreateTag().putIntArray("pos", new int[] { getPos().getX(), getPos().getY(), getPos().getZ() }); - return InteractionResult.SUCCESS; - } - - public record BufferData(Object2LongMap items, Object2LongMap fluids) {} - - public BufferData mergeInternalSlots() { - var items = new Object2LongOpenCustomHashMap<>(ItemStackHashStrategy.comparingAllButCount()); - var fluids = new Object2LongOpenHashMap(); - for (InternalSlot slot : internalInventory) { - slot.itemInventory.object2LongEntrySet().fastForEach(e -> items.addTo(e.getKey(), e.getLongValue())); - slot.fluidInventory.object2LongEntrySet().fastForEach(e -> fluids.addTo(e.getKey(), e.getLongValue())); - } - return new BufferData(items, fluids); - } - - public class InternalSlot implements ITagSerializable, IContentChangeAware { - - @Getter - @Setter - private Runnable onContentsChanged = () -> {}; - private final Object2LongOpenCustomHashMap itemInventory = new Object2LongOpenCustomHashMap<>( - ItemStackHashStrategy.comparingAllButCount()); - private final Object2LongOpenHashMap fluidInventory = new Object2LongOpenHashMap<>(); - private List itemStacks = null; - private List fluidStacks = null; - - public InternalSlot() {} - public boolean isItemEmpty() { - return itemInventory.isEmpty(); - } - - public boolean isFluidEmpty() { - return fluidInventory.isEmpty(); - } - - public void onContentsChanged() { - itemStacks = null; - fluidStacks = null; - onContentsChanged.run(); - } - - private void add(AEKey what, long amount) { - if (amount <= 0L) return; - if (what instanceof AEItemKey itemKey) { - itemInventory.addTo(itemKey.toStack(), amount); - } else if (what instanceof AEFluidKey fluidKey) { - fluidInventory.addTo(fluidKey.toStack(1), amount); - } - } - - public List getItems() { - if (itemStacks == null) { - itemStacks = new ArrayList<>(); - itemInventory.object2LongEntrySet().stream().map(e -> GTMath.splitStacks(e.getKey(), e.getLongValue())) - .forEach(itemStacks::addAll); - } - return itemStacks; - } - - public List getFluids() { - if (fluidStacks == null) { - fluidStacks = new ArrayList<>(); - fluidInventory.object2LongEntrySet().stream() - .map(e -> GTMath.splitFluidStacks(e.getKey(), e.getLongValue())).forEach(fluidStacks::addAll); - } - return fluidStacks; - } - - public void refund() { - var network = getMainNode().getGrid(); - if (network != null) { - MEStorage networkInv = network.getStorageService().getInventory(); - var energy = network.getEnergyService(); - for (var it = itemInventory.object2LongEntrySet().iterator(); it.hasNext();) { - var entry = it.next(); - var key = AEItemKey.of(entry.getKey()); - if (key == null) continue; - long inserted = StorageHelper.poweredInsert(energy, networkInv, key, entry.getLongValue(), - actionSource); - if (inserted > 0) { - long count = entry.getLongValue() - inserted; - if (count == 0) it.remove(); - else entry.setValue(count); - } - } - for (var it = fluidInventory.object2LongEntrySet().iterator(); it.hasNext();) { - var entry = it.next(); - var key = AEFluidKey.of(entry.getKey()); - if (key == null) continue; - long inserted = StorageHelper.poweredInsert(energy, networkInv, key, entry.getLongValue(), - actionSource); - if (inserted > 0) { - long amount = entry.getLongValue() - inserted; - if (amount == 0) it.remove(); - else entry.setValue(amount); - } - } - onContentsChanged(); - } - } - - public void pushPattern(IPatternDetails patternDetails, KeyCounter[] inputHolder) { - patternDetails.pushInputsToExternalInventory(inputHolder, this::add); - onContentsChanged(); - } - - public @Nullable List handleItemInternal(List left, boolean simulate) { - boolean changed = false; - for (var it = left.listIterator(); it.hasNext();) { - var ingredient = it.next(); - var items = ingredient.getItems(); - if (items.length == 0 || items[0].isEmpty()) { - it.remove(); - continue; - } - int amount = items[0].getCount(); - for (var it2 = itemInventory.object2LongEntrySet().iterator(); it2.hasNext();) { - var entry = it2.next(); - if (!ingredient.test(entry.getKey())) continue; - int extracted = Math.min(GTMath.saturatedCast(entry.getLongValue()), amount); - if (!simulate && extracted > 0) { - changed = true; - long count = entry.getLongValue() - extracted; - if (count == 0) it2.remove(); - else entry.setValue(count); - } - amount -= extracted; - if (amount <= 0) { - it.remove(); - break; - } - } - if (amount > 0) { - if (ingredient instanceof SizedIngredient si) si.setAmount(amount); - else items[0].setCount(amount); - } - } - if (changed) onContentsChanged(); - return left.isEmpty() ? null : left; - } - - public @Nullable List handleFluidInternal(List left, boolean simulate) { - boolean changed = false; - for (var it = left.listIterator(); it.hasNext();) { - var ingredient = it.next(); - var fluids = ingredient.getStacks(); - if (fluids.length == 0 || fluids[0].isEmpty()) { - it.remove(); - continue; - } - int amount = fluids[0].getAmount(); - for (var it2 = fluidInventory.object2LongEntrySet().iterator(); it2.hasNext();) { - var entry = it2.next(); - if (!ingredient.test(entry.getKey())) continue; - int extracted = Math.min(GTMath.saturatedCast(entry.getLongValue()), amount); - if (!simulate && extracted > 0) { - changed = true; - long count = entry.getLongValue() - extracted; - if (count == 0) it2.remove(); - else entry.setValue(count); - } - amount -= extracted; - if (amount <= 0) { - it.remove(); - break; - } - } - if (amount > 0) ingredient.setAmount(amount); - } - if (changed) onContentsChanged(); - return left.isEmpty() ? null : left; - } - - @Override - public CompoundTag serializeNBT() { - CompoundTag tag = new CompoundTag(); - ListTag itemsTag = new ListTag(); - for (var entry : itemInventory.object2LongEntrySet()) { - var ct = entry.getKey().serializeNBT(); - ct.putLong("real", entry.getLongValue()); - itemsTag.add(ct); - } - if (!itemsTag.isEmpty()) tag.put("inventory", itemsTag); - ListTag fluidsTag = new ListTag(); - for (var entry : fluidInventory.object2LongEntrySet()) { - var ct = entry.getKey().writeToNBT(new CompoundTag()); - ct.putLong("real", entry.getLongValue()); - fluidsTag.add(ct); - } - if (!fluidsTag.isEmpty()) tag.put("fluidInventory", fluidsTag); - return tag; - } - - @Override - public void deserializeNBT(CompoundTag tag) { - ListTag items = tag.getList("inventory", Tag.TAG_COMPOUND); - for (Tag t : items) { - if (!(t instanceof CompoundTag ct)) continue; - var stack = ItemStack.of(ct); - var count = ct.getLong("real"); - if (!stack.isEmpty() && count > 0) itemInventory.put(stack, count); - } - ListTag fluids = tag.getList("fluidInventory", Tag.TAG_COMPOUND); - for (Tag t : fluids) { - if (!(t instanceof CompoundTag ct)) continue; - var stack = FluidStack.loadFluidStackFromNBT(ct); - var amount = ct.getLong("real"); - if (!stack.isEmpty() && amount > 0) fluidInventory.put(stack, amount); - } - } + return group; } } diff --git a/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferProxyPartMachine.java b/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferProxyPartMachine.java index a536fe7..6ab146e 100644 --- a/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferProxyPartMachine.java +++ b/src/main/java/net/neganote/gtutilities/integration/ae2/machine/ExpandedPatternBufferProxyPartMachine.java @@ -1,133 +1,28 @@ package net.neganote.gtutilities.integration.ae2.machine; -import com.gregtechceu.gtceu.api.GTValues; -import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity; -import com.gregtechceu.gtceu.api.machine.MetaMachine; -import com.gregtechceu.gtceu.api.machine.feature.IDataStickInteractable; -import com.gregtechceu.gtceu.api.machine.feature.IMachineLife; -import com.gregtechceu.gtceu.api.machine.multiblock.part.TieredIOPartMachine; -import com.gregtechceu.gtceu.api.machine.trait.RecipeHandlerList; - -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced; -import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; -import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder; +import com.gregtechceu.gtceu.integration.ae2.machine.MEPatternBufferProxyPartMachine; +import com.gregtechceu.gtceu.integration.ae2.machine.trait.ProxySlotRecipeHandler; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.Tag; -import net.minecraft.server.TickTask; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.BlockHitResult; -import net.neganote.gtutilities.integration.ae2.machine.trait.ExpandedProxySlotRecipeHandler; - -import lombok.Getter; -import org.jetbrains.annotations.Nullable; -import java.util.List; +import java.lang.reflect.Field; import javax.annotation.ParametersAreNonnullByDefault; -@MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class ExpandedPatternBufferProxyPartMachine extends TieredIOPartMachine - implements IMachineLife, IDataStickInteractable { - - protected static final ManagedFieldHolder MANAGED_FIELD_HOLDER = new ManagedFieldHolder( - ExpandedPatternBufferProxyPartMachine.class, TieredIOPartMachine.MANAGED_FIELD_HOLDER); - - @Getter - private final ExpandedProxySlotRecipeHandler proxySlotRecipeHandler; - - @Persisted - @Getter - @DescSynced - private @Nullable BlockPos bufferPos; - - private @Nullable ExpandedPatternBufferPartMachine buffer = null; - private boolean bufferResolved = false; - - public ExpandedPatternBufferProxyPartMachine(IMachineBlockEntity holder) { - super(holder, GTValues.LuV, IO.IN); - this.proxySlotRecipeHandler = new ExpandedProxySlotRecipeHandler(this, 72); - } - - @Override - public void onLoad() { - super.onLoad(); - if (getLevel() instanceof ServerLevel level) { - level.getServer().tell(new TickTask(0, () -> this.setBuffer(bufferPos))); - } - } - - @Override - public List getRecipeHandlers() { - return proxySlotRecipeHandler.getProxySlotHandlers(); - } - - public void setBuffer(@Nullable BlockPos pos) { - this.bufferResolved = true; - var level = getLevel(); - if (level == null || pos == null) { - this.buffer = null; - } else if (MetaMachine.getMachine(level, pos) instanceof ExpandedPatternBufferPartMachine machine) { - bufferPos = pos; - buffer = machine; - machine.addProxy(this); - if (!isRemote()) proxySlotRecipeHandler.updateProxy(machine); - } else { - this.buffer = null; - } - } - - @Nullable - public ExpandedPatternBufferPartMachine getBuffer() { - if (!bufferResolved) setBuffer(bufferPos); - return buffer; - } - - @Override - public boolean shouldOpenUI(Player player, InteractionHand hand, BlockHitResult hit) { - return getBuffer() != null; - } - - @Override - public ModularUI createUI(Player entityPlayer) { - var buf = getBuffer(); - assert buf != null; - return buf.createUI(entityPlayer); - } - - @Override - public ManagedFieldHolder getFieldHolder() { - return MANAGED_FIELD_HOLDER; - } - - @Override - public void onMachineRemoved() { - var buf = getBuffer(); - if (buf != null) { - buf.removeProxy(this); - proxySlotRecipeHandler.clearProxy(); - } - } - - @Override - public InteractionResult onDataStickUse(Player player, ItemStack dataStick) { - if (dataStick.hasTag()) { - assert dataStick.getTag() != null; - if (dataStick.getTag().contains("pos", Tag.TAG_INT_ARRAY)) { - var posArray = dataStick.getOrCreateTag().getIntArray("pos"); - var newBufferPos = new BlockPos(posArray[0], posArray[1], posArray[2]); - setBuffer(newBufferPos); - return InteractionResult.SUCCESS; - } +@MethodsReturnNonnullByDefault +public class ExpandedPatternBufferProxyPartMachine extends MEPatternBufferProxyPartMachine { + + public ExpandedPatternBufferProxyPartMachine(IMachineBlockEntity info) { + super(info); + try { + Field handlerField = MEPatternBufferProxyPartMachine.class.getDeclaredField("proxySlotRecipeHandler"); + handlerField.setAccessible(true); + handlerField.set(this, + new ProxySlotRecipeHandler(this, ExpandedPatternBufferPartMachine.EXPANDED_MAX_PATTERN_COUNT)); + } catch (Exception e) { + throw new RuntimeException("FATAL: Failed to initialize Expanded Proxy Recipe Handler via reflection.", e); } - return InteractionResult.PASS; } } diff --git a/src/main/java/net/neganote/gtutilities/integration/jade/UtilJadePlugin.java b/src/main/java/net/neganote/gtutilities/integration/jade/UtilJadePlugin.java index 1b0cb9e..67deae3 100644 --- a/src/main/java/net/neganote/gtutilities/integration/jade/UtilJadePlugin.java +++ b/src/main/java/net/neganote/gtutilities/integration/jade/UtilJadePlugin.java @@ -5,8 +5,6 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.neganote.gtutilities.integration.jade.provider.EnlargedMEStockingBusInformationProvider; -import net.neganote.gtutilities.integration.jade.provider.ExpandedMEPatternBufferProvider; -import net.neganote.gtutilities.integration.jade.provider.ExpandedMEPatternBufferProxyProvider; import net.neganote.gtutilities.integration.jade.provider.PTERBInformationProvider; import snownee.jade.api.IWailaClientRegistration; @@ -23,8 +21,6 @@ public void register(IWailaCommonRegistration registration) { registration.registerBlockDataProvider(new PTERBInformationProvider(), BlockEntity.class); if (GTCEu.Mods.isAE2Loaded()) { registration.registerBlockDataProvider(new EnlargedMEStockingBusInformationProvider(), BlockEntity.class); - registration.registerBlockDataProvider(new ExpandedMEPatternBufferProvider(), BlockEntity.class); - registration.registerBlockDataProvider(new ExpandedMEPatternBufferProxyProvider(), BlockEntity.class); } } @@ -33,8 +29,6 @@ public void registerClient(IWailaClientRegistration registration) { registration.registerBlockComponent(new PTERBInformationProvider(), Block.class); if (GTCEu.Mods.isAE2Loaded()) { registration.registerBlockComponent(new EnlargedMEStockingBusInformationProvider(), Block.class); - registration.registerBlockComponent(new ExpandedMEPatternBufferProvider(), Block.class); - registration.registerBlockComponent(new ExpandedMEPatternBufferProxyProvider(), Block.class); } } } diff --git a/src/main/java/net/neganote/gtutilities/integration/jade/provider/ExpandedMEPatternBufferProvider.java b/src/main/java/net/neganote/gtutilities/integration/jade/provider/ExpandedMEPatternBufferProvider.java deleted file mode 100644 index 3e30692..0000000 --- a/src/main/java/net/neganote/gtutilities/integration/jade/provider/ExpandedMEPatternBufferProvider.java +++ /dev/null @@ -1,119 +0,0 @@ -package net.neganote.gtutilities.integration.jade.provider; - -import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity; -import com.gregtechceu.gtceu.client.util.TooltipHelper; -import com.gregtechceu.gtceu.integration.jade.GTElementHelper; -import com.gregtechceu.gtceu.utils.FormattingUtil; - -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.fluids.FluidStack; -import net.neganote.gtutilities.GregTechModernUtilities; -import net.neganote.gtutilities.integration.ae2.machine.ExpandedPatternBufferPartMachine; - -import snownee.jade.api.BlockAccessor; -import snownee.jade.api.IBlockComponentProvider; -import snownee.jade.api.IServerDataProvider; -import snownee.jade.api.ITooltip; -import snownee.jade.api.config.IPluginConfig; -import snownee.jade.api.fluid.JadeFluidObject; -import snownee.jade.api.ui.IElementHelper; - -public class ExpandedMEPatternBufferProvider implements IBlockComponentProvider, IServerDataProvider { - - @Override - public void appendTooltip(ITooltip iTooltip, BlockAccessor blockAccessor, IPluginConfig iPluginConfig) { - if (blockAccessor.getBlockEntity() instanceof IMachineBlockEntity blockEntity) { - if (blockEntity.getMetaMachine() instanceof ExpandedPatternBufferPartMachine) { - CompoundTag serverData = blockAccessor.getServerData(); - if (!serverData.getBoolean("formed")) return; - - iTooltip.add(Component.translatable("gtceu.top.proxies_bound", serverData.getInt("proxies")) - .withStyle(TooltipHelper.RAINBOW_HSL_SLOW)); - readBufferTag(iTooltip, serverData); - } - } - } - - @Override - public void appendServerData(CompoundTag compoundTag, BlockAccessor blockAccessor) { - if (blockAccessor.getBlockEntity() instanceof IMachineBlockEntity blockEntity) { - if (blockEntity.getMetaMachine() instanceof ExpandedPatternBufferPartMachine buffer) { - if (!buffer.isFormed()) { - compoundTag.putBoolean("formed", false); - return; - } - compoundTag.putBoolean("formed", true); - compoundTag.putInt("proxies", buffer.getProxies().size()); - writeBufferTag(compoundTag, buffer); - } - } - } - - @Override - public ResourceLocation getUid() { - return GregTechModernUtilities.id("me_expanded_pattern_buffer_info"); - } - - public static void writeBufferTag(CompoundTag compoundTag, ExpandedPatternBufferPartMachine buffer) { - var merged = buffer.mergeInternalSlots(); - var items = merged.items(); - var fluids = merged.fluids(); - - ListTag itemsTag = new ListTag(); - for (var entry : items.object2LongEntrySet()) { - var ct = entry.getKey().serializeNBT(); - ct.putLong("real", entry.getLongValue()); - itemsTag.add(ct); - } - if (!itemsTag.isEmpty()) compoundTag.put("items", itemsTag); - - ListTag fluidsTag = new ListTag(); - for (var entry : fluids.object2LongEntrySet()) { - var ct = entry.getKey().writeToNBT(new CompoundTag()); - ct.putLong("real", entry.getLongValue()); - fluidsTag.add(ct); - } - if (!fluidsTag.isEmpty()) compoundTag.put("fluids", fluidsTag); - } - - public static void readBufferTag(ITooltip iTooltip, CompoundTag serverData) { - IElementHelper helper = iTooltip.getElementHelper(); - - ListTag itemsTag = serverData.getList("items", Tag.TAG_COMPOUND); - for (Tag t : itemsTag) { - if (!(t instanceof CompoundTag ct)) continue; - var stack = ItemStack.of(ct); - var count = ct.getLong("real"); - if (!stack.isEmpty() && count > 0) { - iTooltip.add(helper.smallItem(stack)); - Component text = Component.literal(" ") - .append(Component.literal(FormattingUtil.formatNumbers(count)) - .withStyle(ChatFormatting.DARK_PURPLE)) - .append(Component.literal("× ").withStyle(ChatFormatting.WHITE)) - .append(stack.getHoverName().copy().withStyle(ChatFormatting.GOLD)); - iTooltip.append(text); - } - } - ListTag fluidsTag = serverData.getList("fluids", Tag.TAG_COMPOUND); - for (Tag t : fluidsTag) { - if (!(t instanceof CompoundTag ct)) continue; - var stack = FluidStack.loadFluidStackFromNBT(ct); - var amount = ct.getLong("real"); - if (!stack.isEmpty() && amount > 0) { - iTooltip.add(GTElementHelper.smallFluid(JadeFluidObject.of(stack.getFluid()))); - Component text = Component.literal(" ") - .append(Component.literal(FormattingUtil.formatBuckets(amount))) - .withStyle(ChatFormatting.DARK_PURPLE) - .append(Component.literal(" ").withStyle(ChatFormatting.WHITE)) - .append(stack.getDisplayName().copy().withStyle(ChatFormatting.DARK_AQUA)); - iTooltip.append(text); - } - } - } -} diff --git a/src/main/java/net/neganote/gtutilities/integration/jade/provider/ExpandedMEPatternBufferProxyProvider.java b/src/main/java/net/neganote/gtutilities/integration/jade/provider/ExpandedMEPatternBufferProxyProvider.java deleted file mode 100644 index d6fd627..0000000 --- a/src/main/java/net/neganote/gtutilities/integration/jade/provider/ExpandedMEPatternBufferProxyProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -package net.neganote.gtutilities.integration.jade.provider; - -import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity; -import com.gregtechceu.gtceu.client.util.TooltipHelper; -import com.gregtechceu.gtceu.integration.jade.provider.MEPatternBufferProvider; - -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.neganote.gtutilities.GregTechModernUtilities; -import net.neganote.gtutilities.integration.ae2.machine.ExpandedPatternBufferProxyPartMachine; - -import snownee.jade.api.BlockAccessor; -import snownee.jade.api.IBlockComponentProvider; -import snownee.jade.api.IServerDataProvider; -import snownee.jade.api.ITooltip; -import snownee.jade.api.config.IPluginConfig; - -public class ExpandedMEPatternBufferProxyProvider implements IBlockComponentProvider, - IServerDataProvider { - - @Override - public void appendTooltip(ITooltip iTooltip, BlockAccessor blockAccessor, IPluginConfig iPluginConfig) { - if (blockAccessor.getBlockEntity() instanceof IMachineBlockEntity blockEntity) { - if (blockEntity.getMetaMachine() instanceof ExpandedPatternBufferProxyPartMachine) { - CompoundTag serverData = blockAccessor.getServerData(); - if (!serverData.getBoolean("formed")) return; - if (!serverData.getBoolean("bound")) { - iTooltip.add(Component.translatable("gtceu.top.buffer_not_bound").withStyle(ChatFormatting.RED)); - return; - } - - int[] pos = serverData.getIntArray("pos"); - iTooltip.add(Component.translatable("gtceu.top.buffer_bound_pos", pos[0], pos[1], pos[2]) - .withStyle(TooltipHelper.RAINBOW_HSL_SLOW)); - - MEPatternBufferProvider.readBufferTag(iTooltip, - serverData); - } - } - } - - @Override - public void appendServerData(CompoundTag compoundTag, BlockAccessor blockAccessor) { - if (blockAccessor.getBlockEntity() instanceof IMachineBlockEntity blockEntity) { - if (blockEntity.getMetaMachine() instanceof ExpandedPatternBufferProxyPartMachine proxy) { - if (!proxy.isFormed()) { - compoundTag.putBoolean("formed", false); - return; - } - compoundTag.putBoolean("formed", true); - var buffer = proxy.getBuffer(); - if (buffer == null) { - compoundTag.putBoolean("bound", false); - return; - } - compoundTag.putBoolean("bound", true); - - var pos = buffer.getPos(); - compoundTag.putIntArray("pos", new int[] { pos.getX(), pos.getY(), pos.getZ() }); - ExpandedMEPatternBufferProvider.writeBufferTag(compoundTag, buffer); - } - } - } - - @Override - public ResourceLocation getUid() { - return GregTechModernUtilities.id("me_expanded_pattern_buffer_proxy_info"); - } -}