mirror of
https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial.git
synced 2026-10-25 20:22:23 +00:00
add Super ME Replenisher (#1294)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Martin Robertz <dream-master@gmx.net> Co-authored-by: GitHub GTNH Actions <2970688+Dream-Master@users.noreply.github.com> Co-authored-by: Kogepan229 <73163994+Kogepan229@users.noreply.github.com>
This commit is contained in:
25 files changed
+1173
-26
No files matched your search
@@ -46,4 +46,6 @@ public interface ITickManager extends IGridCache {
|
||||
* @return if the call was successful.
|
||||
*/
|
||||
boolean wakeDevice(IGridNode node);
|
||||
|
||||
default void updateTickRate(final IGridNode node) {}
|
||||
}
|
||||
@@ -184,7 +184,16 @@ public interface IMEInventory<StackType extends IAEStack> {
|
||||
* @deprecated Use {@link IMEInventory#getStackType()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
StorageChannel getChannel();
|
||||
default StorageChannel getChannel() {
|
||||
final IAEStackType<?> type = this.getStackType();
|
||||
if (type == ITEM_STACK_TYPE) {
|
||||
return StorageChannel.ITEMS;
|
||||
} else if (type == FLUID_STACK_TYPE) {
|
||||
return StorageChannel.FLUIDS;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return stack type your handler should be part of
|
||||
|
||||
@@ -34,12 +34,16 @@ public interface IStorageMonitorable {
|
||||
/**
|
||||
* Access the item inventory for the monitorable storage.
|
||||
*/
|
||||
IMEMonitor<IAEItemStack> getItemInventory();
|
||||
default IMEMonitor<IAEItemStack> getItemInventory() {
|
||||
return (IMEMonitor<IAEItemStack>) this.getMEMonitor(ITEM_STACK_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the fluid inventory for the monitorable storage.
|
||||
*/
|
||||
IMEMonitor<IAEFluidStack> getFluidInventory();
|
||||
default IMEMonitor<IAEFluidStack> getFluidInventory() {
|
||||
return (IMEMonitor<IAEFluidStack>) this.getMEMonitor(FLUID_STACK_TYPE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default IMEMonitor<?> getMEMonitor(@Nonnull IAEStackType<?> type) {
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package appeng.block.misc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import appeng.block.AEBaseTileBlock;
|
||||
import appeng.client.texture.ExtraBlockTextures;
|
||||
import appeng.core.features.AEFeature;
|
||||
import appeng.core.sync.GuiBridge;
|
||||
import appeng.tile.misc.TileSuperMEReplenisher;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class BlockSuperMEReplenisher extends AEBaseTileBlock {
|
||||
|
||||
public BlockSuperMEReplenisher() {
|
||||
super(Material.iron);
|
||||
|
||||
this.setTileEntity(TileSuperMEReplenisher.class);
|
||||
this.setFeature(EnumSet.of(AEFeature.Core));
|
||||
this.setHardness(2.2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivated(final World w, final int x, final int y, final int z, final EntityPlayer p,
|
||||
final int side, final float hitX, final float hitY, final float hitZ) {
|
||||
if (p.isSneaking()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final TileSuperMEReplenisher tile = this.getTileEntity(w, x, y, z);
|
||||
if (tile != null) {
|
||||
if (Platform.isClient()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Platform.openGUI(p, tile, ForgeDirection.getOrientation(side), GuiBridge.GUI_SUPER_ME_REPLENISHER);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIcon getIcon(IBlockAccess w, int x, int y, int z, int s) {
|
||||
final TileSuperMEReplenisher tile = this.getTileEntity(w, x, y, z);
|
||||
if (tile != null) {
|
||||
return switch (tile.getStatus()) {
|
||||
case 1 -> ExtraBlockTextures.BlockSuperMEReplenisherDraw.getIcon();
|
||||
case -1 -> ExtraBlockTextures.BlockSuperMEReplenisherExt.getIcon();
|
||||
default -> super.getIcon(w, x, y, z, s);
|
||||
};
|
||||
}
|
||||
return super.getIcon(w, x, y, z, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack is, EntityPlayer player, List<String> lines, boolean advancedItemTooltips) {
|
||||
super.addInformation(is, player, lines, advancedItemTooltips);
|
||||
|
||||
lines.addAll(
|
||||
Arrays.asList(
|
||||
StatCollector.translateToLocal("gui.tooltips.appliedenergistics2.BlockSuperMEReplenisher")
|
||||
.split("\\\\n")));
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package appeng.client.gui.implementations;
|
||||
|
||||
import static appeng.util.Platform.fmt;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.util.numberformatting.NumberFormatUtil;
|
||||
|
||||
import appeng.client.gui.GuiSub;
|
||||
import appeng.client.gui.widgets.GuiAeButton;
|
||||
import appeng.client.gui.widgets.MEGuiTextField;
|
||||
@@ -161,10 +161,6 @@ public class GuiCellRestriction extends GuiSub {
|
||||
super.keyTyped(character, key);
|
||||
}
|
||||
|
||||
private static String fmt(double v) {
|
||||
return NumberFormatUtil.formatNumber(v);
|
||||
}
|
||||
|
||||
private CellRestrictionData filterCellRestriction() {
|
||||
final byte types = (byte) this.getTypes();
|
||||
return new CellRestrictionData(types, this.getAmount(types));
|
||||
|
||||
@@ -3,7 +3,6 @@ package appeng.client.gui.implementations;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
|
||||
import appeng.api.storage.ITerminalHost;
|
||||
import appeng.client.gui.slots.VirtualMESlotSingle;
|
||||
import appeng.container.implementations.ContainerPatternValueAmount;
|
||||
import appeng.core.localization.ColorUtils;
|
||||
@@ -18,7 +17,7 @@ public class GuiPatternValueAmount extends GuiAmount {
|
||||
private final VirtualMESlotSingle slot;
|
||||
|
||||
@Reflected
|
||||
public GuiPatternValueAmount(final InventoryPlayer inventoryPlayer, final ITerminalHost te) {
|
||||
public GuiPatternValueAmount(final InventoryPlayer inventoryPlayer, final Object te) {
|
||||
super(new ContainerPatternValueAmount(inventoryPlayer, te));
|
||||
this.container = (ContainerPatternValueAmount) this.inventorySlots;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package appeng.client.gui.implementations;
|
||||
|
||||
import static appeng.util.Platform.fmt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -21,8 +23,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.util.numberformatting.NumberFormatUtil;
|
||||
|
||||
import appeng.api.config.ActionItems;
|
||||
import appeng.api.config.HealthSortOrder;
|
||||
import appeng.api.config.ReshufflePhase;
|
||||
@@ -944,10 +944,6 @@ public class GuiStorageReshuffle extends AEBaseGui {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String fmt(double v) {
|
||||
return NumberFormatUtil.formatNumber(v);
|
||||
}
|
||||
|
||||
private static String diffColor(double delta) {
|
||||
if (delta > 0) return POSITIVE;
|
||||
if (delta < 0) return NEGATIVE;
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
package appeng.client.gui.implementations;
|
||||
|
||||
import static appeng.util.Platform.fmt;
|
||||
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IAEStackType;
|
||||
import appeng.client.gui.AEBaseGui;
|
||||
import appeng.client.gui.slots.VirtualMEPhantomSlot;
|
||||
import appeng.client.gui.slots.VirtualMEPhantomSlotPrecise;
|
||||
import appeng.client.gui.slots.VirtualMESlot;
|
||||
import appeng.client.gui.widgets.MEGuiTextField;
|
||||
import appeng.container.implementations.ContainerSuperMEReplenisher;
|
||||
import appeng.core.localization.ColorUtils;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.tile.misc.TileSuperMEReplenisher;
|
||||
|
||||
public class GuiSuperMEReplenisher extends AEBaseGui {
|
||||
|
||||
private final ContainerSuperMEReplenisher containerSuperMEReplenisher;
|
||||
private final MEGuiTextField tickRateField;
|
||||
private final MEGuiTextField thresholdField;
|
||||
|
||||
public GuiSuperMEReplenisher(final InventoryPlayer inventoryPlayer, final TileSuperMEReplenisher te) {
|
||||
super(new ContainerSuperMEReplenisher(inventoryPlayer, te));
|
||||
this.containerSuperMEReplenisher = (ContainerSuperMEReplenisher) inventorySlots;
|
||||
this.ySize = 246;
|
||||
this.xSize = 220;
|
||||
|
||||
this.thresholdField = new MEGuiTextField(28, 12);
|
||||
this.thresholdField.setMaxStringLength(3);
|
||||
this.tickRateField = new MEGuiTextField(34, 12);
|
||||
this.tickRateField.setMaxStringLength(4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
this.initVirtualSlots();
|
||||
|
||||
this.tickRateField.x = this.guiLeft + 29;
|
||||
this.thresholdField.x = this.guiLeft + 101;
|
||||
|
||||
this.tickRateField.y = this.guiTop + 133;
|
||||
this.thresholdField.y = this.tickRateField.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) {
|
||||
if (this.containerSuperMEReplenisher.needUpdate) {
|
||||
this.containerSuperMEReplenisher.needUpdate = false;
|
||||
|
||||
this.tickRateField.setText(String.valueOf(this.containerSuperMEReplenisher.tickRate.get()));
|
||||
this.thresholdField.setText(String.valueOf(this.containerSuperMEReplenisher.threshold.get()));
|
||||
}
|
||||
|
||||
final VirtualMESlot slot = this.getVirtualMESlotUnderMouse();
|
||||
final int color = ColorUtils.guiTextColorGray.getColor();
|
||||
if (slot != null) {
|
||||
final IAEStack<?> config = slot.getAEStack();
|
||||
if (config != null) {
|
||||
final IAEStackType<?> type = config.getStackType();
|
||||
final IAEStack<?> stored = this.containerSuperMEReplenisher.storedData.get().list.findPrecise(config);
|
||||
final long storedSize = stored == null ? 0 : stored.getStackSize();
|
||||
|
||||
this.fontRendererObj.drawString(
|
||||
GuiText.SuperMEReplenisherTarget.getLocal(fmt(config.getStackSize())),
|
||||
29,
|
||||
65,
|
||||
color);
|
||||
|
||||
this.fontRendererObj
|
||||
.drawString(GuiText.SuperMEReplenisherStored.getLocal(fmt(storedSize)), 29, 75, color);
|
||||
|
||||
this.fontRendererObj.drawString(
|
||||
GuiText.SuperMEReplenisherBytesUsed
|
||||
.getLocal(fmt((long) Math.ceil((double) storedSize / type.getAmountPerByte()))),
|
||||
29,
|
||||
85,
|
||||
color);
|
||||
}
|
||||
}
|
||||
|
||||
// Status
|
||||
|
||||
final long totalBytes = this.containerSuperMEReplenisher.getTotalBytes();
|
||||
final boolean unlimited = totalBytes >= Long.MAX_VALUE / 16;
|
||||
this.fontRendererObj.drawString(
|
||||
GuiText.SuperMEReplenisherBytesTotal
|
||||
.getLocal(unlimited ? GuiText.SuperMEReplenisherBytesUnlimited.getLocal() : fmt(totalBytes)),
|
||||
29,
|
||||
104,
|
||||
color);
|
||||
this.fontRendererObj.drawString(
|
||||
GuiText.SuperMEReplenisherBytesUsed.getLocal(fmt(this.containerSuperMEReplenisher.getUsedBytes())),
|
||||
29,
|
||||
114,
|
||||
color);
|
||||
|
||||
// Settings
|
||||
|
||||
this.fontRendererObj.drawString(GuiText.SuperMEReplenisherTickRate.getLocal(), 29, 124, color);
|
||||
|
||||
this.fontRendererObj.drawString(GuiText.SuperMEReplenisherThreshold.getLocal(), 100, 124, color);
|
||||
|
||||
this.fontRendererObj.drawString("%", 100 + 31, 136, color);
|
||||
|
||||
this.fontRendererObj.drawString(GuiText.inventory.getLocal(), 29, this.ySize - 99, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) {
|
||||
this.bindTexture("guis/superMEReplenisher.png");
|
||||
this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize);
|
||||
this.tickRateField.drawTextBox();
|
||||
this.thresholdField.drawTextBox();
|
||||
}
|
||||
|
||||
private void initVirtualSlots() {
|
||||
final int xo = 30;
|
||||
final int yo = -154;
|
||||
|
||||
for (int y = 0; y < 3; y++) {
|
||||
for (int x = 0; x < 9; x++) {
|
||||
this.registerVirtualSlots(
|
||||
new VirtualMEPhantomSlotPrecise(
|
||||
xo + x * 18,
|
||||
yo + y * 18 + 9 * 18,
|
||||
this.containerSuperMEReplenisher.config,
|
||||
x + y * 9,
|
||||
this::acceptType) {
|
||||
|
||||
@Override
|
||||
protected void setAEStack(@Nullable IAEStack<?> stack) {
|
||||
if (this.getAEStack() != null)
|
||||
containerSuperMEReplenisher.slotReset.send(this.slotIndex);
|
||||
else super.setAEStack(stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(final int xCoord, final int yCoord, final int btn) {
|
||||
this.tickRateField.mouseClicked(xCoord, yCoord, btn);
|
||||
this.thresholdField.mouseClicked(xCoord, yCoord, btn);
|
||||
super.mouseClicked(xCoord, yCoord, btn);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(final char character, final int key) {
|
||||
if (key == Keyboard.KEY_RETURN || key == Keyboard.KEY_NUMPADENTER) {
|
||||
this.containerSuperMEReplenisher.tickRate.set(this.getInt(this.tickRateField, 10_000));
|
||||
this.containerSuperMEReplenisher.threshold.set(this.getInt(this.thresholdField, 100));
|
||||
this.tickRateField.setFocused(false);
|
||||
this.thresholdField.setFocused(false);
|
||||
} else if (!(this.tickRateField.textboxKeyTyped(character, key)
|
||||
|| this.thresholdField.textboxKeyTyped(character, key)))
|
||||
super.keyTyped(character, key);
|
||||
}
|
||||
|
||||
private int getInt(final MEGuiTextField field, final int maxValue) {
|
||||
try {
|
||||
return Math.min(Math.max(1, Integer.parseInt(field.getText())), maxValue);
|
||||
} catch (Exception ignored) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean acceptType(VirtualMEPhantomSlot slot, IAEStackType<?> type, int mouseButton) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,8 @@ public enum ExtraBlockTextures {
|
||||
BlockSpatialNetworkRelayConnected("BlockSpatialNetworkRelayConnected"),
|
||||
BlockSpatialLinkChamberFrontFull("BlockSpatialLinkChamberFrontFull"),
|
||||
|
||||
;
|
||||
BlockSuperMEReplenisherDraw("BlockSuperMEReplenisherDraw"),
|
||||
BlockSuperMEReplenisherExt("BlockSuperMEReplenisherExt"),;
|
||||
|
||||
private final String name;
|
||||
private IIcon IIcon;
|
||||
|
||||
@@ -6,7 +6,6 @@ import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.ICrafting;
|
||||
|
||||
import appeng.api.storage.ITerminalHost;
|
||||
import appeng.api.storage.StorageName;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.client.gui.implementations.GuiPatternItemRenamer;
|
||||
@@ -23,7 +22,7 @@ public class ContainerPatternValueAmount extends ContainerSubGui implements IVir
|
||||
private IAEStack<?> aes;
|
||||
private int slotIndex;
|
||||
|
||||
public ContainerPatternValueAmount(final InventoryPlayer ip, final ITerminalHost te) {
|
||||
public ContainerPatternValueAmount(final InventoryPlayer ip, final Object te) {
|
||||
super(ip, te);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
package appeng.container.implementations;
|
||||
|
||||
import static appeng.util.Platform.isServer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.implementations.items.IStorageCell;
|
||||
import appeng.api.storage.StorageName;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.container.AEBaseContainer;
|
||||
import appeng.container.guisync.IGuiPacketWritable;
|
||||
import appeng.container.interfaces.IVirtualSlotSource;
|
||||
import appeng.container.slot.SlotRestrictedInput;
|
||||
import appeng.container.sync.ActionHandler;
|
||||
import appeng.container.sync.StreamCodecs;
|
||||
import appeng.container.sync.SyncCodecs;
|
||||
import appeng.container.sync.SyncRegistrar;
|
||||
import appeng.container.sync.handlers.AEStackInventorySyncHandler;
|
||||
import appeng.container.sync.handlers.IntSyncHandler;
|
||||
import appeng.container.sync.handlers.LongSyncHandler;
|
||||
import appeng.container.sync.handlers.ObjectSyncHandler;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.tile.inventory.IAEStackInventory;
|
||||
import appeng.tile.misc.TileSuperMEReplenisher;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.IAEStackList;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class ContainerSuperMEReplenisher extends AEBaseContainer implements IVirtualSlotSource {
|
||||
|
||||
public static class Stored implements IGuiPacketWritable {
|
||||
|
||||
public final IAEStackList list;
|
||||
|
||||
public Stored(final IAEStackList list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public Stored(ByteBuf buf) {
|
||||
this.list = new IAEStackList(true);
|
||||
final int itemListSize = buf.readInt();
|
||||
for (int i = 0; i < itemListSize; i++) this.list.add(Platform.readStackByte(buf));
|
||||
}
|
||||
|
||||
public static Stored copy(final Stored s) {
|
||||
final IAEStackList newList = new IAEStackList(true);
|
||||
s.list.forEach(aes -> newList.add(aes.copy()));
|
||||
return new Stored(newList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Stored subject)) return false;
|
||||
if (this == obj) return true;
|
||||
if (subject.list.size() != this.list.size()) return false;
|
||||
for (final IAEStack<?> aes : this.list)
|
||||
if (!Platform.isStacksIdentical(aes, subject.list.findPrecise(aes))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToPacket(ByteBuf buf) {
|
||||
buf.writeInt(this.list.size());
|
||||
this.list.forEach(o -> Platform.writeStackByte(o, buf));
|
||||
}
|
||||
}
|
||||
|
||||
private final TileSuperMEReplenisher tile;
|
||||
|
||||
private final LongSyncHandler totalBytes;
|
||||
private final LongSyncHandler usedBytes;
|
||||
|
||||
public final IntSyncHandler tickRate;
|
||||
public final IntSyncHandler threshold;
|
||||
|
||||
public final ActionHandler<Integer> slotReset;
|
||||
|
||||
public final AEStackInventorySyncHandler config;
|
||||
public final ObjectSyncHandler<Stored> storedData;
|
||||
|
||||
public boolean needUpdate = false;
|
||||
|
||||
public ContainerSuperMEReplenisher(final InventoryPlayer ip, final TileSuperMEReplenisher te) {
|
||||
super(ip, te);
|
||||
this.tile = te;
|
||||
|
||||
final SyncRegistrar sync = this.syncRegistrar();
|
||||
this.totalBytes = sync.longS2C("totalBytes");
|
||||
this.usedBytes = sync.longS2C("usedBytes");
|
||||
|
||||
this.tickRate = sync.intSync("tickRate").onClientChange((oldValue, newValue) -> this.needUpdate = true)
|
||||
.onServerChange((oldValue, newValue) -> this.tile.setTickRate(newValue));
|
||||
|
||||
this.threshold = sync.intSync("threshold").onClientChange((oldValue, newValue) -> this.needUpdate = true)
|
||||
.onServerChange((oldValue, newValue) -> this.tile.setThreshold((double) newValue / 100));
|
||||
|
||||
this.slotReset = sync.actionC2S("reset", StreamCodecs.intValue()).onServerAction(this::resetSlot);
|
||||
|
||||
this.config = sync.aeStackInventory("config", this.getConfig());
|
||||
|
||||
this.storedData = sync.object(
|
||||
"storedData",
|
||||
SyncCodecs.packetWritable(Stored.class, Stored::new, Stored::copy, Objects::equals),
|
||||
this.tile.getStorage());
|
||||
|
||||
final AppEngInternalInventory cells = this.tile.getCellInventory();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
this.addSlotToContainer(
|
||||
new SlotRestrictedInput(
|
||||
SlotRestrictedInput.PlacableItemType.WORKBENCH_CELL,
|
||||
cells,
|
||||
i,
|
||||
8,
|
||||
8 + i * 18,
|
||||
this.getInventoryPlayer()));
|
||||
this.addSlotToContainer(
|
||||
new SlotRestrictedInput(
|
||||
SlotRestrictedInput.PlacableItemType.WORKBENCH_CELL,
|
||||
cells,
|
||||
3 + i,
|
||||
196,
|
||||
8 + i * 18,
|
||||
this.getInventoryPlayer()));
|
||||
}
|
||||
|
||||
bindPlayerInventory(ip, 22, 158);
|
||||
}
|
||||
|
||||
private void resetSlot(final int slot) {
|
||||
this.tile.getAEInventoryByName(StorageName.CONFIG).putAEStackInSlot(slot, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack slotClick(int slotId, int clickedButton, int mode, EntityPlayer player) {
|
||||
if (slotId >= 0 && slotId < 6) {
|
||||
final ItemStack current = this.tile.getCellInventory().getStackInSlot(slotId);
|
||||
if (current != null) {
|
||||
if (current.getItem() instanceof IStorageCell currentCell) {
|
||||
final long currentBytes = currentCell.getBytesLong(current);
|
||||
if (!(this.totalBytes.get() - this.usedBytes.get() >= currentBytes)) {
|
||||
final ItemStack hand = player.inventory.getItemStack();
|
||||
if (hand != null && hand.getItem() instanceof IStorageCell handCell) {
|
||||
if (!((this.totalBytes.get() + handCell.getBytesLong(hand) - this.usedBytes.get()
|
||||
>= currentBytes))) {
|
||||
return null;
|
||||
}
|
||||
} else return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.slotClick(slotId, clickedButton, mode, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detectAndSendChanges() {
|
||||
this.verifyPermissions(SecurityPermissions.BUILD, false);
|
||||
|
||||
if (isServer()) {
|
||||
this.totalBytes.set(this.tile.getTotalBytes());
|
||||
this.usedBytes.set(this.tile.getUsedBytes());
|
||||
this.tickRate.set(this.tile.getTickRate());
|
||||
this.threshold.set((int) (this.tile.getThreshold() * 100));
|
||||
this.storedData.set(this.tile.getStorage());
|
||||
}
|
||||
|
||||
super.detectAndSendChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateVirtualSlot(StorageName invName, int slotId, IAEStack<?> aes) {
|
||||
final IAEStackInventory config = this.tile.getAEInventoryByName(invName);
|
||||
config.putAEStackInSlot(slotId, aes);
|
||||
}
|
||||
|
||||
public IAEStackInventory getConfig() {
|
||||
return this.tile.getAEInventoryByName(StorageName.CONFIG);
|
||||
}
|
||||
|
||||
public long getTotalBytes() {
|
||||
return this.totalBytes.get();
|
||||
}
|
||||
|
||||
public long getUsedBytes() {
|
||||
return this.usedBytes.get();
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import appeng.block.misc.BlockQuartzTorch;
|
||||
import appeng.block.misc.BlockSecurity;
|
||||
import appeng.block.misc.BlockSkyCompass;
|
||||
import appeng.block.misc.BlockStorageReshuffle;
|
||||
import appeng.block.misc.BlockSuperMEReplenisher;
|
||||
import appeng.block.misc.BlockTinyTNT;
|
||||
import appeng.block.misc.BlockVibrationChamber;
|
||||
import appeng.block.networking.BlockCableBus;
|
||||
@@ -182,6 +183,7 @@ public final class ApiBlocks implements IBlocks {
|
||||
private final IBlockDefinition chunkLoader;
|
||||
private final IBlockDefinition phantomNode;
|
||||
private final IBlockDefinition cubeGenerator;
|
||||
private final IBlockDefinition superMEReplenisher;
|
||||
|
||||
private final Set<IOrientableBlock> orientables;
|
||||
|
||||
@@ -342,6 +344,7 @@ public final class ApiBlocks implements IBlocks {
|
||||
this.chunkLoader = constructor.registerBlockDefinition(new BlockChunkloader());
|
||||
this.phantomNode = constructor.registerBlockDefinition(new BlockPhantomNode());
|
||||
this.cubeGenerator = constructor.registerBlockDefinition(new BlockCubeGenerator());
|
||||
this.superMEReplenisher = constructor.registerBlockDefinition(new BlockSuperMEReplenisher());
|
||||
this.wirelessConnector = constructor.registerTileDefinition(new BlockWirelessConnector());
|
||||
this.wirelessHub = constructor.registerTileDefinition(new BlockWirelessHub());
|
||||
this.crystalGrowthChamber = constructor.registerTileDefinition(new BlockCrystalGrowthChamber());
|
||||
|
||||
@@ -406,6 +406,14 @@ public enum GuiText implements Localization {
|
||||
GuiDimensionalCoordNoDim,
|
||||
GuiDimensionalCoordShortNoDim,
|
||||
|
||||
SuperMEReplenisherBytesTotal,
|
||||
SuperMEReplenisherBytesUnlimited,
|
||||
SuperMEReplenisherBytesUsed,
|
||||
SuperMEReplenisherTickRate,
|
||||
SuperMEReplenisherThreshold,
|
||||
SuperMEReplenisherTarget,
|
||||
SuperMEReplenisherStored,
|
||||
|
||||
itemMEStackPacketDesc1,
|
||||
itemMEStackPacketDesc2,
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ import appeng.container.implementations.ContainerSpatialIOPort;
|
||||
import appeng.container.implementations.ContainerSpatialLinkChamber;
|
||||
import appeng.container.implementations.ContainerStorageBus;
|
||||
import appeng.container.implementations.ContainerStorageReshuffle;
|
||||
import appeng.container.implementations.ContainerSuperMEReplenisher;
|
||||
import appeng.container.implementations.ContainerVibrationChamber;
|
||||
import appeng.container.implementations.ContainerWireless;
|
||||
import appeng.container.implementations.ContainerWirelessKit;
|
||||
@@ -126,6 +127,7 @@ import appeng.tile.misc.TileCrystalGrowthChamber;
|
||||
import appeng.tile.misc.TileInscriber;
|
||||
import appeng.tile.misc.TileSecurity;
|
||||
import appeng.tile.misc.TileStorageReshuffle;
|
||||
import appeng.tile.misc.TileSuperMEReplenisher;
|
||||
import appeng.tile.misc.TileVibrationChamber;
|
||||
import appeng.tile.networking.TileWireless;
|
||||
import appeng.tile.qnb.TileQuantumBridge;
|
||||
@@ -231,7 +233,7 @@ public enum GuiBridge implements IGuiHandler {
|
||||
GUI_CRAFTING_AMOUNT(ContainerCraftAmount.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD,
|
||||
SecurityPermissions.CRAFT),
|
||||
|
||||
GUI_PATTERN_VALUE_AMOUNT(ContainerPatternValueAmount.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD, null),
|
||||
GUI_PATTERN_VALUE_AMOUNT(ContainerPatternValueAmount.class, Object.class, GuiHostType.ITEM_OR_WORLD, null),
|
||||
|
||||
GUI_PATTERN_MULTI(ContainerPatternMulti.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD, null),
|
||||
|
||||
@@ -259,7 +261,10 @@ public enum GuiBridge implements IGuiHandler {
|
||||
|
||||
GUI_SUPER_WIRELESS_KIT(ContainerWirelessKit.class, IGuiItemObject.class, GuiHostType.ITEM, null),
|
||||
|
||||
GUI_WIRELESS_NETWORK_MANAGER(ContainerWirelessNetworkManager.class, IGuiItemObject.class, GuiHostType.ITEM, null);
|
||||
GUI_WIRELESS_NETWORK_MANAGER(ContainerWirelessNetworkManager.class, IGuiItemObject.class, GuiHostType.ITEM, null),
|
||||
|
||||
GUI_SUPER_ME_REPLENISHER(ContainerSuperMEReplenisher.class, TileSuperMEReplenisher.class, GuiHostType.WORLD,
|
||||
SecurityPermissions.BUILD);
|
||||
|
||||
private final Class tileClass;
|
||||
private final Class containerClass;
|
||||
|
||||
@@ -218,4 +218,23 @@ public class TickManagerCache implements ITickManager {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTickRate(IGridNode gridNode) {
|
||||
final IGridHost machine = gridNode.getMachine();
|
||||
if (machine instanceof IGridTickable) {
|
||||
final TickingRequest tr = ((IGridTickable) machine).getTickingRequest(gridNode);
|
||||
if (tr != null) {
|
||||
final TickTracker tt = new TickTracker(tr, gridNode, (IGridTickable) machine, this.currentTick, this);
|
||||
this.alertable.replace(gridNode, tt);
|
||||
this.sleeping.replace(gridNode, tt);
|
||||
final TickTracker awakeTT = this.awake.get(gridNode);
|
||||
if (awakeTT != null) {
|
||||
this.upcomingTicks.remove(awakeTT);
|
||||
this.upcomingTicks.add(tt);
|
||||
}
|
||||
this.awake.replace(gridNode, tt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import appeng.api.storage.IExternalStorageHandler;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.data.IAEStackType;
|
||||
import appeng.tile.misc.TileCondenser;
|
||||
import appeng.tile.misc.TileSuperMEReplenisher;
|
||||
|
||||
public class AEExternalHandler implements IExternalStorageHandler {
|
||||
|
||||
@@ -29,6 +30,7 @@ public class AEExternalHandler implements IExternalStorageHandler {
|
||||
public boolean canHandle(TileEntity te, ForgeDirection d, IAEStackType<?> type, BaseActionSource mySrc) {
|
||||
if (te instanceof ITileStorageMonitorable)
|
||||
return ((ITileStorageMonitorable) te).getMonitorable(d, mySrc) != null;
|
||||
else if (te instanceof TileSuperMEReplenisher) return true;
|
||||
else return te instanceof TileCondenser && (type == ITEM_STACK_TYPE || type == FLUID_STACK_TYPE);
|
||||
}
|
||||
|
||||
@@ -43,7 +45,7 @@ public class AEExternalHandler implements IExternalStorageHandler {
|
||||
|
||||
if (te instanceof ITileStorageMonitorable iface) {
|
||||
return iface.getMonitorable(d, src).getMEMonitor(type);
|
||||
}
|
||||
} else if (te instanceof TileSuperMEReplenisher tSMR) return new MEInventoryWrapper(tSMR, type);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package appeng.me.storage;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IAEStackType;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
|
||||
public class MEInventoryWrapper<T extends IAEStack<T>> implements IMEInventory<T> {
|
||||
|
||||
private final IMEInventory<T> delegate;
|
||||
private final IAEStackType<T> type;
|
||||
|
||||
public MEInventoryWrapper(IMEInventory<T> delegate, IAEStackType<T> type) {
|
||||
this.delegate = delegate;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems(T input, Actionable type, BaseActionSource src) {
|
||||
return this.delegate.injectItems(input, type, src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems(T request, Actionable mode, BaseActionSource src) {
|
||||
return this.delegate.extractItems(request, mode, src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(IItemList<T> out, int iteration) {
|
||||
return this.delegate.getAvailableItems(out, iteration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEStackType<?> getStackType() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
package appeng.tile.misc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.item.ItemStackNBT;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.implementations.IPowerChannelState;
|
||||
import appeng.api.implementations.items.IStorageCell;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.events.MENetworkBootingStatusChange;
|
||||
import appeng.api.networking.events.MENetworkEventSubscribe;
|
||||
import appeng.api.networking.events.MENetworkPowerStatusChange;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.networking.security.MachineSource;
|
||||
import appeng.api.networking.storage.IStorageGrid;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.StorageName;
|
||||
import appeng.api.storage.data.AEStackTypeRegistry;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IAEStackType;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.container.implementations.ContainerSuperMEReplenisher;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.TileEvent;
|
||||
import appeng.tile.events.TileEventType;
|
||||
import appeng.tile.grid.AENetworkTile;
|
||||
import appeng.tile.inventory.AppEngInternalInventory;
|
||||
import appeng.tile.inventory.IAEStackInventory;
|
||||
import appeng.tile.inventory.IIAEStackInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.IAEStackList;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
|
||||
public class TileSuperMEReplenisher extends AENetworkTile
|
||||
implements IMEInventory<IAEStack<?>>, IIAEStackInventory, IPowerChannelState, IGridTickable {
|
||||
|
||||
private final IAEStackList storage = new IAEStackList(true);
|
||||
private final IAEStackList out = new IAEStackList(true);
|
||||
private final IAEStackInventory config = new IAEStackInventory(this, 3 * 9, StorageName.CONFIG) {
|
||||
|
||||
@Override
|
||||
public void putAEStackInSlot(int n, IAEStack<?> aes) {
|
||||
if (haveSame(n, aes)) return;
|
||||
if (Platform.isServer() && TileSuperMEReplenisher.this.onConfigChange(n, aes)) return;
|
||||
super.putAEStackInSlot(n, aes);
|
||||
}
|
||||
};
|
||||
|
||||
private final Object2IntOpenHashMap<IAEStackType<?>> unusedCount = new Object2IntOpenHashMap<>();
|
||||
|
||||
private long totalBytes = 0;
|
||||
private long usedBytes = 0;
|
||||
|
||||
private int tickRate = 120;
|
||||
private double threshold = 0.5;
|
||||
|
||||
private boolean unlimited = false;
|
||||
private boolean isPowered = false;
|
||||
|
||||
private int status = 0;
|
||||
|
||||
private final BaseActionSource src = new MachineSource(this);
|
||||
|
||||
private final AppEngInternalInventory cells = new AppEngInternalInventory(null, 6) {
|
||||
|
||||
@Override
|
||||
public ItemStack decrStackSize(int slot, int qty) {
|
||||
TileSuperMEReplenisher.this.removeCell(this.getStackInSlot(slot));
|
||||
return super.decrStackSize(slot, qty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInventorySlotContents(int slot, ItemStack newItemStack) {
|
||||
TileSuperMEReplenisher.this.removeCell(this.getStackInSlot(slot));
|
||||
TileSuperMEReplenisher.this.addCell(newItemStack);
|
||||
super.setInventorySlotContents(slot, newItemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
TileSuperMEReplenisher.this.markDirty();
|
||||
}
|
||||
};
|
||||
|
||||
public TileSuperMEReplenisher() {
|
||||
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
|
||||
this.getProxy().setIdlePowerUsage(4.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest(IGridNode node) {
|
||||
return new TickingRequest(this.tickRate, this.tickRate, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall) {
|
||||
try {
|
||||
if (this.getProxy().isActive()) return this.doWork(this.getProxy().getStorage());
|
||||
} catch (final GridAccessException ignored) {}
|
||||
return TickRateModulation.SAME;
|
||||
}
|
||||
|
||||
private void updateTickRate() {
|
||||
try {
|
||||
this.getProxy().getTick().updateTickRate(this.getGridNode(ForgeDirection.UNKNOWN));
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
@TileEvent(TileEventType.TICK)
|
||||
public void tick() {
|
||||
if (Platform.isServer() && this.status != 0) {
|
||||
this.status = 0;
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@TileEvent(TileEventType.NETWORK_READ)
|
||||
public boolean readFromStream_TileSuperMEReplenisher(final ByteBuf data) {
|
||||
final boolean oldPower = this.isPowered;
|
||||
final int oldStatus = this.status;
|
||||
this.isPowered = data.readBoolean();
|
||||
this.status = data.readInt();
|
||||
return this.isPowered != oldPower || this.status != oldStatus;
|
||||
}
|
||||
|
||||
@TileEvent(TileEventType.NETWORK_WRITE)
|
||||
public void writeToStream_TileSuperMEReplenisher(final ByteBuf data) {
|
||||
data.writeBoolean(isActive());
|
||||
data.writeInt(this.status);
|
||||
}
|
||||
|
||||
@TileEvent(TileEventType.WORLD_NBT_READ)
|
||||
public void readFromNBTEvent(NBTTagCompound data) {
|
||||
this.config.readFromNBT(data, "config");
|
||||
this.cells.readFromNBT(data, "cells");
|
||||
|
||||
if (data.hasKey("threshold")) this.threshold = data.getDouble("threshold");
|
||||
if (data.hasKey("tickRate")) this.setTickRate(data.getInteger("tickRate"));
|
||||
Platform.readAEStackListNBT(this.storage, data.getTagList("storage", Constants.NBT.TAG_COMPOUND));
|
||||
Platform.readAEStackListNBT(this.out, data.getTagList("out", Constants.NBT.TAG_COMPOUND));
|
||||
|
||||
this.countBytes();
|
||||
this.countUsedBytes();
|
||||
}
|
||||
|
||||
@TileEvent(TileEventType.WORLD_NBT_WRITE)
|
||||
public NBTTagCompound writeToNBTEvent(NBTTagCompound data) {
|
||||
this.config.writeToNBT(data, "config");
|
||||
this.cells.writeToNBT(data, "cells");
|
||||
|
||||
data.setDouble("threshold", this.threshold);
|
||||
data.setInteger("tickRate", this.tickRate);
|
||||
data.setTag("storage", Platform.writeAEStackListNBT(this.storage));
|
||||
data.setTag("out", Platform.writeAEStackListNBT(this.out));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange(final MENetworkPowerStatusChange p) {
|
||||
this.updatePowerState();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public final void bootingRender(final MENetworkBootingStatusChange c) {
|
||||
this.updatePowerState();
|
||||
}
|
||||
|
||||
private TickRateModulation doWork(final IStorageGrid storage) {
|
||||
for (int i = 0; i < this.config.getSizeInventory(); i++) {
|
||||
final IAEStack<?> config = this.config.getAEStackInSlot(i);
|
||||
if (config == null) continue;
|
||||
final IAEStackType<?> type = config.getStackType();
|
||||
final IAEStack<?> stored = this.storage.findPrecise(config);
|
||||
|
||||
final long configSize = config.getStackSize();
|
||||
final long storedSize = stored == null ? 0 : stored.getStackSize();
|
||||
|
||||
if (((double) storedSize / configSize) < this.threshold) {
|
||||
final IAEStack<?> toRequest = config.copy();
|
||||
toRequest.setStackSize(configSize - storedSize);
|
||||
toRequest(toRequest, storage);
|
||||
} else if (storedSize > configSize) {
|
||||
final IAEStack<?> toReturn = config.copy();
|
||||
toReturn.setStackSize(storedSize - configSize);
|
||||
toReturn(toReturn, storage, this.storage);
|
||||
}
|
||||
}
|
||||
|
||||
this.refund(this.out);
|
||||
|
||||
return TickRateModulation.SAME;
|
||||
}
|
||||
|
||||
private boolean haveSame(final int n, final IAEStack<?> aes) {
|
||||
for (int i = 0; i < this.config.getSizeInventory(); i++) {
|
||||
if (i == n) continue;
|
||||
final IAEStack<?> config = this.config.getAEStackInSlot(i);
|
||||
if (config == null) continue;
|
||||
if (config.equals(aes)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean onConfigChange(final int slots, final IAEStack<?> newStack) {
|
||||
try {
|
||||
final IStorageGrid storage = this.getProxy().getStorage();
|
||||
final IAEStack<?> currentConfig = this.config.getAEStackInSlot(slots);
|
||||
if (currentConfig == null) return false;
|
||||
if (currentConfig.equals(newStack)) {
|
||||
final long currentConfigSize = currentConfig.getStackSize();
|
||||
final long newConfigSize = newStack.getStackSize();
|
||||
|
||||
if (currentConfigSize > newConfigSize) {
|
||||
final IAEStack<?> stored = this.get(currentConfig);
|
||||
if (stored == null) return false;
|
||||
final long storedSize = stored.getStackSize();
|
||||
if (storedSize > newConfigSize) {
|
||||
final long newSize = storedSize - newConfigSize;
|
||||
final IAEStack<?> tempStack = stored.copy();
|
||||
tempStack.setStackSize(newSize);
|
||||
this.toReturn(tempStack, storage, this.storage);
|
||||
return stored.getStackSize() > newConfigSize;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
this.doWork(storage);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this.toReturn(currentConfig, storage, this.storage);
|
||||
final IAEStack<?> stored = this.get(currentConfig);
|
||||
return !(stored == null || stored.getStackSize() == 0);
|
||||
}
|
||||
} catch (final GridAccessException ignored) {}
|
||||
return true;
|
||||
}
|
||||
|
||||
private IAEStack<?> get(final IAEStack<?> aes) {
|
||||
return this.storage.findPrecise(aes);
|
||||
}
|
||||
|
||||
private void toRequest(final IAEStack<?> aes, final IStorageGrid storage) {
|
||||
final IMEMonitor monitor = storage.getMEMonitor(aes.getStackType());
|
||||
if (monitor == null) return;
|
||||
final IAEStack<?> notAllowed = this.injectItems(aes, Actionable.SIMULATE, this.storage);
|
||||
|
||||
if (notAllowed != null) {
|
||||
final long requestSize = aes.getStackSize();
|
||||
final long notAllowedSize = notAllowed.getStackSize();
|
||||
aes.setStackSize(requestSize - notAllowedSize);
|
||||
}
|
||||
|
||||
final IAEStack<?> extracted = monitor.extractItems(aes, Actionable.MODULATE, this.src);
|
||||
this.injectItems(extracted, Actionable.MODULATE, this.storage);
|
||||
}
|
||||
|
||||
private void toReturn(final IAEStack<?> aes, final IStorageGrid storage, final IAEStackList target) {
|
||||
final IMEMonitor monitor = storage.getMEMonitor(aes.getStackType());
|
||||
if (monitor == null) return;
|
||||
final IAEStack<?> allowed = this.extractItems(aes, Actionable.MODULATE, target);
|
||||
if (allowed == null) return;
|
||||
final IAEStack<?> notInjected = monitor.injectItems(allowed, Actionable.MODULATE, this.src);
|
||||
this.injectItems(notInjected, Actionable.MODULATE, target);
|
||||
}
|
||||
|
||||
private void refund(final IAEStackList fList) {
|
||||
try {
|
||||
final IStorageGrid storage = this.getProxy().getStorage();
|
||||
fList.forEach(listItem -> {
|
||||
final IMEMonitor monitor = storage.getMEMonitor(listItem.getStackType());
|
||||
if (monitor != null) {
|
||||
final IAEStack<?> leftOver = monitor.injectItems(
|
||||
this.extractItems(listItem, Actionable.MODULATE, fList),
|
||||
Actionable.MODULATE,
|
||||
this.src);
|
||||
if (leftOver != null) this.injectItems(leftOver, Actionable.MODULATE, fList);
|
||||
}
|
||||
});
|
||||
} catch (final GridAccessException ignored) {}
|
||||
}
|
||||
|
||||
public void fullRefund() {
|
||||
this.refund(this.storage);
|
||||
this.refund(this.out);
|
||||
}
|
||||
|
||||
private long getCellBytes(final ItemStack is) {
|
||||
if (is != null && is.getItem() instanceof IStorageCell baseCell) {
|
||||
return baseCell.getBytesLong(is);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void removeCell(final ItemStack is) {
|
||||
final long newBytes = this.getCellBytes(is);
|
||||
this.totalBytes -= newBytes;
|
||||
|
||||
if (this.totalBytes < Long.MAX_VALUE / 16) {
|
||||
this.unlimited = false;
|
||||
this.countUsedBytes();
|
||||
}
|
||||
|
||||
this.updatePowerDraw();
|
||||
}
|
||||
|
||||
private void addCell(final ItemStack is) {
|
||||
final long newBytes = this.getCellBytes(is);
|
||||
this.totalBytes += newBytes;
|
||||
if (this.totalBytes >= Long.MAX_VALUE / 16) this.unlimited = true;
|
||||
this.updatePowerDraw();
|
||||
}
|
||||
|
||||
private void updatePowerDraw() {
|
||||
final double powerDraw;
|
||||
if (this.unlimited) powerDraw = 1;
|
||||
else powerDraw = Math.sqrt(Math.pow(this.totalBytes, 0.576D));
|
||||
this.getProxy().setIdlePowerUsage(powerDraw);
|
||||
}
|
||||
|
||||
private void updatePowerState() {
|
||||
boolean newState = false;
|
||||
try {
|
||||
newState = this.getProxy().isActive()
|
||||
&& this.getProxy().getEnergy().extractAEPower(1, Actionable.SIMULATE, PowerMultiplier.CONFIG)
|
||||
> 0.0001;
|
||||
} catch (final GridAccessException ignored) {}
|
||||
if (newState != this.isPowered) {
|
||||
this.isPowered = newState;
|
||||
this.markForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEStack<?>> getAvailableItems(IItemList<IAEStack<?>> out, int iteration) {
|
||||
final IAEStackType<?> outStackType = out.getStackType();
|
||||
this.storage.forEach(aes -> { if (aes.getStackType().equals(outStackType)) out.add(aes); });
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEStack<?> injectItems(IAEStack<?> input, Actionable type, BaseActionSource src) {
|
||||
return this.injectItems(input, type, this.out);
|
||||
}
|
||||
|
||||
private IAEStack<?> injectItems(final IAEStack<?> input, final Actionable type, final IAEStackList target) {
|
||||
if (input == null) return null;
|
||||
|
||||
final long freeBytes = this.totalBytes - this.usedBytes;
|
||||
|
||||
final IAEStackType<?> stackType = input.getStackType();
|
||||
final int typeWeight = stackType.getAmountPerByte();
|
||||
final long stackSize = input.getStackSize();
|
||||
final int unusedCount = this.unusedCount.getOrDefault(stackType, 0);
|
||||
|
||||
if (freeBytes == 0 && unusedCount == 0) return input;
|
||||
|
||||
final int freeUnusedCount = unusedCount == 0 ? 0 : typeWeight - unusedCount;
|
||||
|
||||
final long needBytes;
|
||||
final int newUnusedCount;
|
||||
if (stackSize > freeUnusedCount) {
|
||||
final long toCountSize = stackSize - freeUnusedCount;
|
||||
needBytes = (long) Math.ceil((double) toCountSize / typeWeight);
|
||||
newUnusedCount = (int) toCountSize % typeWeight;
|
||||
} else {
|
||||
needBytes = 0;
|
||||
newUnusedCount = (int) ((unusedCount + stackSize) % typeWeight);
|
||||
}
|
||||
|
||||
if (type == Actionable.SIMULATE) {
|
||||
if (freeBytes >= needBytes) return null;
|
||||
else {
|
||||
final IAEStack<?> notAllowed = input.copy();
|
||||
notAllowed.setStackSize(input.getStackSize() - ((freeBytes * typeWeight) + freeUnusedCount));
|
||||
return notAllowed;
|
||||
}
|
||||
} else {
|
||||
this.status = 1;
|
||||
this.markForUpdate();
|
||||
|
||||
if (freeBytes >= needBytes) {
|
||||
if (!this.unlimited) {
|
||||
this.unusedCount.put(stackType, newUnusedCount);
|
||||
this.usedBytes += needBytes;
|
||||
}
|
||||
|
||||
target.add(input);
|
||||
return null;
|
||||
} else {
|
||||
final IAEStack<?> notAllowed = input.copy();
|
||||
final IAEStack<?> allowed = input.copy();
|
||||
|
||||
if (!this.unlimited) {
|
||||
final long newNeedBytes = freeBytes * typeWeight;
|
||||
notAllowed.setStackSize(input.getStackSize() - (newNeedBytes + freeUnusedCount));
|
||||
allowed.setStackSize(input.getStackSize() - notAllowed.getStackSize());
|
||||
|
||||
this.usedBytes += freeBytes;
|
||||
this.unusedCount.put(stackType, 0);
|
||||
}
|
||||
|
||||
target.add(allowed);
|
||||
return notAllowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEStack<?> extractItems(IAEStack<?> request, Actionable mode, BaseActionSource src) {
|
||||
return this.extractItems(request, mode, this.storage);
|
||||
}
|
||||
|
||||
private IAEStack<?> extractItems(final IAEStack<?> request, final Actionable mode, final IAEStackList target) {
|
||||
if (request == null) return null;
|
||||
|
||||
final IAEStackType<?> stackType = request.getStackType();
|
||||
final IAEStack<?> stack = target.findPrecise(request);
|
||||
if (stack == null) return null;
|
||||
|
||||
final long stackSize = stack.getStackSize();
|
||||
if (stackSize <= 0) return null;
|
||||
|
||||
long requestSize = request.getStackSize();
|
||||
final IAEStack<?> ret = request.copy();
|
||||
|
||||
if (stackSize < requestSize) {
|
||||
ret.setStackSize(stackSize);
|
||||
requestSize = stackSize;
|
||||
}
|
||||
|
||||
if (mode == Actionable.MODULATE) {
|
||||
this.status = -1;
|
||||
this.markForUpdate();
|
||||
|
||||
stack.decStackSize(requestSize);
|
||||
if (!this.unlimited) {
|
||||
final int typeWeight = stackType.getAmountPerByte();
|
||||
final int unusedCount = this.unusedCount.getOrDefault(stackType, 0);
|
||||
|
||||
final int freeInPartialByte = unusedCount == 0 ? 0 : typeWeight - unusedCount;
|
||||
final long freedBytes = (freeInPartialByte + requestSize) / typeWeight;
|
||||
final int newFreeInPartialByte = (int) ((freeInPartialByte + requestSize) % typeWeight);
|
||||
final int newUnusedCount = newFreeInPartialByte == 0 ? 0 : typeWeight - newFreeInPartialByte;
|
||||
|
||||
this.usedBytes -= freedBytes;
|
||||
this.unusedCount.put(stackType, newUnusedCount);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void countUsedBytes() {
|
||||
this.usedBytes = 0;
|
||||
|
||||
final Object2DoubleOpenHashMap<IAEStackType<?>> unusedCount = new Object2DoubleOpenHashMap<>();
|
||||
this.storage.forEach(aes -> {
|
||||
final IAEStackType<?> stackType = aes.getStackType();
|
||||
unusedCount.put(stackType, unusedCount.getOrDefault(stackType, 0) + aes.getStackSize());
|
||||
});
|
||||
|
||||
this.out.forEach(aes -> {
|
||||
final IAEStackType<?> stackType = aes.getStackType();
|
||||
unusedCount.put(stackType, unusedCount.getOrDefault(stackType, 0) + aes.getStackSize());
|
||||
});
|
||||
|
||||
for (IAEStackType<?> stackType : AEStackTypeRegistry.getAllTypes()) {
|
||||
final int typeWeight = stackType.getAmountPerByte();
|
||||
final double count = unusedCount.getOrDefault(stackType, 0);
|
||||
this.unusedCount.put(stackType, (int) count % typeWeight);
|
||||
this.usedBytes += (long) Math.ceil(count / typeWeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void countBytes() {
|
||||
this.totalBytes = 0;
|
||||
for (int i = 0; i < this.cells.getSizeInventory(); i++) {
|
||||
this.totalBytes += this.getCellBytes(this.cells.getStackInSlot(i));
|
||||
}
|
||||
|
||||
if (this.totalBytes >= Long.MAX_VALUE / 16) this.unlimited = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAEStackInv() {
|
||||
this.markDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDrops(World w, int x, int y, int z, List<ItemStack> drops) {
|
||||
this.fullRefund();
|
||||
|
||||
for (int i = 0; i < this.cells.getSizeInventory(); i++) {
|
||||
final ItemStack cell = this.cells.getStackInSlot(i);
|
||||
if (cell != null) drops.add(cell);
|
||||
}
|
||||
|
||||
this.zeroVoid(drops);
|
||||
}
|
||||
|
||||
private void zeroVoid(final IAEStackList fList, final List<ItemStack> drops) {
|
||||
final ItemStack container = AEApi.instance().definitions().items().itemMEStackPacket().maybeStack(1).get();
|
||||
fList.forEach(listItem -> {
|
||||
final ItemStack is = container.copy();
|
||||
Platform.writeStackNBT(listItem, ItemStackNBT.get(is));
|
||||
drops.add(is);
|
||||
});
|
||||
}
|
||||
|
||||
public void zeroVoid(final List<ItemStack> drops) {
|
||||
this.zeroVoid(this.storage, drops);
|
||||
this.zeroVoid(this.out, drops);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPowered() {
|
||||
return this.isPowered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return this.isPowered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEStackInventory getAEInventoryByName(StorageName name) {
|
||||
if (name == StorageName.CONFIG) return this.config;
|
||||
return null;
|
||||
}
|
||||
|
||||
public ContainerSuperMEReplenisher.Stored getStorage() {
|
||||
return new ContainerSuperMEReplenisher.Stored(this.storage);
|
||||
}
|
||||
|
||||
public AppEngInternalInventory getCellInventory() {
|
||||
return this.cells;
|
||||
}
|
||||
|
||||
public long getTotalBytes() {
|
||||
return this.totalBytes;
|
||||
}
|
||||
|
||||
public long getUsedBytes() {
|
||||
if (this.unlimited) this.countUsedBytes();
|
||||
return this.usedBytes;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public void setTickRate(final int tickRate) {
|
||||
this.tickRate = tickRate;
|
||||
this.updateTickRate();
|
||||
}
|
||||
|
||||
public int getTickRate() {
|
||||
return this.tickRate;
|
||||
}
|
||||
|
||||
public void setThreshold(final double threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
public double getThreshold() {
|
||||
return this.threshold;
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import com.glodblock.github.common.item.ItemFluidDrop;
|
||||
import com.glodblock.github.common.item.ItemFluidPacket;
|
||||
import com.gtnewhorizon.gtnhlib.item.ItemStackNBT;
|
||||
import com.gtnewhorizon.gtnhlib.util.numberformatting.NumberFormatUtil;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
@@ -2064,7 +2065,16 @@ public class Platform {
|
||||
}
|
||||
|
||||
public static IItemList<IAEStack<?>> readAEStackListNBT(final NBTTagList tag, boolean convert) {
|
||||
final IItemList<IAEStack<?>> out = AEApi.instance().storage().createAEStackList();
|
||||
return readAEStackListNBT(null, tag, convert);
|
||||
}
|
||||
|
||||
public static IItemList<IAEStack<?>> readAEStackListNBT(final IItemList<IAEStack<?>> out, final NBTTagList tag) {
|
||||
return readAEStackListNBT(out, tag, false);
|
||||
}
|
||||
|
||||
public static IItemList<IAEStack<?>> readAEStackListNBT(IItemList<IAEStack<?>> out, final NBTTagList tag,
|
||||
boolean convert) {
|
||||
if (out == null) out = AEApi.instance().storage().createAEStackList();
|
||||
|
||||
if (tag != null) {
|
||||
for (int x = 0; x < tag.tagCount(); x++) {
|
||||
@@ -2168,6 +2178,10 @@ public class Platform {
|
||||
}
|
||||
}
|
||||
|
||||
public static String fmt(double v) {
|
||||
return NumberFormatUtil.formatNumber(v);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract("_ -> new")
|
||||
public static ItemStack copyStackWithSizeOne(@NotNull ItemStack itemStack) {
|
||||
|
||||
@@ -21,8 +21,18 @@ public final class IAEStackList implements IItemList<IAEStack<?>> {
|
||||
private final Map<IAEStackType<?>, IItemList> lists = new IdentityHashMap<>();
|
||||
|
||||
public IAEStackList() {
|
||||
for (IAEStackType<?> type : AEStackTypeRegistry.getAllTypes()) {
|
||||
this.lists.put(type, type.createList());
|
||||
this(false);
|
||||
}
|
||||
|
||||
public IAEStackList(final boolean primitive) {
|
||||
if (primitive) {
|
||||
for (IAEStackType<?> type : AEStackTypeRegistry.getAllTypes()) {
|
||||
this.lists.put(type, type.createPrimitiveList());
|
||||
}
|
||||
} else {
|
||||
for (IAEStackType<?> type : AEStackTypeRegistry.getAllTypes()) {
|
||||
this.lists.put(type, type.createList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ tile.appliedenergistics2.BlockSingularityCraftingStorage.name=Singularity Crafti
|
||||
tile.appliedenergistics2.BlockPaint.name=Paint
|
||||
tile.appliedenergistics2.BlockSpatialLinkChamber.name=Spatial Link Chamber
|
||||
tile.appliedenergistics2.BlockSpatialNetworkRelay.name=Spatial Network Relay
|
||||
tile.appliedenergistics2.BlockSuperMEReplenisher.name=Super ME Replenisher
|
||||
tile.appliedenergistics2.BlockWirelessConnector.name=Wireless Connector
|
||||
tile.appliedenergistics2.BlockWirelessHub.name=Wireless Hub
|
||||
tile.appliedenergistics2.BlockCrystalGrowthChamber.name=Crystal Growth Chamber
|
||||
@@ -251,6 +252,14 @@ gui.appliedenergistics2.ReshuffleReportTextColorNegative=§4
|
||||
gui.appliedenergistics2.ReshuffleReportTextColorNeutral=§8
|
||||
gui.appliedenergistics2.ReshuffleReportTextColorWarning=§6
|
||||
|
||||
gui.appliedenergistics2.SuperMEReplenisherBytesTotal=Bytes total: §6%s
|
||||
gui.appliedenergistics2.SuperMEReplenisherBytesUnlimited=Unlimited
|
||||
gui.appliedenergistics2.SuperMEReplenisherBytesUsed=Bytes used: §c%s
|
||||
gui.appliedenergistics2.SuperMEReplenisherTickRate=Tick Rate
|
||||
gui.appliedenergistics2.SuperMEReplenisherThreshold=Threshold
|
||||
gui.appliedenergistics2.SuperMEReplenisherTarget=Target: §5%s
|
||||
gui.appliedenergistics2.SuperMEReplenisherStored=Stored: §5%s
|
||||
|
||||
gui.appliedenergistics2.Efficiency=Efficiency
|
||||
gui.appliedenergistics2.RequiredPower=Required Power
|
||||
gui.appliedenergistics2.StoredPower=Stored Power
|
||||
@@ -830,6 +839,7 @@ gui.tooltips.appliedenergistics2.BlockCreativeEnergyCell=§dInfinite Energy
|
||||
gui.tooltips.appliedenergistics2.PartCreativeEnergy=§dInfinite Energy
|
||||
gui.tooltips.appliedenergistics2.BlockCreativeEnergyController=§dInfinite Energy
|
||||
gui.tooltips.appliedenergistics2.PreconfiguredPriority=Preconfigured storage priority: §f%s
|
||||
gui.tooltips.appliedenergistics2.BlockSuperMEReplenisher=Only for network usage!\nEverything injected will be cached\nThen flashed in local network on Tick Rate!
|
||||
|
||||
# Units
|
||||
gui.appliedenergistics2.units.appliedenergistics=AE
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 614 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 610 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 610 B |
Binary file not shown.
|
After Width: | Height: | Size: 805 B |
Reference in new issue
Block a user