From ba686f96c6fb90c5557e4e063a5f0308d7f67aad Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Tue, 31 Oct 2023 17:46:38 +0800 Subject: [PATCH 01/34] Add network bytes infomation for network status gui --- .../api/networking/storage/IStorageGrid.java | 56 +- .../gui/implementations/GuiNetworkStatus.java | 25 +- .../ContainerNetworkStatus.java | 292 +- .../appeng/core/localization/GuiText.java | 7 +- .../appeng/me/cache/GridStorageCache.java | 609 +-- src/main/java/appeng/util/Platform.java | 3444 +++++++++-------- .../appliedenergistics2/lang/en_US.lang | 4 + .../appliedenergistics2/lang/zh_CN.lang | 4 + .../textures/guis/networkstatus.png | Bin 1792 -> 2721 bytes 9 files changed, 2290 insertions(+), 2151 deletions(-) diff --git a/src/main/java/appeng/api/networking/storage/IStorageGrid.java b/src/main/java/appeng/api/networking/storage/IStorageGrid.java index 930f72fc139..69980f25f50 100644 --- a/src/main/java/appeng/api/networking/storage/IStorageGrid.java +++ b/src/main/java/appeng/api/networking/storage/IStorageGrid.java @@ -13,6 +13,8 @@ package appeng.api.networking.storage; +import java.util.HashSet; + import appeng.api.networking.IGridCache; import appeng.api.networking.IGridHost; import appeng.api.networking.security.BaseActionSource; @@ -27,30 +29,32 @@ */ public interface IStorageGrid extends IGridCache, IStorageMonitorable { - /** - * Used to inform the network of alterations to the storage system that fall outside of the standard Network - * operations, Examples, ME Chest inputs from the world, or a Storage Bus detecting modifications made to the chest - * by an outside force. - *

- * Expects the input to have either a negative or a positive stack size to correspond to the injection, or - * extraction operation. - * - * @param input injected items - */ - void postAlterationOfStoredItems(StorageChannel chan, Iterable input, BaseActionSource src); - - /** - * Used to add a cell provider to the storage system - *

- * THIS IT NOT FOR USE {@link IGridHost} THAT PROVIDE {@link ICellContainer} - those are automatically handled by - * the storage system. - * - * @param cc to be added cell provider - */ - void registerCellProvider(ICellProvider cc); - - /** - * remove a provider added with addCellContainer - */ - void unregisterCellProvider(ICellProvider cc); + /** + * Used to inform the network of alterations to the storage system that fall + * outside of the standard Network operations, Examples, ME Chest inputs from + * the world, or a Storage Bus detecting modifications made to the chest by an + * outside force. + *

+ * Expects the input to have either a negative or a positive stack size to + * correspond to the injection, or extraction operation. + * + * @param input injected items + */ + void postAlterationOfStoredItems(StorageChannel chan, Iterable input, BaseActionSource src); + + /** + * Used to add a cell provider to the storage system + *

+ * THIS IT NOT FOR USE {@link IGridHost} THAT PROVIDE {@link ICellContainer} - + * those are automatically handled by the storage system. + * + * @param cc to be added cell provider + */ + void registerCellProvider(ICellProvider cc); + + /** + * remove a provider added with addCellContainer + */ + void unregisterCellProvider(ICellProvider cc); + } diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index aaede798a18..c3fc05b6a7a 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -10,6 +10,7 @@ package appeng.client.gui.implementations; +import java.text.DecimalFormat; import java.util.List; import net.minecraft.client.gui.GuiButton; @@ -51,7 +52,7 @@ public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkToo this.setScrollBar(scrollbar); this.repo = new ItemRepo(scrollbar, this); - this.ySize = 153; + this.ySize = 183; this.xSize = 195; this.repo.setRowSize(5); } @@ -115,7 +116,7 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { @Override public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; - + final DecimalFormat df = new DecimalFormat("#.##"); this.fontRendererObj .drawString(GuiText.NetworkDetails.getLocal(), 8, 6, GuiColors.NetworkStatusDetails.getColor()); @@ -140,6 +141,26 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final 13, 143 - 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); + this.fontRendererObj.drawString( + GuiText.ByteTotal.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesTotal()), + 13, + 143, + GuiColors.NetworkStatusPowerUsageRate.getColor()); + this.fontRendererObj.drawString( + GuiText.ByteUsage.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesUsed()) + + " (" + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + "%)", + 13, + 143 + 10, + GuiColors.NetworkStatusPowerUsageRate.getColor()); + this.fontRendererObj.drawString( + GuiText.ByteFree.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesFree()) + + " (" + df.format(ns.getItemBytesFree() * 100d / ns.getItemBytesTotal()) + "%)", + 13, + 143 + 20, + GuiColors.NetworkStatusPowerUsageRate.getColor()); + + + final int sectionLength = 30; diff --git a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java index e612f9a3ee4..766ff75522b 100644 --- a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java +++ b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java @@ -11,6 +11,8 @@ package appeng.container.implementations; import java.io.IOException; +import java.util.HashSet; +import java.util.List; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -26,134 +28,186 @@ import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.storage.ICellInventory; +import appeng.api.storage.ICellInventoryHandler; +import appeng.api.storage.ICellProvider; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.container.AEBaseContainer; import appeng.container.guisync.GuiSync; import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.packets.PacketMEInventoryUpdate; +import appeng.me.cache.GridStorageCache; +import appeng.me.cache.NetworkMonitor; +import appeng.me.storage.CellInventoryHandler; +import appeng.me.storage.DriveWatcher; +import appeng.services.version.Channel; import appeng.util.Platform; import appeng.util.item.AEItemStack; public class ContainerNetworkStatus extends AEBaseContainer { - @GuiSync(0) - public long avgAddition; - - @GuiSync(1) - public long powerUsage; - - @GuiSync(2) - public long currentPower; - - @GuiSync(3) - public long maxPower; - - private IGrid network; - private int delay = 40; - - public ContainerNetworkStatus(final InventoryPlayer ip, final INetworkTool te) { - super(ip, null, null); - final IGridHost host = te.getGridHost(); - - if (host != null) { - this.findNode(host, ForgeDirection.UNKNOWN); - for (final ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { - this.findNode(host, d); - } - } - - if (this.network == null && Platform.isServer()) { - this.setValidContainer(false); - } - } - - private void findNode(final IGridHost host, final ForgeDirection d) { - if (this.network == null) { - final IGridNode node = host.getGridNode(d); - if (node != null) { - this.network = node.getGrid(); - } - } - } - - @Override - public void detectAndSendChanges() { - this.delay++; - if (Platform.isServer() && this.delay > 15 && this.network != null) { - this.delay = 0; - - final IEnergyGrid eg = this.network.getCache(IEnergyGrid.class); - if (eg != null) { - this.setAverageAddition((long) (100.0 * eg.getAvgPowerInjection())); - this.setPowerUsage((long) (100.0 * eg.getAvgPowerUsage())); - this.setCurrentPower((long) (100.0 * eg.getStoredPower())); - this.setMaxPower((long) (100.0 * eg.getMaxStoredPower())); - } - - try { - final PacketMEInventoryUpdate piu = new PacketMEInventoryUpdate(); - - for (final Class machineClass : this.network.getMachinesClasses()) { - final IItemList list = AEApi.instance().storage().createItemList(); - for (final IGridNode machine : this.network.getMachines(machineClass)) { - final IGridBlock blk = machine.getGridBlock(); - final ItemStack is = blk.getMachineRepresentation(); - if (is != null && is.getItem() != null) { - final IAEItemStack ais = AEItemStack.create(is); - ais.setStackSize(1); - ais.setCountRequestable( - (long) PowerMultiplier.CONFIG.multiply(blk.getIdlePowerUsage() * 100.0)); - list.add(ais); - } - } - - for (final IAEItemStack ais : list) { - piu.appendItem(ais); - } - } - - for (final Object c : this.crafters) { - if (c instanceof EntityPlayer) { - NetworkHandler.instance.sendTo(piu, (EntityPlayerMP) c); - } - } - } catch (final IOException e) { - // :P - } - } - super.detectAndSendChanges(); - } - - public long getCurrentPower() { - return this.currentPower; - } - - private void setCurrentPower(final long currentPower) { - this.currentPower = currentPower; - } - - public long getMaxPower() { - return this.maxPower; - } - - private void setMaxPower(final long maxPower) { - this.maxPower = maxPower; - } - - public long getAverageAddition() { - return this.avgAddition; - } - - private void setAverageAddition(final long avgAddition) { - this.avgAddition = avgAddition; - } - - public long getPowerUsage() { - return this.powerUsage; - } - - private void setPowerUsage(final long powerUsage) { - this.powerUsage = powerUsage; - } + @GuiSync(0) + public long avgAddition; + + @GuiSync(1) + public long powerUsage; + + @GuiSync(2) + public long currentPower; + + @GuiSync(3) + public long maxPower; + + @GuiSync(4) + public long itemBytesTotal; + + @GuiSync(5) + public long itemBytesUsed; + + @GuiSync(6) + public long itemBytesFree; + + private IGrid network; + private int delay = 40; + + public ContainerNetworkStatus(final InventoryPlayer ip, final INetworkTool te) { + super(ip, null, null); + final IGridHost host = te.getGridHost(); + + if (host != null) { + this.findNode(host, ForgeDirection.UNKNOWN); + for (final ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { + this.findNode(host, d); + } + } + + if (this.network == null && Platform.isServer()) { + this.setValidContainer(false); + } + } + + private void findNode(final IGridHost host, final ForgeDirection d) { + if (this.network == null) { + final IGridNode node = host.getGridNode(d); + if (node != null) { + this.network = node.getGrid(); + } + } + } + + @Override + public void detectAndSendChanges() { + this.delay++; + if (Platform.isServer() && this.delay > 15 && this.network != null) { + this.delay = 0; + + final IEnergyGrid eg = this.network.getCache(IEnergyGrid.class); + if (eg != null) { + this.setAverageAddition((long) (100.0 * eg.getAvgPowerInjection())); + this.setPowerUsage((long) (100.0 * eg.getAvgPowerUsage())); + this.setCurrentPower((long) (100.0 * eg.getStoredPower())); + this.setMaxPower((long) (100.0 * eg.getMaxStoredPower())); + } + + try { + final PacketMEInventoryUpdate piu = new PacketMEInventoryUpdate(); + + for (final Class machineClass : this.network.getMachinesClasses()) { + final IItemList list = AEApi.instance().storage().createItemList(); + for (final IGridNode machine : this.network.getMachines(machineClass)) { + final IGridBlock blk = machine.getGridBlock(); + final ItemStack is = blk.getMachineRepresentation(); + if (is != null && is.getItem() != null) { + final IAEItemStack ais = AEItemStack.create(is); + ais.setStackSize(1); + ais.setCountRequestable( + (long) PowerMultiplier.CONFIG.multiply(blk.getIdlePowerUsage() * 100.0)); + list.add(ais); + } + } + + for (final IAEItemStack ais : list) { + piu.appendItem(ais); + } + } + + for (final Object c : this.crafters) { + if (c instanceof EntityPlayer) { + NetworkHandler.instance.sendTo(piu, (EntityPlayerMP) c); + } + } + } catch (final IOException e) { + // :P + } + final GridStorageCache sg = this.network.getCache(IStorageGrid.class); + if (sg != null) { + this.setItemBytesTotal(sg.getItemBytesTotal()); + this.setItemBytesUsed(sg.getItemBytesUsed()); + this.setItemBytesFree(this.getItemBytesTotal() - this.getItemBytesUsed()); + } + } + super.detectAndSendChanges(); + } + + public long getCurrentPower() { + return this.currentPower; + } + + private void setCurrentPower(final long currentPower) { + this.currentPower = currentPower; + } + + public long getMaxPower() { + return this.maxPower; + } + + private void setMaxPower(final long maxPower) { + this.maxPower = maxPower; + } + + public long getAverageAddition() { + return this.avgAddition; + } + + private void setAverageAddition(final long avgAddition) { + this.avgAddition = avgAddition; + } + + public long getPowerUsage() { + return this.powerUsage; + } + + private void setPowerUsage(final long powerUsage) { + this.powerUsage = powerUsage; + } + + public long getItemBytesTotal() { + return this.itemBytesTotal; + } + + public long getItemBytesUsed() { + return this.itemBytesUsed; + } + + public long getItemBytesFree() { + return this.itemBytesFree; + } + + public void setItemBytesTotal(final long itemBytesTotal) { + this.itemBytesTotal = itemBytesTotal; + } + + public void setItemBytesUsed(final long itemBytesUsed) { + this.itemBytesUsed = itemBytesUsed; + } + + public void setItemBytesFree(final long itemBytesFree) { + this.itemBytesFree = itemBytesFree; + } } diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index d908e3514be..eae559d2f93 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -205,7 +205,12 @@ public enum GuiText { VoidCellTooltip, // If a thing is deprecated - Deprecated; + Deprecated, + + //mine + ByteTotal, + ByteUsage, + ByteFree; private final String root; diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index fb2f1316613..9416db69961 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -42,291 +42,336 @@ import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.me.helpers.GenericInterestManager; +import appeng.me.storage.CellInventoryHandler; +import appeng.me.storage.DriveWatcher; import appeng.me.storage.ItemWatcher; import appeng.me.storage.NetworkInventoryHandler; public class GridStorageCache implements IStorageGrid { - private final IGrid myGrid; - private final HashSet activeCellProviders = new HashSet<>(); - private final HashSet inactiveCellProviders = new HashSet<>(); - private final SetMultimap interests = HashMultimap.create(); - private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); - private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); - private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); - private final HashMap watchers = new HashMap<>(); - private NetworkInventoryHandler myItemNetwork; - private NetworkInventoryHandler myFluidNetwork; - - public GridStorageCache(final IGrid g) { - this.myGrid = g; - } - - @Override - public void onUpdateTick() { - this.itemMonitor.onTick(); - this.fluidMonitor.onTick(); - } - - @Override - public void removeNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.removeCellProvider(cc, tracker); - this.inactiveCellProviders.remove(cc); - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - tracker.applyChanges(); - } - - if (machine instanceof IStackWatcherHost) { - final IStackWatcher myWatcher = this.watchers.get(machine); - - if (myWatcher != null) { - myWatcher.clear(); - this.watchers.remove(machine); - } - } - } - - @Override - public void addNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - this.inactiveCellProviders.add(cc); - - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - if (node.isActive()) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.addCellProvider(cc, tracker); - tracker.applyChanges(); - } - } - - if (machine instanceof IStackWatcherHost swh) { - final ItemWatcher iw = new ItemWatcher(this, swh); - this.watchers.put(node, iw); - swh.updateWatcher(iw); - } - } - - @Override - public void onSplit(final IGridStorage storageB) {} - - @Override - public void onJoin(final IGridStorage storageB) {} - - @Override - public void populateGridStorage(final IGridStorage storage) {} - - private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.inactiveCellProviders.contains(cc)) { - this.inactiveCellProviders.remove(cc); - this.activeCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); - } - } - - return tracker; - } - - private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.activeCellProviders.contains(cc)) { - this.activeCellProviders.remove(cc); - this.inactiveCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); - } - } - - return tracker; - } - - @MENetworkEventSubscribe - public void cellUpdate(final MENetworkCellArrayUpdate ev) { - this.myItemNetwork = null; - this.myFluidNetwork = null; - - final LinkedList ll = new LinkedList(); - ll.addAll(this.inactiveCellProviders); - ll.addAll(this.activeCellProviders); - - final CellChangeTracker tracker = new CellChangeTracker(); - - for (final ICellProvider cc : ll) { - boolean active = true; - - if (cc instanceof IActionHost) { - final IGridNode node = ((IActionHost) cc).getActionableNode(); - active = node != null && node.isActive(); - } - - if (active) { - this.addCellProvider(cc, tracker); - } else { - this.removeCellProvider(cc, tracker); - } - } - - this.itemMonitor.forceUpdate(); - this.fluidMonitor.forceUpdate(); - - tracker.applyChanges(); - } - - private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, - final BaseActionSource src) { - switch (chan) { - case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); - case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); - default -> {} - } - } - - IMEInventoryHandler getItemInventoryHandler() { - if (this.myItemNetwork == null) { - this.buildNetworkStorage(StorageChannel.ITEMS); - } - return this.myItemNetwork; - } - - private void buildNetworkStorage(final StorageChannel chan) { - final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); - - switch (chan) { - case FLUIDS -> { - this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myFluidNetwork.addNewStorage(h); - } - } - } - case ITEMS -> { - this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myItemNetwork.addNewStorage(h); - } - } - } - default -> {} - } - } - - IMEInventoryHandler getFluidInventoryHandler() { - if (this.myFluidNetwork == null) { - this.buildNetworkStorage(StorageChannel.FLUIDS); - } - return this.myFluidNetwork; - } - - @Override - public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, - final BaseActionSource src) { - if (chan == StorageChannel.ITEMS) { - this.itemMonitor.postChange(true, (Iterable) input, src); - } else if (chan == StorageChannel.FLUIDS) { - this.fluidMonitor.postChange(true, (Iterable) input, src); - } - } - - @Override - public void registerCellProvider(final ICellProvider provider) { - this.inactiveCellProviders.add(provider); - this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); - } - - @Override - public void unregisterCellProvider(final ICellProvider provider) { - this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); - this.inactiveCellProviders.remove(provider); - } - - @Override - public IMEMonitor getItemInventory() { - return this.itemMonitor; - } - - @Override - public IMEMonitor getFluidInventory() { - return this.fluidMonitor; - } - - public GenericInterestManager getInterestManager() { - return this.interestManager; - } - - IGrid getGrid() { - return this.myGrid; - } - - private class CellChangeTrackerRecord { - - final StorageChannel channel; - final int up_or_down; - final IItemList list; - final BaseActionSource src; - - public CellChangeTrackerRecord(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.channel = channel; - this.up_or_down = i; - this.src = actionSrc; - - if (channel == StorageChannel.ITEMS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createItemList()); - } else if (channel == StorageChannel.FLUIDS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createFluidList()); - } else { - this.list = null; - } - } - - public void applyChanges() { - GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); - } - } - - private class CellChangeTracker { - - final List data = new LinkedList<>(); - - public void postChanges(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); - } - - public void applyChanges() { - for (final CellChangeTrackerRecord rec : this.data) { - rec.applyChanges(); - } - } - } + private final IGrid myGrid; + private final HashSet activeCellProviders = new HashSet<>(); + private final HashSet inactiveCellProviders = new HashSet<>(); + private final SetMultimap interests = HashMultimap.create(); + private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); + private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); + private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); + private final HashMap watchers = new HashMap<>(); + private NetworkInventoryHandler myItemNetwork; + private NetworkInventoryHandler myFluidNetwork; + + // mine + private long itemBytesTotal; + private long itemBytesUsed; + + public GridStorageCache(final IGrid g) { + this.myGrid = g; + } + + @Override + public void onUpdateTick() { + this.itemMonitor.onTick(); + this.fluidMonitor.onTick(); + + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + try { + for (ICellProvider icp : this.activeCellProviders) { + if (icp.getClass() == Class.forName("appeng.tile.storage.TileDrive")) { + // All Item Cell + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + if (((DriveWatcher) meih).getInternal().getClass() == Class + .forName("appeng.me.storage.VoidCellInventory")) { // exclude void cell and creative cell + continue; + } + if(((CellInventoryHandler) (((DriveWatcher) meih).getInternal())).getCellInv() != null) { + itemBytesTotal += ((CellInventoryHandler) (((DriveWatcher) meih).getInternal())) + .getCellInv().getTotalBytes(); + itemBytesUsed += ((CellInventoryHandler) (((DriveWatcher) meih).getInternal())) + .getCellInv().getUsedBytes(); + } + } + } + } + } catch (ClassNotFoundException e) { + // XD + } + } + + @Override + public void removeNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.removeCellProvider(cc, tracker); + this.inactiveCellProviders.remove(cc); + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + tracker.applyChanges(); + } + + if (machine instanceof IStackWatcherHost) { + final IStackWatcher myWatcher = this.watchers.get(machine); + + if (myWatcher != null) { + myWatcher.clear(); + this.watchers.remove(machine); + } + } + } + + @Override + public void addNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + this.inactiveCellProviders.add(cc); + + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + if (node.isActive()) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.addCellProvider(cc, tracker); + tracker.applyChanges(); + } + } + + if (machine instanceof IStackWatcherHost swh) { + final ItemWatcher iw = new ItemWatcher(this, swh); + this.watchers.put(node, iw); + swh.updateWatcher(iw); + } + } + + @Override + public void onSplit(final IGridStorage storageB) { + } + + @Override + public void onJoin(final IGridStorage storageB) { + } + + @Override + public void populateGridStorage(final IGridStorage storage) { + } + + private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.inactiveCellProviders.contains(cc)) { + this.inactiveCellProviders.remove(cc); + this.activeCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); + } + } + + return tracker; + } + + private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.activeCellProviders.contains(cc)) { + this.activeCellProviders.remove(cc); + this.inactiveCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); + } + } + + return tracker; + } + + @MENetworkEventSubscribe + public void cellUpdate(final MENetworkCellArrayUpdate ev) { + this.myItemNetwork = null; + this.myFluidNetwork = null; + + final LinkedList ll = new LinkedList(); + ll.addAll(this.inactiveCellProviders); + ll.addAll(this.activeCellProviders); + + final CellChangeTracker tracker = new CellChangeTracker(); + + for (final ICellProvider cc : ll) { + boolean active = true; + + if (cc instanceof IActionHost) { + final IGridNode node = ((IActionHost) cc).getActionableNode(); + active = node != null && node.isActive(); + } + + if (active) { + this.addCellProvider(cc, tracker); + } else { + this.removeCellProvider(cc, tracker); + } + } + + this.itemMonitor.forceUpdate(); + this.fluidMonitor.forceUpdate(); + + tracker.applyChanges(); + + } + + private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, + final BaseActionSource src) { + switch (chan) { + case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); + case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); + default -> { + } + } + } + + IMEInventoryHandler getItemInventoryHandler() { + if (this.myItemNetwork == null) { + this.buildNetworkStorage(StorageChannel.ITEMS); + } + return this.myItemNetwork; + } + + private void buildNetworkStorage(final StorageChannel chan) { + final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); + + switch (chan) { + case FLUIDS -> { + this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myFluidNetwork.addNewStorage(h); + } + } + } + case ITEMS -> { + this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myItemNetwork.addNewStorage(h); + } + } + } + default -> { + } + } + } + + IMEInventoryHandler getFluidInventoryHandler() { + if (this.myFluidNetwork == null) { + this.buildNetworkStorage(StorageChannel.FLUIDS); + } + return this.myFluidNetwork; + } + + @Override + public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, + final BaseActionSource src) { + if (chan == StorageChannel.ITEMS) { + this.itemMonitor.postChange(true, (Iterable) input, src); + } else if (chan == StorageChannel.FLUIDS) { + this.fluidMonitor.postChange(true, (Iterable) input, src); + } + } + + @Override + public void registerCellProvider(final ICellProvider provider) { + this.inactiveCellProviders.add(provider); + this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); + } + + @Override + public void unregisterCellProvider(final ICellProvider provider) { + this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); + this.inactiveCellProviders.remove(provider); + } + + @Override + public IMEMonitor getItemInventory() { + return this.itemMonitor; + } + + @Override + public IMEMonitor getFluidInventory() { + return this.fluidMonitor; + } + + public GenericInterestManager getInterestManager() { + return this.interestManager; + } + + IGrid getGrid() { + return this.myGrid; + } + + private class CellChangeTrackerRecord { + + final StorageChannel channel; + final int up_or_down; + final IItemList list; + final BaseActionSource src; + + public CellChangeTrackerRecord(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.channel = channel; + this.up_or_down = i; + this.src = actionSrc; + + if (channel == StorageChannel.ITEMS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createItemList()); + } else if (channel == StorageChannel.FLUIDS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createFluidList()); + } else { + this.list = null; + } + } + + public void applyChanges() { + GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); + } + } + + private class CellChangeTracker { + + final List data = new LinkedList<>(); + + public void postChanges(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); + } + + public void applyChanges() { + for (final CellChangeTrackerRecord rec : this.data) { + rec.applyChanges(); + } + } + } + + public long getItemBytesTotal() { + return this.itemBytesTotal; + } + + public long getItemBytesUsed() { + return this.itemBytesUsed; + } + } diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index a159de830a1..967897eef96 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -67,6 +67,7 @@ import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.oredict.OreDictionary; +import com.ibm.icu.text.NumberFormat; import com.mojang.authlib.GameProfile; import appeng.api.AEApi; @@ -142,1725 +143,1726 @@ */ public class Platform { - public static final Block AIR_BLOCK = Blocks.air; - - public static final int DEF_OFFSET = 16; - - /* - * random source, use it for item drop locations... - */ - private static final Random RANDOM_GENERATOR = new Random(); - private static final WeakHashMap FAKE_PLAYERS = new WeakHashMap<>(); - private static Field tagList; - private static Class playerInstance; - private static Method getOrCreateChunkWatcher; - private static Method sendToAllPlayersWatchingChunk; - private static GameProfile fakeProfile = new GameProfile( - UUID.fromString("839eb18c-50bc-400c-8291-9383f09763e7"), - "[AE2Player]"); - - public static Random getRandom() { - return RANDOM_GENERATOR; - } - - public static float getRandomFloat() { - return RANDOM_GENERATOR.nextFloat(); - } - - /** - * Seed a random number generator from a world seed and grid location. The grid can be any arbitrary set of - * coordinates, e.g. chunk position or block position. This method guarantees that for the same inputs (worldSeed, - * x, z) the same seed will be used. - * - * @param rng The generator to re-seed. - * @param worldSeed Global seed independent of the grid position - * @param x X location in the grid - * @param z Z location in the grid - */ - public static void seedFromGrid(final Random rng, final long worldSeed, final long x, final long z) { - rng.setSeed(worldSeed); - final long xSeed = rng.nextLong() >> 2 + 1L; - final long zSeed = rng.nextLong() >> 2 + 1L; - final long gridSeed = (xSeed * x + zSeed * z) ^ worldSeed; - rng.setSeed(gridSeed); - } - - /** - * This displays the value for encoded longs ( double *100 ) - * - * @param n to be formatted long value - * @param isRate if true it adds a /t to the formatted string - * @return formatted long value - */ - public static String formatPowerLong(final long n, final boolean isRate) { - double p = ((double) n) / 100; - - final PowerUnits displayUnits = AEConfig.instance.selectedPowerUnit(); - p = PowerUnits.AE.convertTo(displayUnits, p); - - String unitName = displayUnits.name(); - - if (displayUnits == PowerUnits.WA) { - unitName = "J"; - } - - if (displayUnits == PowerUnits.MK) { - unitName = "J"; - } - - final String[] preFixes = { "k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y" }; - String level = ""; - int offset = 0; - while (p > 1000 && offset < preFixes.length) { - p /= 1000; - level = preFixes[offset]; - offset++; - } - - final DecimalFormat df = new DecimalFormat("#.##"); - return df.format(p) + ' ' + level + unitName + (isRate ? "/t" : ""); - } - - public static ForgeDirection crossProduct(final ForgeDirection forward, final ForgeDirection up) { - final int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; - final int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; - final int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; - - return switch (west_x + west_y * 2 + west_z * 3) { - case 1 -> ForgeDirection.EAST; - case -1 -> ForgeDirection.WEST; - case 2 -> ForgeDirection.UP; - case -2 -> ForgeDirection.DOWN; - case 3 -> ForgeDirection.SOUTH; - case -3 -> ForgeDirection.NORTH; - default -> ForgeDirection.UNKNOWN; - }; - - } - - public static T rotateEnum(T ce, final boolean backwards, final EnumSet validOptions) { - do { - if (backwards) { - ce = prevEnum(ce); - } else { - ce = nextEnum(ce); - } - } while (!validOptions.contains(ce) || isNotValidSetting(ce)); - - return ce; - } - - /* - * Simple way to cycle an enum... - */ - private static T prevEnum(final T ce) { - final EnumSet valList = EnumSet.allOf(ce.getClass()); - - int pLoc = ce.ordinal() - 1; - if (pLoc < 0) { - pLoc = valList.size() - 1; - } - - if (pLoc < 0 || pLoc >= valList.size()) { - pLoc = 0; - } - - int pos = 0; - for (final Object g : valList) { - if (pos == pLoc) { - return (T) g; - } - pos++; - } - - return null; - } - - /* - * Simple way to cycle an enum... - */ - public static T nextEnum(final T ce) { - final EnumSet valList = EnumSet.allOf(ce.getClass()); - - int pLoc = ce.ordinal() + 1; - if (pLoc >= valList.size()) { - pLoc = 0; - } - - if (pLoc < 0 || pLoc >= valList.size()) { - pLoc = 0; - } - - int pos = 0; - for (final Object g : valList) { - if (pos == pLoc) { - return (T) g; - } - pos++; - } - - return null; - } - - private static boolean isNotValidSetting(final Enum e) { - if (e == SortOrder.INVTWEAKS && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.InvTweaks)) { - return true; - } - - if (e == SearchBoxMode.NEI_AUTOSEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI)) { - return true; - } - - return e == SearchBoxMode.NEI_MANUAL_SEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI); - } - - public static void openGUI(@Nonnull final EntityPlayer p, @Nullable final TileEntity tile, - @Nullable final ForgeDirection side, @Nonnull final GuiBridge type) { - if (isClient()) { - return; - } - - int x = (int) p.posX; - int y = (int) p.posY; - int z = (int) p.posZ; - if (tile != null) { - x = tile.xCoord; - y = tile.yCoord; - z = tile.zCoord; - } - - if ((type.getType().isItem() && tile == null) || type.hasPermissions(tile, x, y, z, side, p)) { - if (tile == null && type.getType() == GuiHostType.ITEM) { - p.openGui( - AppEng.instance(), - type.ordinal() << 5 | (1 << 4), - p.getEntityWorld(), - p.inventory.currentItem, - 0, - 0); - } else if (tile == null || type.getType() == GuiHostType.ITEM) { - p.openGui(AppEng.instance(), type.ordinal() << 5 | (1 << 3), p.getEntityWorld(), x, y, z); - } else { - p.openGui(AppEng.instance(), type.ordinal() << 5 | (side.ordinal()), tile.getWorldObj(), x, y, z); - } - } - } - - /* - * returns true if the code is on the client. - */ - public static boolean isClient() { - return FMLCommonHandler.instance().getEffectiveSide().isClient(); - } - - public static boolean hasPermissions(final DimensionalCoord dc, final EntityPlayer player) { - return dc.getWorld().canMineBlock(player, dc.x, dc.y, dc.z); - } - - /* - * Checks to see if a block is air? - */ - public static boolean isBlockAir(final World w, final int x, final int y, final int z) { - try { - return w.getBlock(x, y, z).isAir(w, x, y, z); - } catch (final Throwable e) { - return false; - } - } - - /* - * Lots of silliness to try and account for weird tag related junk, basically requires that two tags have at least - * something in their tags before it wasts its time comparing them. - */ - private static boolean sameStackStags(final ItemStack a, final ItemStack b) { - if (a == null && b == null) { - return true; - } - if (a == null || b == null) { - return false; - } - if (a == b) { - return true; - } - - final NBTTagCompound ta = a.getTagCompound(); - final NBTTagCompound tb = b.getTagCompound(); - if (ta == tb) { - return true; - } - - if ((ta == null && tb == null) || (ta != null && ta.hasNoTags() && tb == null) - || (tb != null && tb.hasNoTags() && ta == null) - || (ta != null && ta.hasNoTags() && tb != null && tb.hasNoTags())) { - return true; - } - - if ((ta == null && tb != null) || (ta != null && tb == null)) { - return false; - } - - // if both tags are shared this is easy... - if (AESharedNBT.isShared(ta) && AESharedNBT.isShared(tb)) { - return ta == tb; - } - - return NBTEqualityTest(ta, tb); - } - - /* - * recursive test for NBT Equality, this was faster then trying to compare / generate hashes, its also more reliable - * then the vanilla version which likes to fail when NBT Compound data changes order, it is pretty expensive - * performance wise, so try an use shared tag compounds as long as the system remains in AE. - */ - public static boolean NBTEqualityTest(final NBTBase left, final NBTBase right) { - // same type? - final byte id = left.getId(); - if (id == right.getId()) { - switch (id) { - case 10 -> { - final NBTTagCompound ctA = (NBTTagCompound) left; - final NBTTagCompound ctB = (NBTTagCompound) right; - - final Set cA = ctA.func_150296_c(); - final Set cB = ctB.func_150296_c(); - - if (cA.size() != cB.size()) { - return false; - } - - for (final String name : cA) { - final NBTBase tag = ctA.getTag(name); - final NBTBase aTag = ctB.getTag(name); - if (aTag == null) { - return false; - } - - if (!NBTEqualityTest(tag, aTag)) { - return false; - } - } - - return true; - } - case 9 -> // ) // A instanceof NBTTagList ) - { - final NBTTagList lA = (NBTTagList) left; - final NBTTagList lB = (NBTTagList) right; - if (lA.tagCount() != lB.tagCount()) { - return false; - } - - final List tag = tagList(lA); - final List aTag = tagList(lB); - if (tag.size() != aTag.size()) { - return false; - } - - for (int x = 0; x < tag.size(); x++) { - if (aTag.get(x) == null) { - return false; - } - - if (!NBTEqualityTest(tag.get(x), aTag.get(x))) { - return false; - } - } - - return true; - } - case 1 -> { // ( A instanceof NBTTagByte ) - return ((NBTBase.NBTPrimitive) left).func_150287_d() - == ((NBTBase.NBTPrimitive) right).func_150287_d(); - } - case 4 -> { // else if ( A instanceof NBTTagLong ) - return ((NBTBase.NBTPrimitive) left).func_150291_c() - == ((NBTBase.NBTPrimitive) right).func_150291_c(); - } - case 8 -> { // else if ( A instanceof NBTTagString ) - return ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()) - || ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()); - } - case 6 -> { // else if ( A instanceof NBTTagDouble ) - return ((NBTBase.NBTPrimitive) left).func_150286_g() - == ((NBTBase.NBTPrimitive) right).func_150286_g(); - } - case 5 -> { // else if ( A instanceof NBTTagFloat ) - return ((NBTBase.NBTPrimitive) left).func_150288_h() - == ((NBTBase.NBTPrimitive) right).func_150288_h(); - } - case 3 -> { // else if ( A instanceof NBTTagInt ) - return ((NBTBase.NBTPrimitive) left).func_150287_d() - == ((NBTBase.NBTPrimitive) right).func_150287_d(); - } - default -> { - return left.equals(right); - } - } - } - - return false; - } - - private static List tagList(final NBTTagList lB) { - if (tagList == null) { - try { - tagList = lB.getClass().getDeclaredField("tagList"); - } catch (final Throwable t) { - try { - tagList = lB.getClass().getDeclaredField("field_74747_a"); - } catch (final Throwable z) { - AELog.debug(t); - AELog.debug(z); - } - } - } - - try { - tagList.setAccessible(true); - return (List) tagList.get(lB); - } catch (final Throwable t) { - AELog.debug(t); - } - - return new ArrayList<>(); - } - - /* - * Orderless hash on NBT Data, used to work thought huge piles fast, but ignores the order just in case MC decided - * to change it... WHICH IS BAD... - */ - public static int NBTOrderlessHash(final NBTBase nbt) { - // same type? - int hash = 0; - final byte id = nbt.getId(); - hash += id; - switch (id) { - case 10 -> { - final NBTTagCompound ctA = (NBTTagCompound) nbt; - - final Set cA = ctA.func_150296_c(); - - for (final String name : cA) { - hash += name.hashCode() ^ NBTOrderlessHash(ctA.getTag(name)); - } - - return hash; - } - case 9 -> // ) // A instanceof NBTTagList ) - { - final NBTTagList lA = (NBTTagList) nbt; - hash += 9 * lA.tagCount(); - - final List l = tagList(lA); - for (int x = 0; x < l.size(); x++) { - hash += ((Integer) x).hashCode() ^ NBTOrderlessHash(l.get(x)); - } - - return hash; - } - case 1 -> { // ( A instanceof NBTTagByte ) - return hash + ((NBTBase.NBTPrimitive) nbt).func_150290_f(); - } - case 4 -> { // else if ( A instanceof NBTTagLong ) - return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150291_c(); - } - case 8 -> { // else if ( A instanceof NBTTagString ) - return hash + ((NBTTagString) nbt).func_150285_a_().hashCode(); - } - case 6 -> { // else if ( A instanceof NBTTagDouble ) - return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150286_g(); - } - case 5 -> { // else if ( A instanceof NBTTagFloat ) - return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150288_h(); - } - case 3 -> { // else if ( A instanceof NBTTagInt ) - return hash + ((NBTBase.NBTPrimitive) nbt).func_150287_d(); - } - default -> { - return hash; - } - } - } - - private static IRecipe lastUsedRecipe = null; - - /* - * The usual version of this returns an ItemStack, this version returns the recipe. - */ - public static IRecipe findMatchingRecipe(final InventoryCrafting inventoryCrafting, final World par2World) { - if (lastUsedRecipe != null && lastUsedRecipe.matches(inventoryCrafting, par2World)) return lastUsedRecipe; - - final CraftingManager cm = CraftingManager.getInstance(); - final List rl = cm.getRecipeList(); - - for (final IRecipe r : rl) { - if (r.matches(inventoryCrafting, par2World)) { - lastUsedRecipe = r; - return r; - } - } - - return null; - } - - public static ItemStack[] getBlockDrops(final World w, final int x, final int y, final int z) { - List out = new ArrayList<>(); - final Block which = w.getBlock(x, y, z); - - if (which != null) { - out = which.getDrops(w, x, y, z, w.getBlockMetadata(x, y, z), 0); - } - - if (out == null) { - return new ItemStack[0]; - } - return out.toArray(new ItemStack[0]); - } - - public static ForgeDirection cycleOrientations(final ForgeDirection dir, final boolean upAndDown) { - if (upAndDown) { - return switch (dir) { - case NORTH -> ForgeDirection.SOUTH; - case SOUTH -> ForgeDirection.EAST; - case EAST -> ForgeDirection.WEST; - case WEST -> ForgeDirection.NORTH; - case UP -> ForgeDirection.UP; - case DOWN -> ForgeDirection.DOWN; - case UNKNOWN -> ForgeDirection.UNKNOWN; - }; - } else { - return switch (dir) { - case UP -> ForgeDirection.DOWN; - case DOWN -> ForgeDirection.NORTH; - case NORTH -> ForgeDirection.SOUTH; - case SOUTH -> ForgeDirection.EAST; - case EAST -> ForgeDirection.WEST; - case WEST -> ForgeDirection.UP; - case UNKNOWN -> ForgeDirection.UNKNOWN; - }; - } - } - - /* - * Creates / or loads previous NBT Data on items, used for editing items owned by AE. - */ - public static NBTTagCompound openNbtData(final ItemStack i) { - NBTTagCompound compound = i.getTagCompound(); - - if (compound == null) { - i.setTagCompound(compound = new NBTTagCompound()); - } - - return compound; - } - - /* - * Generates Item entities in the world similar to how items are generally dropped. - */ - public static void spawnDrops(final World w, final int x, final int y, final int z, final List drops) { - if (isServer()) { - for (final ItemStack i : drops) { - if (i != null) { - if (i.stackSize > 0) { - final double offset_x = (getRandomInt() % 32 - 16) / 82; - final double offset_y = (getRandomInt() % 32 - 16) / 82; - final double offset_z = (getRandomInt() % 32 - 16) / 82; - final EntityItem ei = new EntityItem( - w, - 0.5 + offset_x + x, - 0.5 + offset_y + y, - 0.2 + offset_z + z, - i.copy()); - w.spawnEntityInWorld(ei); - } - } - } - } - } - - /* - * returns true if the code is on the server. - */ - public static boolean isServer() { - return FMLCommonHandler.instance().getEffectiveSide().isServer(); - } - - public static int getRandomInt() { - return Math.abs(RANDOM_GENERATOR.nextInt()); - } - - /* - * Utility function to get the full inventory for a Double Chest in the World. - */ - public static IInventory GetChestInv(final Object te) { - TileEntityChest teA = (TileEntityChest) te; - TileEntity teB = null; - final Block myBlockID = teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord); - - if (teA.getWorldObj().getBlock(teA.xCoord + 1, teA.yCoord, teA.zCoord) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord + 1, teA.yCoord, teA.zCoord); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } - } - - if (teB == null) { - if (teA.getWorldObj().getBlock(teA.xCoord - 1, teA.yCoord, teA.zCoord) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord - 1, teA.yCoord, teA.zCoord); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } else { - final TileEntityChest x = teA; - teA = (TileEntityChest) teB; - teB = x; - } - } - } - - if (teB == null) { - if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord + 1) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord + 1); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } - } - } - - if (teB == null) { - if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord - 1) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord - 1); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } else { - final TileEntityChest x = teA; - teA = (TileEntityChest) teB; - teB = x; - } - } - } - - if (teB == null) { - return teA; - } - - return new InventoryLargeChest("", teA, (IInventory) teB); - } - - public static boolean isModLoaded(final String modid) { - try { - // if this fails for some reason, try the other method. - return Loader.isModLoaded(modid); - } catch (final Throwable ignored) {} - - for (final ModContainer f : Loader.instance().getActiveModList()) { - if (f.getModId().equals(modid)) { - return true; - } - } - return false; - } - - public static ItemStack findMatchingRecipeOutput(final InventoryCrafting ic, final World worldObj) { - return CraftingManager.getInstance().findMatchingRecipe(ic, worldObj); - } - - @SideOnly(Side.CLIENT) - public static List getTooltip(final Object o) { - if (o == null) { - return new ArrayList<>(); - } - - ItemStack itemStack = null; - if (o instanceof AEItemStack ais) { - return ais.getToolTip(); - } else if (o instanceof ItemStack) { - itemStack = (ItemStack) o; - } else { - return new ArrayList<>(); - } - - try { - return itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } catch (final Exception errB) { - return new ArrayList<>(); - } - } - - public static String getModId(final IAEItemStack is) { - if (is == null) { - return "** Null"; - } - - final String n = ((AEItemStack) is).getModID(); - return n == null ? "** Null" : n; - } - - public static String getItemDisplayName(final Object o) { - if (o == null) { - return "** Null"; - } - - ItemStack itemStack = null; - if (o instanceof AEItemStack) { - final String n = ((AEItemStack) o).getDisplayName(); - return n == null ? "** Null" : n; - } else if (o instanceof ItemStack) { - itemStack = (ItemStack) o; - } else { - return "**Invalid Object"; - } - - try { - String name = itemStack.getDisplayName(); - if (name == null || name.isEmpty()) { - name = itemStack.getItem().getUnlocalizedName(itemStack); - } - return name == null ? "** Null" : name; - } catch (final Exception errA) { - try { - final String n = itemStack.getUnlocalizedName(); - return n == null ? "** Null" : n; - } catch (final Exception errB) { - return "** Exception"; - } - } - } - - public static boolean hasSpecialComparison(final IAEItemStack willAdd) { - if (willAdd == null) { - return false; - } - final IAETagCompound tag = willAdd.getTagCompound(); - return tag != null && tag.getSpecialComparison() != null; - } - - public static boolean hasSpecialComparison(final ItemStack willAdd) { - if (AESharedNBT.isShared(willAdd.getTagCompound())) { - if (((IAETagCompound) willAdd.getTagCompound()).getSpecialComparison() != null) { - return true; - } - } - return false; - } - - public static boolean isWrench(final EntityPlayer player, final ItemStack stack, final int x, final int y, - final int z) { - if (stack != null) { - Item itemWrench = stack.getItem(); - if (itemWrench instanceof IAEWrench wrench) { - return wrench.canWrench(stack, player, x, y, z); - } - - if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.CoFHWrench) - && itemWrench instanceof IToolHammer wrench) { - return wrench.isUsable(stack, player, x, y, z); - } - - if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.BuildCraftCore) - && itemWrench instanceof IToolWrench wrench) { - return wrench.canWrench(player, x, y, z); - } - } - return false; - } - - public static boolean isChargeable(final ItemStack i) { - if (i == null) { - return false; - } - final Item it = i.getItem(); - if (it instanceof IAEItemPowerStorage) { - return ((IAEItemPowerStorage) it).getPowerFlow(i) != AccessRestriction.READ; - } - return false; - } - - public static EntityPlayer getPlayer(final WorldServer w) { - if (w == null) { - throw new InvalidParameterException("World is null."); - } - - final EntityPlayer wrp = FAKE_PLAYERS.get(w); - if (wrp != null) { - return wrp; - } - - final EntityPlayer p = FakePlayerFactory.get(w, fakeProfile); - FAKE_PLAYERS.put(w, p); - return p; - } - - public static int MC2MEColor(final int color) { - switch (color) { - case 4: // "blue" - return 0; - case 0: // "black" - return 1; - case 15: // "white" - return 2; - case 3: // "brown" - return 3; - case 1: // "red" - return 4; - case 11: // "yellow" - return 5; - case 2: // "green" - return 6; - - case 5: // "purple" - case 6: // "cyan" - case 7: // "silver" - case 8: // "gray" - case 9: // "pink" - case 10: // "lime" - case 12: // "lightBlue" - case 13: // "magenta" - case 14: // "orange" - } - return -1; - } - - public static int findEmpty(final Object[] l) { - for (int x = 0; x < l.length; x++) { - if (l[x] == null) { - return x; - } - } - return -1; - } - - public static T pickRandom(final Collection outs) { - int index = RANDOM_GENERATOR.nextInt(outs.size()); - final Iterator i = outs.iterator(); - while (i.hasNext() && index > 0) { - index--; - i.next(); - } - index--; - if (i.hasNext()) { - return i.next(); - } - return null; // wtf? - } - - public static ForgeDirection rotateAround(final ForgeDirection forward, final ForgeDirection axis) { - if (axis == ForgeDirection.UNKNOWN || forward == ForgeDirection.UNKNOWN) { - return forward; - } - - switch (forward) { - case DOWN: - switch (axis) { - case DOWN -> { - return forward; - } - case UP -> { - return forward; - } - case NORTH -> { - return ForgeDirection.EAST; - } - case SOUTH -> { - return ForgeDirection.WEST; - } - case EAST -> { - return ForgeDirection.NORTH; - } - case WEST -> { - return ForgeDirection.SOUTH; - } - default -> {} - } - break; - case UP: - switch (axis) { - case NORTH -> { - return ForgeDirection.WEST; - } - case SOUTH -> { - return ForgeDirection.EAST; - } - case EAST -> { - return ForgeDirection.SOUTH; - } - case WEST -> { - return ForgeDirection.NORTH; - } - default -> {} - } - break; - case NORTH: - switch (axis) { - case UP -> { - return ForgeDirection.WEST; - } - case DOWN -> { - return ForgeDirection.EAST; - } - case EAST -> { - return ForgeDirection.UP; - } - case WEST -> { - return ForgeDirection.DOWN; - } - default -> {} - } - break; - case SOUTH: - switch (axis) { - case UP -> { - return ForgeDirection.EAST; - } - case DOWN -> { - return ForgeDirection.WEST; - } - case EAST -> { - return ForgeDirection.DOWN; - } - case WEST -> { - return ForgeDirection.UP; - } - default -> {} - } - break; - case EAST: - switch (axis) { - case UP -> { - return ForgeDirection.NORTH; - } - case DOWN -> { - return ForgeDirection.SOUTH; - } - case NORTH -> { - return ForgeDirection.UP; - } - case SOUTH -> { - return ForgeDirection.DOWN; - } - default -> {} - } - case WEST: - switch (axis) { - case UP -> { - return ForgeDirection.SOUTH; - } - case DOWN -> { - return ForgeDirection.NORTH; - } - case NORTH -> { - return ForgeDirection.DOWN; - } - case SOUTH -> { - return ForgeDirection.UP; - } - default -> {} - } - default: - break; - } - return forward; - } - - @SideOnly(Side.CLIENT) - public static String gui_localize(final String string) { - return StatCollector.translateToLocal(string); - } - - public static boolean isSameItemPrecise(@Nullable final ItemStack is, @Nullable final ItemStack filter) { - return isSameItem(is, filter) && sameStackStags(is, filter); - } - - public static boolean isSameItemFuzzy(final ItemStack a, final ItemStack b, final FuzzyMode mode) { - if (a == null && b == null) { - return true; - } - - if (a == null) { - return false; - } - - if (b == null) { - return false; - } - - /* - * if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! a.getHasSubtypes() && a.itemID == - * b.itemID ) { return (a.getItemDamage() > 0) == (b.getItemDamage() > 0); } - */ - - // test damageable items.. - if (a.getItem() != null && b.getItem() != null && a.getItem().isDamageable() && a.getItem() == b.getItem()) { - try { - if (mode == FuzzyMode.IGNORE_ALL) { - return true; - } else if (mode == FuzzyMode.PERCENT_99) { - return (a.getItemDamageForDisplay() > 1) == (b.getItemDamageForDisplay() > 1); - } else { - final float percentDamagedOfA = 1.0f - - (float) a.getItemDamageForDisplay() / (float) a.getMaxDamage(); - final float percentDamagedOfB = 1.0f - - (float) b.getItemDamageForDisplay() / (float) b.getMaxDamage(); - - return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); - } - } catch (final Throwable e) { - if (mode == FuzzyMode.IGNORE_ALL) { - return true; - } else if (mode == FuzzyMode.PERCENT_99) { - return (a.getItemDamage() > 1) == (b.getItemDamage() > 1); - } else { - final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage(); - final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage(); - - return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); - } - } - } - - final OreReference aOR = OreHelper.INSTANCE.isOre(a); - final OreReference bOR = OreHelper.INSTANCE.isOre(b); - - if (OreHelper.INSTANCE.sameOre(aOR, bOR)) { - return true; - } - - /* - * // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return OreID == getOreID( b ); if ( - * Mode != FuzzyMode.IGNORE_ALL ) { if ( a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a = - * Platform.getSharedItemStack( AEItemStack.create( a ) ); } if ( b.hasTagCompound() && !isShared( - * b.getTagCompound() ) ) { b = Platform.getSharedItemStack( AEItemStack.create( b ) ); } // test regular items - * with damage values and what not... if ( isShared( a.getTagCompound() ) && isShared( b.getTagCompound() ) && - * a.itemID == b.itemID ) { return ((AppEngSharedNBTTagCompound) a.getTagCompound()).compareFuzzyWithRegistry( - * (AppEngSharedNBTTagCompound) b.getTagCompound() ); } } - */ - - return a.isItemEqual(b); - } - - public static LookDirection getPlayerRay(final EntityPlayer player, final float eyeOffset) { - final float f = 1.0F; - final float f1 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * f; - final float f2 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * f; - final double d0 = player.prevPosX + (player.posX - player.prevPosX) * f; - final double d1 = eyeOffset; - final double d2 = player.prevPosZ + (player.posZ - player.prevPosZ) * f; - - final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); - final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); - final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); - final float f5 = -MathHelper.cos(-f1 * 0.017453292F); - final float f6 = MathHelper.sin(-f1 * 0.017453292F); - final float f7 = f4 * f5; - final float f8 = f3 * f5; - double d3 = 5.0D; - - if (player instanceof EntityPlayerMP) { - d3 = ((EntityPlayerMP) player).theItemInWorldManager.getBlockReachDistance(); - } - final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); - return new LookDirection(vec3, vec31); - } - - public static MovingObjectPosition rayTrace(final EntityPlayer p, final boolean hitBlocks, - final boolean hitEntities) { - final World w = p.getEntityWorld(); - - final float f = 1.0F; - float f1 = p.prevRotationPitch + (p.rotationPitch - p.prevRotationPitch) * f; - final float f2 = p.prevRotationYaw + (p.rotationYaw - p.prevRotationYaw) * f; - final double d0 = p.prevPosX + (p.posX - p.prevPosX) * f; - final double d1 = p.prevPosY + (p.posY - p.prevPosY) * f + 1.62D - p.yOffset; - final double d2 = p.prevPosZ + (p.posZ - p.prevPosZ) * f; - final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); - final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); - final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); - final float f5 = -MathHelper.cos(-f1 * 0.017453292F); - final float f6 = MathHelper.sin(-f1 * 0.017453292F); - final float f7 = f4 * f5; - final float f8 = f3 * f5; - final double d3 = 32.0D; - - final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); - - final AxisAlignedBB bb = AxisAlignedBB.getBoundingBox( - Math.min(vec3.xCoord, vec31.xCoord), - Math.min(vec3.yCoord, vec31.yCoord), - Math.min(vec3.zCoord, vec31.zCoord), - Math.max(vec3.xCoord, vec31.xCoord), - Math.max(vec3.yCoord, vec31.yCoord), - Math.max(vec3.zCoord, vec31.zCoord)).expand(16, 16, 16); - - Entity entity = null; - double closest = 9999999.0D; - if (hitEntities) { - final List list = w.getEntitiesWithinAABBExcludingEntity(p, bb); - - for (Object o : list) { - final Entity entity1 = (Entity) o; - - if (!entity1.isDead && entity1 != p && !(entity1 instanceof EntityItem)) { - if (entity1.isEntityAlive()) { - // prevent killing / flying of mounts. - if (entity1.riddenByEntity == p) { - continue; - } - - f1 = 0.3F; - final AxisAlignedBB boundingBox = entity1.boundingBox.expand(f1, f1, f1); - final MovingObjectPosition movingObjectPosition = boundingBox.calculateIntercept(vec3, vec31); - - if (movingObjectPosition != null) { - final double nd = vec3.squareDistanceTo(movingObjectPosition.hitVec); - - if (nd < closest) { - entity = entity1; - closest = nd; - } - } - } - } - } - } - - MovingObjectPosition pos = null; - Vec3 vec = null; - - if (hitBlocks) { - vec = Vec3.createVectorHelper(d0, d1, d2); - pos = w.rayTraceBlocks(vec3, vec31, true); - } - - if (entity != null && pos != null && pos.hitVec.squareDistanceTo(vec) > closest) { - pos = new MovingObjectPosition(entity); - } else if (entity != null && pos == null) { - pos = new MovingObjectPosition(entity); - } - - return pos; - } - - public static long nanoTime() { - // if ( Configuration.INSTANCE.enableNetworkProfiler ) - // return System.nanoTime(); - return 0; - } - - public static StackType poweredExtraction(final IEnergySource energy, - final IMEInventory cell, final StackType request, final BaseActionSource src) { - final StackType possible = cell.extractItems((StackType) request.copy(), Actionable.SIMULATE, src); - - long retrieved = 0; - if (possible != null) { - retrieved = possible.getStackSize(); - } - - final double availablePower = energy.extractAEPower(retrieved, Actionable.SIMULATE, PowerMultiplier.CONFIG); - - final long itemToExtract = Math.min((long) (availablePower + 0.9), retrieved); - - if (itemToExtract > 0) { - energy.extractAEPower(retrieved, Actionable.MODULATE, PowerMultiplier.CONFIG); - - possible.setStackSize(itemToExtract); - final StackType ret = cell.extractItems(possible, Actionable.MODULATE, src); - - if (ret != null && src.isPlayer()) { - Stats.ItemsExtracted.addToPlayer(((PlayerSource) src).player, (int) ret.getStackSize()); - } - - return ret; - } - - return null; - } - - public static StackType poweredInsert(final IEnergySource energy, - final IMEInventory cell, final StackType input, final BaseActionSource src) { - final StackType possible = cell.injectItems((StackType) input.copy(), Actionable.SIMULATE, src); - - long stored = input.getStackSize(); - if (possible != null) { - stored -= possible.getStackSize(); - } - long typeMultiplier = input instanceof IAEFluidStack ? 1000 : 1; - - final double availablePower = energy - .extractAEPower(Platform.ceilDiv(stored, typeMultiplier), Actionable.SIMULATE, PowerMultiplier.CONFIG); - - final long itemToAdd = Math.min((long) (availablePower * typeMultiplier + 0.9), stored); - - if (itemToAdd > 0) { - energy.extractAEPower( - Platform.ceilDiv(stored, typeMultiplier), - Actionable.MODULATE, - PowerMultiplier.CONFIG); - - if (itemToAdd < input.getStackSize()) { - final long original = input.getStackSize(); - final StackType split = (StackType) input.copy(); - split.decStackSize(itemToAdd); - input.setStackSize(itemToAdd); - split.add(cell.injectItems(input, Actionable.MODULATE, src)); - - if (src.isPlayer()) { - final long diff = original - split.getStackSize(); - Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); - } - - return split; - } - - final StackType ret = cell.injectItems(input, Actionable.MODULATE, src); - - if (src.isPlayer()) { - final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize(); - Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); - } - - return ret; - } - - return input; - } - - @SuppressWarnings("unchecked") - public static void postChanges(final IStorageGrid gs, final ItemStack removed, final ItemStack added, - final BaseActionSource src) { - final IItemList itemChanges = AEApi.instance().storage().createItemList(); - final IItemList fluidChanges = AEApi.instance().storage().createFluidList(); - IMEInventory myItems = null; - IMEInventory myFluids = null; - if (removed != null) { - myItems = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.ITEMS); - - if (myItems != null) { - for (final IAEItemStack is : myItems.getAvailableItems(itemChanges)) { - is.setStackSize(-is.getStackSize()); - } - } - - myFluids = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.FLUIDS); - - if (myFluids != null) { - for (final IAEFluidStack is : myFluids.getAvailableItems(fluidChanges)) { - is.setStackSize(-is.getStackSize()); - } - } - } - - if (added != null) { - myItems = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.ITEMS); - - if (myItems != null) { - myItems.getAvailableItems(itemChanges); - } - - myFluids = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.FLUIDS); - - if (myFluids != null) { - myFluids.getAvailableItems(fluidChanges); - } - } - if (myItems == null) { - gs.postAlterationOfStoredItems(StorageChannel.FLUIDS, fluidChanges, src); - } else { - gs.postAlterationOfStoredItems(StorageChannel.ITEMS, itemChanges, src); - } - } - - public static > void postListChanges(final IItemList before, final IItemList after, - final IMEMonitorHandlerReceiver meMonitorPassthrough, final BaseActionSource source) { - final LinkedList changes = new LinkedList<>(); - - for (final T is : before) { - is.setStackSize(-is.getStackSize()); - } - - for (final T is : after) { - before.add(is); - } - - for (final T is : before) { - if (is.getStackSize() != 0) { - changes.add(is); - } - } - - if (!changes.isEmpty()) { - meMonitorPassthrough.postChange(null, changes, source); - } - } - - public static int generateTileHash(final TileEntity target) { - if (target == null) { - return 0; - } - - int hash = target.hashCode(); - - if (target instanceof ITileStorageMonitorable) { - return 0; - } else if (target instanceof TileEntityChest chest) { - chest.checkForAdjacentChests(); - if (chest.adjacentChestZNeg != null) { - hash ^= chest.adjacentChestZNeg.hashCode(); - } else if (chest.adjacentChestZPos != null) { - hash ^= chest.adjacentChestZPos.hashCode(); - } else if (chest.adjacentChestXPos != null) { - hash ^= chest.adjacentChestXPos.hashCode(); - } else if (chest.adjacentChestXNeg != null) { - hash ^= chest.adjacentChestXNeg.hashCode(); - } - } else if (target instanceof IInventory) { - hash ^= ((IInventory) target).getSizeInventory(); - - if (target instanceof ISidedInventory) { - for (final ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { - - final int[] sides = ((ISidedInventory) target).getAccessibleSlotsFromSide(dir.ordinal()); - - if (sides == null) { - return 0; - } - - int offset = 0; - for (final int side : sides) { - final int c = (side << (offset % 8)) ^ (1 << dir.ordinal()); - offset++; - hash = c + (hash << 6) + (hash << 16) - hash; - } - } - } - } - - return hash; - } - - public static boolean securityCheck(final GridNode a, final GridNode b) { - if (a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1) { - return false; - } else if (a.getLastSecurityKey() == b.getLastSecurityKey()) { - return false; - } - - final boolean a_isSecure = isPowered(a.getGrid()) && a.getLastSecurityKey() != -1; - final boolean b_isSecure = isPowered(b.getGrid()) && b.getLastSecurityKey() != -1; - - if (AEConfig.instance.isFeatureEnabled(AEFeature.LogSecurityAudits)) { - AELog.info( - "Audit: " + a_isSecure - + " : " - + b_isSecure - + " @ " - + a.getLastSecurityKey() - + " vs " - + b.getLastSecurityKey() - + " & " - + a.getPlayerID() - + " vs " - + b.getPlayerID()); - } - - // can't do that son... - if (a_isSecure && b_isSecure) { - return true; - } - - if (!a_isSecure && b_isSecure) { - return checkPlayerPermissions(b.getGrid(), a.getPlayerID()); - } - - if (a_isSecure && !b_isSecure) { - return checkPlayerPermissions(a.getGrid(), b.getPlayerID()); - } - - return false; - } - - private static boolean isPowered(final IGrid grid) { - if (grid == null) { - return false; - } - - final IEnergyGrid eg = grid.getCache(IEnergyGrid.class); - return eg.isNetworkPowered(); - } - - private static boolean checkPlayerPermissions(final IGrid grid, final int playerID) { - if (grid == null) { - return false; - } - - final ISecurityGrid gs = grid.getCache(ISecurityGrid.class); - - if (gs == null) { - return false; - } - - if (!gs.isAvailable()) { - return false; - } - - return !gs.hasPermission(playerID, SecurityPermissions.BUILD); - } - - public static void configurePlayer(final EntityPlayer player, final ForgeDirection side, final TileEntity tile) { - player.yOffset = 1.8f; - - float yaw = 0.0f; - float pitch = 0.0f; - switch (side) { - case DOWN: - pitch = 90.0f; - player.yOffset = -1.8f; - break; - case EAST: - yaw = -90.0f; - break; - case NORTH: - yaw = 180.0f; - break; - case SOUTH: - yaw = 0.0f; - break; - case UNKNOWN: - break; - case UP: - pitch = 90.0f; - break; - case WEST: - yaw = 90.0f; - break; - } - - player.posX = tile.xCoord + 0.5; - player.posY = tile.yCoord + 0.5; - player.posZ = tile.zCoord + 0.5; - - player.rotationPitch = player.prevCameraPitch = player.cameraPitch = pitch; - player.rotationYaw = player.prevCameraYaw = player.cameraYaw = yaw; - } - - public static boolean canAccess(final AENetworkProxy gridProxy, final BaseActionSource src) { - try { - if (src.isPlayer()) { - return gridProxy.getSecurity().hasPermission(((PlayerSource) src).player, SecurityPermissions.BUILD); - } else if (src.isMachine()) { - final IActionHost te = ((MachineSource) src).via; - final IGridNode n = te.getActionableNode(); - if (n == null) { - return false; - } - - final int playerID = n.getPlayerID(); - return gridProxy.getSecurity().hasPermission(playerID, SecurityPermissions.BUILD); - } else { - return false; - } - } catch (final GridAccessException gae) { - return false; - } - } - - public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, - final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, - final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, - final IItemList items, final Actionable realForFake, - final IPartitionList filter) { - return extractItemsByRecipe( - energySrc, - mySrc, - src, - w, - r, - output, - ci, - providedTemplate, - slot, - items, - realForFake, - filter, - 1); - } - - public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, - final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, - final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, - final IItemList items, final Actionable realForFake, - final IPartitionList filter, int multiple) { - if (energySrc.extractAEPower(multiple, Actionable.SIMULATE, PowerMultiplier.CONFIG) > 0.9) { - if (providedTemplate == null) { - return null; - } - - final AEItemStack ae_req = AEItemStack.create(providedTemplate); - ae_req.setStackSize(multiple); - - if (filter == null || filter.isListed(ae_req)) { - final IAEItemStack ae_ext = src.extractItems(ae_req, realForFake, mySrc); - if (ae_ext != null) { - final ItemStack extracted = ae_ext.getItemStack(); - if (extracted != null) { - energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); - return extracted; - } - } - } - - final boolean checkFuzzy = ae_req.isOre() - || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE - || providedTemplate.hasTagCompound() - || providedTemplate.isItemStackDamageable(); - - if (items != null && checkFuzzy) { - for (final IAEItemStack x : items) { - final ItemStack sh = x.getItemStack(); - if ((Platform.isSameItemType(providedTemplate, sh) || ae_req.sameOre(x)) - && !Platform.isSameItem(sh, output)) { // Platform.isSameItemType( sh, providedTemplate ) - final ItemStack cp = Platform.cloneItemStack(sh); - cp.stackSize = 1; - ci.setInventorySlotContents(slot, cp); - if (r.matches(ci, w) && Platform.isSameItem(r.getCraftingResult(ci), output)) { - final IAEItemStack ax = x.copy(); - ax.setStackSize(multiple); - if (filter == null || filter.isListed(ax)) { - final IAEItemStack ex = src.extractItems(ax, realForFake, mySrc); - if (ex != null) { - energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); - return ex.getItemStack(); - } - } - } - ci.setInventorySlotContents(slot, providedTemplate); - } - } - } - } - return null; - } - - public static boolean isSameItemType(final ItemStack that, final ItemStack other) { - if (that != null && other != null && that.getItem() == other.getItem()) { - if (that.isItemStackDamageable()) { - return true; - } - return that.getItemDamage() == other.getItemDamage(); - } - return false; - } - - public static boolean isSameItem(@Nullable final ItemStack left, @Nullable final ItemStack right) { - return left != null && right != null && left.isItemEqual(right); - } - - public static ItemStack cloneItemStack(final ItemStack a) { - return a.copy(); - } - - public static ItemStack getContainerItem(final ItemStack stackInSlot) { - if (stackInSlot == null) { - return null; - } - - final Item i = stackInSlot.getItem(); - if (i == null || !i.hasContainerItem(stackInSlot)) { - if (stackInSlot.stackSize > 1) { - stackInSlot.stackSize--; - return stackInSlot; - } - return null; - } - - ItemStack ci = i.getContainerItem(stackInSlot.copy()); - if (ci != null && ci.isItemStackDamageable() && ci.getItemDamage() > ci.getMaxDamage()) { - ci = null; - } - - return ci; - } - - public static void notifyBlocksOfNeighbors(final World worldObj, final int xCoord, final int yCoord, - final int zCoord) { - if (!worldObj.isRemote) { - TickHandler.INSTANCE.addCallable(worldObj, new BlockUpdate(xCoord, yCoord, zCoord)); - } - } - - public static boolean canRepair(final AEFeature type, final ItemStack a, final ItemStack b) { - if (b == null || a == null) { - return false; - } - - if (type == AEFeature.CertusQuartzTools) { - final IItemDefinition certusQuartzCrystal = AEApi.instance().definitions().materials() - .certusQuartzCrystal(); - - return certusQuartzCrystal.isSameAs(b); - } - - if (type == AEFeature.NetherQuartzTools) { - return Items.quartz == b.getItem(); - } - - return false; - } - - public static Object findPreferred(final ItemStack[] is) { - final IParts parts = AEApi.instance().definitions().parts(); - - for (final ItemStack stack : is) { - if (parts.cableGlass().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableCovered().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableSmart().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableDense().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableDenseCovered().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableUltraDenseCovered().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableUltraDenseSmart().sameAs(AEColor.Transparent, stack)) { - return stack; - } - } - - return is; - } - - public static void sendChunk(final Chunk c, final int verticalBits) { - try { - final WorldServer ws = (WorldServer) c.worldObj; - final PlayerManager pm = ws.getPlayerManager(); - - if (getOrCreateChunkWatcher == null) { - getOrCreateChunkWatcher = ReflectionHelper.findMethod( - PlayerManager.class, - pm, - new String[] { "getOrCreateChunkWatcher", "func_72690_a" }, - int.class, - int.class, - boolean.class); - } - - if (getOrCreateChunkWatcher != null) { - final Object playerInstance = getOrCreateChunkWatcher.invoke(pm, c.xPosition, c.zPosition, false); - if (playerInstance != null) { - Platform.playerInstance = playerInstance.getClass(); - - if (sendToAllPlayersWatchingChunk == null) { - sendToAllPlayersWatchingChunk = ReflectionHelper.findMethod( - Platform.playerInstance, - playerInstance, - new String[] { "sendToAllPlayersWatchingChunk", "func_151251_a" }, - Packet.class); - } - - if (sendToAllPlayersWatchingChunk != null) { - sendToAllPlayersWatchingChunk - .invoke(playerInstance, new S21PacketChunkData(c, false, verticalBits)); - } - } - } - } catch (final Throwable t) { - AELog.debug(t); - } - } - - public static AxisAlignedBB getPrimaryBox(final ForgeDirection side, final int facadeThickness) { - switch (side) { - case DOWN -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, (facadeThickness) / 16.0, 1.0); - } - case EAST -> { - return AxisAlignedBB.getBoundingBox((16.0 - facadeThickness) / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0); - } - case NORTH -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, (facadeThickness) / 16.0); - } - case SOUTH -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, (16.0 - facadeThickness) / 16.0, 1.0, 1.0, 1.0); - } - case UP -> { - return AxisAlignedBB.getBoundingBox(0.0, (16.0 - facadeThickness) / 16.0, 0.0, 1.0, 1.0, 1.0); - } - case WEST -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, (facadeThickness) / 16.0, 1.0, 1.0); - } - default -> {} - } - return AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1); - } - - public static float getEyeOffset(final EntityPlayer player) { - assert player.worldObj.isRemote : "Valid only on client"; - return (float) (player.posY + player.getEyeHeight() - player.getDefaultEyeHeight()); - } - - public static void addStat(final int playerID, final Achievement achievement) { - final EntityPlayer p = AEApi.instance().registries().players().findPlayer(playerID); - if (p != null) { - p.addStat(achievement, 1); - } - } - - public static boolean isRecipePrioritized(final ItemStack what) { - final IMaterials materials = AEApi.instance().definitions().materials(); - - boolean isPurified = materials.purifiedCertusQuartzCrystal().isSameAs(what); - isPurified |= materials.purifiedFluixCrystal().isSameAs(what); - isPurified |= materials.purifiedNetherQuartzCrystal().isSameAs(what); - - return isPurified; - } - - public static ItemStack loadItemStackFromNBT(NBTTagCompound tagCompound) { - ItemStack stack = ItemStack.loadItemStackFromNBT(tagCompound); - if (stack != null) { - stack.stackSize = tagCompound.getInteger("Count"); - } - return stack; - } - - public static NBTTagCompound writeItemStackToNBT(ItemStack is, NBTTagCompound tagCompound) { - is.writeToNBT(tagCompound); - tagCompound.setInteger("Count", is.stackSize); - return tagCompound; - } - - public static IAEItemStack getAEStackInSlot(Slot slot) { - if (slot == null || !slot.getHasStack()) { - return null; - } - - if (slot instanceof SlotME) { - return ((SlotME) slot).getAEStack(); - } - - if (slot instanceof SlotFake) { - return ((SlotFake) slot).getAEStack(); - } - - return AEItemStack.create(slot.getStack()); - } - - /** - * @return (a divided by b) rounded up - */ - public static long ceilDiv(long a, long b) { - return Math.addExact(Math.addExact(a, b), -1) / b; - } + public static final Block AIR_BLOCK = Blocks.air; + + public static final int DEF_OFFSET = 16; + + /* + * random source, use it for item drop locations... + */ + private static final Random RANDOM_GENERATOR = new Random(); + private static final WeakHashMap FAKE_PLAYERS = new WeakHashMap<>(); + private static Field tagList; + private static Class playerInstance; + private static Method getOrCreateChunkWatcher; + private static Method sendToAllPlayersWatchingChunk; + private static GameProfile fakeProfile = new GameProfile(UUID.fromString("839eb18c-50bc-400c-8291-9383f09763e7"), + "[AE2Player]"); + + public static Random getRandom() { + return RANDOM_GENERATOR; + } + + public static float getRandomFloat() { + return RANDOM_GENERATOR.nextFloat(); + } + + /** + * Seed a random number generator from a world seed and grid location. The grid + * can be any arbitrary set of coordinates, e.g. chunk position or block + * position. This method guarantees that for the same inputs (worldSeed, x, z) + * the same seed will be used. + * + * @param rng The generator to re-seed. + * @param worldSeed Global seed independent of the grid position + * @param x X location in the grid + * @param z Z location in the grid + */ + public static void seedFromGrid(final Random rng, final long worldSeed, final long x, final long z) { + rng.setSeed(worldSeed); + final long xSeed = rng.nextLong() >> 2 + 1L; + final long zSeed = rng.nextLong() >> 2 + 1L; + final long gridSeed = (xSeed * x + zSeed * z) ^ worldSeed; + rng.setSeed(gridSeed); + } + + /** + * This displays the value for encoded longs ( double *100 ) + * + * @param n to be formatted long value + * @param isRate if true it adds a /t to the formatted string + * @return formatted long value + */ + public static String formatPowerLong(final long n, final boolean isRate) { + double p = ((double) n) / 100; + + final PowerUnits displayUnits = AEConfig.instance.selectedPowerUnit(); + p = PowerUnits.AE.convertTo(displayUnits, p); + + String unitName = displayUnits.name(); + + if (displayUnits == PowerUnits.WA) { + unitName = "J"; + } + + if (displayUnits == PowerUnits.MK) { + unitName = "J"; + } + + final String[] preFixes = { "k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y" }; + String level = ""; + int offset = 0; + while (p > 1000 && offset < preFixes.length) { + p /= 1000; + level = preFixes[offset]; + offset++; + } + + final DecimalFormat df = new DecimalFormat("#.##"); + return df.format(p) + ' ' + level + unitName + (isRate ? "/t" : ""); + } + + public static ForgeDirection crossProduct(final ForgeDirection forward, final ForgeDirection up) { + final int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; + final int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; + final int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; + + return switch (west_x + west_y * 2 + west_z * 3) { + case 1 -> ForgeDirection.EAST; + case -1 -> ForgeDirection.WEST; + case 2 -> ForgeDirection.UP; + case -2 -> ForgeDirection.DOWN; + case 3 -> ForgeDirection.SOUTH; + case -3 -> ForgeDirection.NORTH; + default -> ForgeDirection.UNKNOWN; + }; + + } + + public static T rotateEnum(T ce, final boolean backwards, final EnumSet validOptions) { + do { + if (backwards) { + ce = prevEnum(ce); + } else { + ce = nextEnum(ce); + } + } while (!validOptions.contains(ce) || isNotValidSetting(ce)); + + return ce; + } + + /* + * Simple way to cycle an enum... + */ + private static T prevEnum(final T ce) { + final EnumSet valList = EnumSet.allOf(ce.getClass()); + + int pLoc = ce.ordinal() - 1; + if (pLoc < 0) { + pLoc = valList.size() - 1; + } + + if (pLoc < 0 || pLoc >= valList.size()) { + pLoc = 0; + } + + int pos = 0; + for (final Object g : valList) { + if (pos == pLoc) { + return (T) g; + } + pos++; + } + + return null; + } + + /* + * Simple way to cycle an enum... + */ + public static T nextEnum(final T ce) { + final EnumSet valList = EnumSet.allOf(ce.getClass()); + + int pLoc = ce.ordinal() + 1; + if (pLoc >= valList.size()) { + pLoc = 0; + } + + if (pLoc < 0 || pLoc >= valList.size()) { + pLoc = 0; + } + + int pos = 0; + for (final Object g : valList) { + if (pos == pLoc) { + return (T) g; + } + pos++; + } + + return null; + } + + private static boolean isNotValidSetting(final Enum e) { + if (e == SortOrder.INVTWEAKS && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.InvTweaks)) { + return true; + } + + if (e == SearchBoxMode.NEI_AUTOSEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI)) { + return true; + } + + return e == SearchBoxMode.NEI_MANUAL_SEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI); + } + + public static void openGUI(@Nonnull final EntityPlayer p, @Nullable final TileEntity tile, + @Nullable final ForgeDirection side, @Nonnull final GuiBridge type) { + if (isClient()) { + return; + } + + int x = (int) p.posX; + int y = (int) p.posY; + int z = (int) p.posZ; + if (tile != null) { + x = tile.xCoord; + y = tile.yCoord; + z = tile.zCoord; + } + + if ((type.getType().isItem() && tile == null) || type.hasPermissions(tile, x, y, z, side, p)) { + if (tile == null && type.getType() == GuiHostType.ITEM) { + p.openGui(AppEng.instance(), type.ordinal() << 5 | (1 << 4), p.getEntityWorld(), + p.inventory.currentItem, 0, 0); + } else if (tile == null || type.getType() == GuiHostType.ITEM) { + p.openGui(AppEng.instance(), type.ordinal() << 5 | (1 << 3), p.getEntityWorld(), x, y, z); + } else { + p.openGui(AppEng.instance(), type.ordinal() << 5 | (side.ordinal()), tile.getWorldObj(), x, y, z); + } + } + } + + /* + * returns true if the code is on the client. + */ + public static boolean isClient() { + return FMLCommonHandler.instance().getEffectiveSide().isClient(); + } + + public static boolean hasPermissions(final DimensionalCoord dc, final EntityPlayer player) { + return dc.getWorld().canMineBlock(player, dc.x, dc.y, dc.z); + } + + /* + * Checks to see if a block is air? + */ + public static boolean isBlockAir(final World w, final int x, final int y, final int z) { + try { + return w.getBlock(x, y, z).isAir(w, x, y, z); + } catch (final Throwable e) { + return false; + } + } + + /* + * Lots of silliness to try and account for weird tag related junk, basically + * requires that two tags have at least something in their tags before it wasts + * its time comparing them. + */ + private static boolean sameStackStags(final ItemStack a, final ItemStack b) { + if (a == null && b == null) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a == b) { + return true; + } + + final NBTTagCompound ta = a.getTagCompound(); + final NBTTagCompound tb = b.getTagCompound(); + if (ta == tb) { + return true; + } + + if ((ta == null && tb == null) || (ta != null && ta.hasNoTags() && tb == null) + || (tb != null && tb.hasNoTags() && ta == null) + || (ta != null && ta.hasNoTags() && tb != null && tb.hasNoTags())) { + return true; + } + + if ((ta == null && tb != null) || (ta != null && tb == null)) { + return false; + } + + // if both tags are shared this is easy... + if (AESharedNBT.isShared(ta) && AESharedNBT.isShared(tb)) { + return ta == tb; + } + + return NBTEqualityTest(ta, tb); + } + + /* + * recursive test for NBT Equality, this was faster then trying to compare / + * generate hashes, its also more reliable then the vanilla version which likes + * to fail when NBT Compound data changes order, it is pretty expensive + * performance wise, so try an use shared tag compounds as long as the system + * remains in AE. + */ + public static boolean NBTEqualityTest(final NBTBase left, final NBTBase right) { + // same type? + final byte id = left.getId(); + if (id == right.getId()) { + switch (id) { + case 10 -> { + final NBTTagCompound ctA = (NBTTagCompound) left; + final NBTTagCompound ctB = (NBTTagCompound) right; + + final Set cA = ctA.func_150296_c(); + final Set cB = ctB.func_150296_c(); + + if (cA.size() != cB.size()) { + return false; + } + + for (final String name : cA) { + final NBTBase tag = ctA.getTag(name); + final NBTBase aTag = ctB.getTag(name); + if (aTag == null) { + return false; + } + + if (!NBTEqualityTest(tag, aTag)) { + return false; + } + } + + return true; + } + case 9 -> // ) // A instanceof NBTTagList ) + { + final NBTTagList lA = (NBTTagList) left; + final NBTTagList lB = (NBTTagList) right; + if (lA.tagCount() != lB.tagCount()) { + return false; + } + + final List tag = tagList(lA); + final List aTag = tagList(lB); + if (tag.size() != aTag.size()) { + return false; + } + + for (int x = 0; x < tag.size(); x++) { + if (aTag.get(x) == null) { + return false; + } + + if (!NBTEqualityTest(tag.get(x), aTag.get(x))) { + return false; + } + } + + return true; + } + case 1 -> { // ( A instanceof NBTTagByte ) + return ((NBTBase.NBTPrimitive) left).func_150287_d() == ((NBTBase.NBTPrimitive) right).func_150287_d(); + } + case 4 -> { // else if ( A instanceof NBTTagLong ) + return ((NBTBase.NBTPrimitive) left).func_150291_c() == ((NBTBase.NBTPrimitive) right).func_150291_c(); + } + case 8 -> { // else if ( A instanceof NBTTagString ) + return ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()) + || ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()); + } + case 6 -> { // else if ( A instanceof NBTTagDouble ) + return ((NBTBase.NBTPrimitive) left).func_150286_g() == ((NBTBase.NBTPrimitive) right).func_150286_g(); + } + case 5 -> { // else if ( A instanceof NBTTagFloat ) + return ((NBTBase.NBTPrimitive) left).func_150288_h() == ((NBTBase.NBTPrimitive) right).func_150288_h(); + } + case 3 -> { // else if ( A instanceof NBTTagInt ) + return ((NBTBase.NBTPrimitive) left).func_150287_d() == ((NBTBase.NBTPrimitive) right).func_150287_d(); + } + default -> { + return left.equals(right); + } + } + } + + return false; + } + + private static List tagList(final NBTTagList lB) { + if (tagList == null) { + try { + tagList = lB.getClass().getDeclaredField("tagList"); + } catch (final Throwable t) { + try { + tagList = lB.getClass().getDeclaredField("field_74747_a"); + } catch (final Throwable z) { + AELog.debug(t); + AELog.debug(z); + } + } + } + + try { + tagList.setAccessible(true); + return (List) tagList.get(lB); + } catch (final Throwable t) { + AELog.debug(t); + } + + return new ArrayList<>(); + } + + /* + * Orderless hash on NBT Data, used to work thought huge piles fast, but ignores + * the order just in case MC decided to change it... WHICH IS BAD... + */ + public static int NBTOrderlessHash(final NBTBase nbt) { + // same type? + int hash = 0; + final byte id = nbt.getId(); + hash += id; + switch (id) { + case 10 -> { + final NBTTagCompound ctA = (NBTTagCompound) nbt; + + final Set cA = ctA.func_150296_c(); + + for (final String name : cA) { + hash += name.hashCode() ^ NBTOrderlessHash(ctA.getTag(name)); + } + + return hash; + } + case 9 -> // ) // A instanceof NBTTagList ) + { + final NBTTagList lA = (NBTTagList) nbt; + hash += 9 * lA.tagCount(); + + final List l = tagList(lA); + for (int x = 0; x < l.size(); x++) { + hash += ((Integer) x).hashCode() ^ NBTOrderlessHash(l.get(x)); + } + + return hash; + } + case 1 -> { // ( A instanceof NBTTagByte ) + return hash + ((NBTBase.NBTPrimitive) nbt).func_150290_f(); + } + case 4 -> { // else if ( A instanceof NBTTagLong ) + return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150291_c(); + } + case 8 -> { // else if ( A instanceof NBTTagString ) + return hash + ((NBTTagString) nbt).func_150285_a_().hashCode(); + } + case 6 -> { // else if ( A instanceof NBTTagDouble ) + return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150286_g(); + } + case 5 -> { // else if ( A instanceof NBTTagFloat ) + return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150288_h(); + } + case 3 -> { // else if ( A instanceof NBTTagInt ) + return hash + ((NBTBase.NBTPrimitive) nbt).func_150287_d(); + } + default -> { + return hash; + } + } + } + + private static IRecipe lastUsedRecipe = null; + + /* + * The usual version of this returns an ItemStack, this version returns the + * recipe. + */ + public static IRecipe findMatchingRecipe(final InventoryCrafting inventoryCrafting, final World par2World) { + if (lastUsedRecipe != null && lastUsedRecipe.matches(inventoryCrafting, par2World)) + return lastUsedRecipe; + + final CraftingManager cm = CraftingManager.getInstance(); + final List rl = cm.getRecipeList(); + + for (final IRecipe r : rl) { + if (r.matches(inventoryCrafting, par2World)) { + lastUsedRecipe = r; + return r; + } + } + + return null; + } + + public static ItemStack[] getBlockDrops(final World w, final int x, final int y, final int z) { + List out = new ArrayList<>(); + final Block which = w.getBlock(x, y, z); + + if (which != null) { + out = which.getDrops(w, x, y, z, w.getBlockMetadata(x, y, z), 0); + } + + if (out == null) { + return new ItemStack[0]; + } + return out.toArray(new ItemStack[0]); + } + + public static ForgeDirection cycleOrientations(final ForgeDirection dir, final boolean upAndDown) { + if (upAndDown) { + return switch (dir) { + case NORTH -> ForgeDirection.SOUTH; + case SOUTH -> ForgeDirection.EAST; + case EAST -> ForgeDirection.WEST; + case WEST -> ForgeDirection.NORTH; + case UP -> ForgeDirection.UP; + case DOWN -> ForgeDirection.DOWN; + case UNKNOWN -> ForgeDirection.UNKNOWN; + }; + } else { + return switch (dir) { + case UP -> ForgeDirection.DOWN; + case DOWN -> ForgeDirection.NORTH; + case NORTH -> ForgeDirection.SOUTH; + case SOUTH -> ForgeDirection.EAST; + case EAST -> ForgeDirection.WEST; + case WEST -> ForgeDirection.UP; + case UNKNOWN -> ForgeDirection.UNKNOWN; + }; + } + } + + /* + * Creates / or loads previous NBT Data on items, used for editing items owned + * by AE. + */ + public static NBTTagCompound openNbtData(final ItemStack i) { + NBTTagCompound compound = i.getTagCompound(); + + if (compound == null) { + i.setTagCompound(compound = new NBTTagCompound()); + } + + return compound; + } + + /* + * Generates Item entities in the world similar to how items are generally + * dropped. + */ + public static void spawnDrops(final World w, final int x, final int y, final int z, final List drops) { + if (isServer()) { + for (final ItemStack i : drops) { + if (i != null) { + if (i.stackSize > 0) { + final double offset_x = (getRandomInt() % 32 - 16) / 82; + final double offset_y = (getRandomInt() % 32 - 16) / 82; + final double offset_z = (getRandomInt() % 32 - 16) / 82; + final EntityItem ei = new EntityItem(w, 0.5 + offset_x + x, 0.5 + offset_y + y, + 0.2 + offset_z + z, i.copy()); + w.spawnEntityInWorld(ei); + } + } + } + } + } + + /* + * returns true if the code is on the server. + */ + public static boolean isServer() { + return FMLCommonHandler.instance().getEffectiveSide().isServer(); + } + + public static int getRandomInt() { + return Math.abs(RANDOM_GENERATOR.nextInt()); + } + + /* + * Utility function to get the full inventory for a Double Chest in the World. + */ + public static IInventory GetChestInv(final Object te) { + TileEntityChest teA = (TileEntityChest) te; + TileEntity teB = null; + final Block myBlockID = teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord); + + if (teA.getWorldObj().getBlock(teA.xCoord + 1, teA.yCoord, teA.zCoord) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord + 1, teA.yCoord, teA.zCoord); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } + } + + if (teB == null) { + if (teA.getWorldObj().getBlock(teA.xCoord - 1, teA.yCoord, teA.zCoord) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord - 1, teA.yCoord, teA.zCoord); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } else { + final TileEntityChest x = teA; + teA = (TileEntityChest) teB; + teB = x; + } + } + } + + if (teB == null) { + if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord + 1) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord + 1); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } + } + } + + if (teB == null) { + if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord - 1) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord - 1); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } else { + final TileEntityChest x = teA; + teA = (TileEntityChest) teB; + teB = x; + } + } + } + + if (teB == null) { + return teA; + } + + return new InventoryLargeChest("", teA, (IInventory) teB); + } + + public static boolean isModLoaded(final String modid) { + try { + // if this fails for some reason, try the other method. + return Loader.isModLoaded(modid); + } catch (final Throwable ignored) { + } + + for (final ModContainer f : Loader.instance().getActiveModList()) { + if (f.getModId().equals(modid)) { + return true; + } + } + return false; + } + + public static ItemStack findMatchingRecipeOutput(final InventoryCrafting ic, final World worldObj) { + return CraftingManager.getInstance().findMatchingRecipe(ic, worldObj); + } + + @SideOnly(Side.CLIENT) + public static List getTooltip(final Object o) { + if (o == null) { + return new ArrayList<>(); + } + + ItemStack itemStack = null; + if (o instanceof AEItemStack ais) { + return ais.getToolTip(); + } else if (o instanceof ItemStack) { + itemStack = (ItemStack) o; + } else { + return new ArrayList<>(); + } + + try { + return itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } catch (final Exception errB) { + return new ArrayList<>(); + } + } + + public static String getModId(final IAEItemStack is) { + if (is == null) { + return "** Null"; + } + + final String n = ((AEItemStack) is).getModID(); + return n == null ? "** Null" : n; + } + + public static String getItemDisplayName(final Object o) { + if (o == null) { + return "** Null"; + } + + ItemStack itemStack = null; + if (o instanceof AEItemStack) { + final String n = ((AEItemStack) o).getDisplayName(); + return n == null ? "** Null" : n; + } else if (o instanceof ItemStack) { + itemStack = (ItemStack) o; + } else { + return "**Invalid Object"; + } + + try { + String name = itemStack.getDisplayName(); + if (name == null || name.isEmpty()) { + name = itemStack.getItem().getUnlocalizedName(itemStack); + } + return name == null ? "** Null" : name; + } catch (final Exception errA) { + try { + final String n = itemStack.getUnlocalizedName(); + return n == null ? "** Null" : n; + } catch (final Exception errB) { + return "** Exception"; + } + } + } + + public static boolean hasSpecialComparison(final IAEItemStack willAdd) { + if (willAdd == null) { + return false; + } + final IAETagCompound tag = willAdd.getTagCompound(); + return tag != null && tag.getSpecialComparison() != null; + } + + public static boolean hasSpecialComparison(final ItemStack willAdd) { + if (AESharedNBT.isShared(willAdd.getTagCompound())) { + if (((IAETagCompound) willAdd.getTagCompound()).getSpecialComparison() != null) { + return true; + } + } + return false; + } + + public static boolean isWrench(final EntityPlayer player, final ItemStack stack, final int x, final int y, + final int z) { + if (stack != null) { + Item itemWrench = stack.getItem(); + if (itemWrench instanceof IAEWrench wrench) { + return wrench.canWrench(stack, player, x, y, z); + } + + if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.CoFHWrench) + && itemWrench instanceof IToolHammer wrench) { + return wrench.isUsable(stack, player, x, y, z); + } + + if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.BuildCraftCore) + && itemWrench instanceof IToolWrench wrench) { + return wrench.canWrench(player, x, y, z); + } + } + return false; + } + + public static boolean isChargeable(final ItemStack i) { + if (i == null) { + return false; + } + final Item it = i.getItem(); + if (it instanceof IAEItemPowerStorage) { + return ((IAEItemPowerStorage) it).getPowerFlow(i) != AccessRestriction.READ; + } + return false; + } + + public static EntityPlayer getPlayer(final WorldServer w) { + if (w == null) { + throw new InvalidParameterException("World is null."); + } + + final EntityPlayer wrp = FAKE_PLAYERS.get(w); + if (wrp != null) { + return wrp; + } + + final EntityPlayer p = FakePlayerFactory.get(w, fakeProfile); + FAKE_PLAYERS.put(w, p); + return p; + } + + public static int MC2MEColor(final int color) { + switch (color) { + case 4: // "blue" + return 0; + case 0: // "black" + return 1; + case 15: // "white" + return 2; + case 3: // "brown" + return 3; + case 1: // "red" + return 4; + case 11: // "yellow" + return 5; + case 2: // "green" + return 6; + + case 5: // "purple" + case 6: // "cyan" + case 7: // "silver" + case 8: // "gray" + case 9: // "pink" + case 10: // "lime" + case 12: // "lightBlue" + case 13: // "magenta" + case 14: // "orange" + } + return -1; + } + + public static int findEmpty(final Object[] l) { + for (int x = 0; x < l.length; x++) { + if (l[x] == null) { + return x; + } + } + return -1; + } + + public static T pickRandom(final Collection outs) { + int index = RANDOM_GENERATOR.nextInt(outs.size()); + final Iterator i = outs.iterator(); + while (i.hasNext() && index > 0) { + index--; + i.next(); + } + index--; + if (i.hasNext()) { + return i.next(); + } + return null; // wtf? + } + + public static ForgeDirection rotateAround(final ForgeDirection forward, final ForgeDirection axis) { + if (axis == ForgeDirection.UNKNOWN || forward == ForgeDirection.UNKNOWN) { + return forward; + } + + switch (forward) { + case DOWN: + switch (axis) { + case DOWN -> { + return forward; + } + case UP -> { + return forward; + } + case NORTH -> { + return ForgeDirection.EAST; + } + case SOUTH -> { + return ForgeDirection.WEST; + } + case EAST -> { + return ForgeDirection.NORTH; + } + case WEST -> { + return ForgeDirection.SOUTH; + } + default -> { + } + } + break; + case UP: + switch (axis) { + case NORTH -> { + return ForgeDirection.WEST; + } + case SOUTH -> { + return ForgeDirection.EAST; + } + case EAST -> { + return ForgeDirection.SOUTH; + } + case WEST -> { + return ForgeDirection.NORTH; + } + default -> { + } + } + break; + case NORTH: + switch (axis) { + case UP -> { + return ForgeDirection.WEST; + } + case DOWN -> { + return ForgeDirection.EAST; + } + case EAST -> { + return ForgeDirection.UP; + } + case WEST -> { + return ForgeDirection.DOWN; + } + default -> { + } + } + break; + case SOUTH: + switch (axis) { + case UP -> { + return ForgeDirection.EAST; + } + case DOWN -> { + return ForgeDirection.WEST; + } + case EAST -> { + return ForgeDirection.DOWN; + } + case WEST -> { + return ForgeDirection.UP; + } + default -> { + } + } + break; + case EAST: + switch (axis) { + case UP -> { + return ForgeDirection.NORTH; + } + case DOWN -> { + return ForgeDirection.SOUTH; + } + case NORTH -> { + return ForgeDirection.UP; + } + case SOUTH -> { + return ForgeDirection.DOWN; + } + default -> { + } + } + case WEST: + switch (axis) { + case UP -> { + return ForgeDirection.SOUTH; + } + case DOWN -> { + return ForgeDirection.NORTH; + } + case NORTH -> { + return ForgeDirection.DOWN; + } + case SOUTH -> { + return ForgeDirection.UP; + } + default -> { + } + } + default: + break; + } + return forward; + } + + @SideOnly(Side.CLIENT) + public static String gui_localize(final String string) { + return StatCollector.translateToLocal(string); + } + + public static boolean isSameItemPrecise(@Nullable final ItemStack is, @Nullable final ItemStack filter) { + return isSameItem(is, filter) && sameStackStags(is, filter); + } + + public static boolean isSameItemFuzzy(final ItemStack a, final ItemStack b, final FuzzyMode mode) { + if (a == null && b == null) { + return true; + } + + if (a == null) { + return false; + } + + if (b == null) { + return false; + } + + /* + * if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! + * a.getHasSubtypes() && a.itemID == b.itemID ) { return (a.getItemDamage() > 0) + * == (b.getItemDamage() > 0); } + */ + + // test damageable items.. + if (a.getItem() != null && b.getItem() != null && a.getItem().isDamageable() && a.getItem() == b.getItem()) { + try { + if (mode == FuzzyMode.IGNORE_ALL) { + return true; + } else if (mode == FuzzyMode.PERCENT_99) { + return (a.getItemDamageForDisplay() > 1) == (b.getItemDamageForDisplay() > 1); + } else { + final float percentDamagedOfA = 1.0f + - (float) a.getItemDamageForDisplay() / (float) a.getMaxDamage(); + final float percentDamagedOfB = 1.0f + - (float) b.getItemDamageForDisplay() / (float) b.getMaxDamage(); + + return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); + } + } catch (final Throwable e) { + if (mode == FuzzyMode.IGNORE_ALL) { + return true; + } else if (mode == FuzzyMode.PERCENT_99) { + return (a.getItemDamage() > 1) == (b.getItemDamage() > 1); + } else { + final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage(); + final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage(); + + return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); + } + } + } + + final OreReference aOR = OreHelper.INSTANCE.isOre(a); + final OreReference bOR = OreHelper.INSTANCE.isOre(b); + + if (OreHelper.INSTANCE.sameOre(aOR, bOR)) { + return true; + } + + /* + * // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return + * OreID == getOreID( b ); if ( Mode != FuzzyMode.IGNORE_ALL ) { if ( + * a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a = + * Platform.getSharedItemStack( AEItemStack.create( a ) ); } if ( + * b.hasTagCompound() && !isShared( b.getTagCompound() ) ) { b = + * Platform.getSharedItemStack( AEItemStack.create( b ) ); } // test regular + * items with damage values and what not... if ( isShared( a.getTagCompound() ) + * && isShared( b.getTagCompound() ) && a.itemID == b.itemID ) { return + * ((AppEngSharedNBTTagCompound) a.getTagCompound()).compareFuzzyWithRegistry( + * (AppEngSharedNBTTagCompound) b.getTagCompound() ); } } + */ + + return a.isItemEqual(b); + } + + public static LookDirection getPlayerRay(final EntityPlayer player, final float eyeOffset) { + final float f = 1.0F; + final float f1 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * f; + final float f2 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * f; + final double d0 = player.prevPosX + (player.posX - player.prevPosX) * f; + final double d1 = eyeOffset; + final double d2 = player.prevPosZ + (player.posZ - player.prevPosZ) * f; + + final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); + final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); + final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); + final float f5 = -MathHelper.cos(-f1 * 0.017453292F); + final float f6 = MathHelper.sin(-f1 * 0.017453292F); + final float f7 = f4 * f5; + final float f8 = f3 * f5; + double d3 = 5.0D; + + if (player instanceof EntityPlayerMP) { + d3 = ((EntityPlayerMP) player).theItemInWorldManager.getBlockReachDistance(); + } + final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); + return new LookDirection(vec3, vec31); + } + + public static MovingObjectPosition rayTrace(final EntityPlayer p, final boolean hitBlocks, + final boolean hitEntities) { + final World w = p.getEntityWorld(); + + final float f = 1.0F; + float f1 = p.prevRotationPitch + (p.rotationPitch - p.prevRotationPitch) * f; + final float f2 = p.prevRotationYaw + (p.rotationYaw - p.prevRotationYaw) * f; + final double d0 = p.prevPosX + (p.posX - p.prevPosX) * f; + final double d1 = p.prevPosY + (p.posY - p.prevPosY) * f + 1.62D - p.yOffset; + final double d2 = p.prevPosZ + (p.posZ - p.prevPosZ) * f; + final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); + final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); + final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); + final float f5 = -MathHelper.cos(-f1 * 0.017453292F); + final float f6 = MathHelper.sin(-f1 * 0.017453292F); + final float f7 = f4 * f5; + final float f8 = f3 * f5; + final double d3 = 32.0D; + + final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); + + final AxisAlignedBB bb = AxisAlignedBB + .getBoundingBox(Math.min(vec3.xCoord, vec31.xCoord), Math.min(vec3.yCoord, vec31.yCoord), + Math.min(vec3.zCoord, vec31.zCoord), Math.max(vec3.xCoord, vec31.xCoord), + Math.max(vec3.yCoord, vec31.yCoord), Math.max(vec3.zCoord, vec31.zCoord)) + .expand(16, 16, 16); + + Entity entity = null; + double closest = 9999999.0D; + if (hitEntities) { + final List list = w.getEntitiesWithinAABBExcludingEntity(p, bb); + + for (Object o : list) { + final Entity entity1 = (Entity) o; + + if (!entity1.isDead && entity1 != p && !(entity1 instanceof EntityItem)) { + if (entity1.isEntityAlive()) { + // prevent killing / flying of mounts. + if (entity1.riddenByEntity == p) { + continue; + } + + f1 = 0.3F; + final AxisAlignedBB boundingBox = entity1.boundingBox.expand(f1, f1, f1); + final MovingObjectPosition movingObjectPosition = boundingBox.calculateIntercept(vec3, vec31); + + if (movingObjectPosition != null) { + final double nd = vec3.squareDistanceTo(movingObjectPosition.hitVec); + + if (nd < closest) { + entity = entity1; + closest = nd; + } + } + } + } + } + } + + MovingObjectPosition pos = null; + Vec3 vec = null; + + if (hitBlocks) { + vec = Vec3.createVectorHelper(d0, d1, d2); + pos = w.rayTraceBlocks(vec3, vec31, true); + } + + if (entity != null && pos != null && pos.hitVec.squareDistanceTo(vec) > closest) { + pos = new MovingObjectPosition(entity); + } else if (entity != null && pos == null) { + pos = new MovingObjectPosition(entity); + } + + return pos; + } + + public static long nanoTime() { + // if ( Configuration.INSTANCE.enableNetworkProfiler ) + // return System.nanoTime(); + return 0; + } + + public static StackType poweredExtraction(final IEnergySource energy, + final IMEInventory cell, final StackType request, final BaseActionSource src) { + final StackType possible = cell.extractItems((StackType) request.copy(), Actionable.SIMULATE, src); + + long retrieved = 0; + if (possible != null) { + retrieved = possible.getStackSize(); + } + + final double availablePower = energy.extractAEPower(retrieved, Actionable.SIMULATE, PowerMultiplier.CONFIG); + + final long itemToExtract = Math.min((long) (availablePower + 0.9), retrieved); + + if (itemToExtract > 0) { + energy.extractAEPower(retrieved, Actionable.MODULATE, PowerMultiplier.CONFIG); + + possible.setStackSize(itemToExtract); + final StackType ret = cell.extractItems(possible, Actionable.MODULATE, src); + + if (ret != null && src.isPlayer()) { + Stats.ItemsExtracted.addToPlayer(((PlayerSource) src).player, (int) ret.getStackSize()); + } + + return ret; + } + + return null; + } + + public static StackType poweredInsert(final IEnergySource energy, + final IMEInventory cell, final StackType input, final BaseActionSource src) { + final StackType possible = cell.injectItems((StackType) input.copy(), Actionable.SIMULATE, src); + + long stored = input.getStackSize(); + if (possible != null) { + stored -= possible.getStackSize(); + } + long typeMultiplier = input instanceof IAEFluidStack ? 1000 : 1; + + final double availablePower = energy.extractAEPower(Platform.ceilDiv(stored, typeMultiplier), + Actionable.SIMULATE, PowerMultiplier.CONFIG); + + final long itemToAdd = Math.min((long) (availablePower * typeMultiplier + 0.9), stored); + + if (itemToAdd > 0) { + energy.extractAEPower(Platform.ceilDiv(stored, typeMultiplier), Actionable.MODULATE, + PowerMultiplier.CONFIG); + + if (itemToAdd < input.getStackSize()) { + final long original = input.getStackSize(); + final StackType split = (StackType) input.copy(); + split.decStackSize(itemToAdd); + input.setStackSize(itemToAdd); + split.add(cell.injectItems(input, Actionable.MODULATE, src)); + + if (src.isPlayer()) { + final long diff = original - split.getStackSize(); + Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); + } + + return split; + } + + final StackType ret = cell.injectItems(input, Actionable.MODULATE, src); + + if (src.isPlayer()) { + final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize(); + Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); + } + + return ret; + } + + return input; + } + + @SuppressWarnings("unchecked") + public static void postChanges(final IStorageGrid gs, final ItemStack removed, final ItemStack added, + final BaseActionSource src) { + final IItemList itemChanges = AEApi.instance().storage().createItemList(); + final IItemList fluidChanges = AEApi.instance().storage().createFluidList(); + IMEInventory myItems = null; + IMEInventory myFluids = null; + if (removed != null) { + myItems = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.ITEMS); + + if (myItems != null) { + for (final IAEItemStack is : myItems.getAvailableItems(itemChanges)) { + is.setStackSize(-is.getStackSize()); + } + } + + myFluids = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.FLUIDS); + + if (myFluids != null) { + for (final IAEFluidStack is : myFluids.getAvailableItems(fluidChanges)) { + is.setStackSize(-is.getStackSize()); + } + } + } + + if (added != null) { + myItems = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.ITEMS); + + if (myItems != null) { + myItems.getAvailableItems(itemChanges); + } + + myFluids = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.FLUIDS); + + if (myFluids != null) { + myFluids.getAvailableItems(fluidChanges); + } + } + if (myItems == null) { + gs.postAlterationOfStoredItems(StorageChannel.FLUIDS, fluidChanges, src); + } else { + gs.postAlterationOfStoredItems(StorageChannel.ITEMS, itemChanges, src); + } + } + + public static > void postListChanges(final IItemList before, final IItemList after, + final IMEMonitorHandlerReceiver meMonitorPassthrough, final BaseActionSource source) { + final LinkedList changes = new LinkedList<>(); + + for (final T is : before) { + is.setStackSize(-is.getStackSize()); + } + + for (final T is : after) { + before.add(is); + } + + for (final T is : before) { + if (is.getStackSize() != 0) { + changes.add(is); + } + } + + if (!changes.isEmpty()) { + meMonitorPassthrough.postChange(null, changes, source); + } + } + + public static int generateTileHash(final TileEntity target) { + if (target == null) { + return 0; + } + + int hash = target.hashCode(); + + if (target instanceof ITileStorageMonitorable) { + return 0; + } else if (target instanceof TileEntityChest chest) { + chest.checkForAdjacentChests(); + if (chest.adjacentChestZNeg != null) { + hash ^= chest.adjacentChestZNeg.hashCode(); + } else if (chest.adjacentChestZPos != null) { + hash ^= chest.adjacentChestZPos.hashCode(); + } else if (chest.adjacentChestXPos != null) { + hash ^= chest.adjacentChestXPos.hashCode(); + } else if (chest.adjacentChestXNeg != null) { + hash ^= chest.adjacentChestXNeg.hashCode(); + } + } else if (target instanceof IInventory) { + hash ^= ((IInventory) target).getSizeInventory(); + + if (target instanceof ISidedInventory) { + for (final ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + + final int[] sides = ((ISidedInventory) target).getAccessibleSlotsFromSide(dir.ordinal()); + + if (sides == null) { + return 0; + } + + int offset = 0; + for (final int side : sides) { + final int c = (side << (offset % 8)) ^ (1 << dir.ordinal()); + offset++; + hash = c + (hash << 6) + (hash << 16) - hash; + } + } + } + } + + return hash; + } + + public static boolean securityCheck(final GridNode a, final GridNode b) { + if (a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1) { + return false; + } else if (a.getLastSecurityKey() == b.getLastSecurityKey()) { + return false; + } + + final boolean a_isSecure = isPowered(a.getGrid()) && a.getLastSecurityKey() != -1; + final boolean b_isSecure = isPowered(b.getGrid()) && b.getLastSecurityKey() != -1; + + if (AEConfig.instance.isFeatureEnabled(AEFeature.LogSecurityAudits)) { + AELog.info("Audit: " + a_isSecure + " : " + b_isSecure + " @ " + a.getLastSecurityKey() + " vs " + + b.getLastSecurityKey() + " & " + a.getPlayerID() + " vs " + b.getPlayerID()); + } + + // can't do that son... + if (a_isSecure && b_isSecure) { + return true; + } + + if (!a_isSecure && b_isSecure) { + return checkPlayerPermissions(b.getGrid(), a.getPlayerID()); + } + + if (a_isSecure && !b_isSecure) { + return checkPlayerPermissions(a.getGrid(), b.getPlayerID()); + } + + return false; + } + + private static boolean isPowered(final IGrid grid) { + if (grid == null) { + return false; + } + + final IEnergyGrid eg = grid.getCache(IEnergyGrid.class); + return eg.isNetworkPowered(); + } + + private static boolean checkPlayerPermissions(final IGrid grid, final int playerID) { + if (grid == null) { + return false; + } + + final ISecurityGrid gs = grid.getCache(ISecurityGrid.class); + + if (gs == null) { + return false; + } + + if (!gs.isAvailable()) { + return false; + } + + return !gs.hasPermission(playerID, SecurityPermissions.BUILD); + } + + public static void configurePlayer(final EntityPlayer player, final ForgeDirection side, final TileEntity tile) { + player.yOffset = 1.8f; + + float yaw = 0.0f; + float pitch = 0.0f; + switch (side) { + case DOWN: + pitch = 90.0f; + player.yOffset = -1.8f; + break; + case EAST: + yaw = -90.0f; + break; + case NORTH: + yaw = 180.0f; + break; + case SOUTH: + yaw = 0.0f; + break; + case UNKNOWN: + break; + case UP: + pitch = 90.0f; + break; + case WEST: + yaw = 90.0f; + break; + } + + player.posX = tile.xCoord + 0.5; + player.posY = tile.yCoord + 0.5; + player.posZ = tile.zCoord + 0.5; + + player.rotationPitch = player.prevCameraPitch = player.cameraPitch = pitch; + player.rotationYaw = player.prevCameraYaw = player.cameraYaw = yaw; + } + + public static boolean canAccess(final AENetworkProxy gridProxy, final BaseActionSource src) { + try { + if (src.isPlayer()) { + return gridProxy.getSecurity().hasPermission(((PlayerSource) src).player, SecurityPermissions.BUILD); + } else if (src.isMachine()) { + final IActionHost te = ((MachineSource) src).via; + final IGridNode n = te.getActionableNode(); + if (n == null) { + return false; + } + + final int playerID = n.getPlayerID(); + return gridProxy.getSecurity().hasPermission(playerID, SecurityPermissions.BUILD); + } else { + return false; + } + } catch (final GridAccessException gae) { + return false; + } + } + + public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, + final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, + final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, + final IItemList items, final Actionable realForFake, + final IPartitionList filter) { + return extractItemsByRecipe(energySrc, mySrc, src, w, r, output, ci, providedTemplate, slot, items, realForFake, + filter, 1); + } + + public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, + final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, + final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, + final IItemList items, final Actionable realForFake, + final IPartitionList filter, int multiple) { + if (energySrc.extractAEPower(multiple, Actionable.SIMULATE, PowerMultiplier.CONFIG) > 0.9) { + if (providedTemplate == null) { + return null; + } + + final AEItemStack ae_req = AEItemStack.create(providedTemplate); + ae_req.setStackSize(multiple); + + if (filter == null || filter.isListed(ae_req)) { + final IAEItemStack ae_ext = src.extractItems(ae_req, realForFake, mySrc); + if (ae_ext != null) { + final ItemStack extracted = ae_ext.getItemStack(); + if (extracted != null) { + energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); + return extracted; + } + } + } + + final boolean checkFuzzy = ae_req.isOre() + || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE + || providedTemplate.hasTagCompound() || providedTemplate.isItemStackDamageable(); + + if (items != null && checkFuzzy) { + for (final IAEItemStack x : items) { + final ItemStack sh = x.getItemStack(); + if ((Platform.isSameItemType(providedTemplate, sh) || ae_req.sameOre(x)) + && !Platform.isSameItem(sh, output)) { // Platform.isSameItemType( sh, providedTemplate ) + final ItemStack cp = Platform.cloneItemStack(sh); + cp.stackSize = 1; + ci.setInventorySlotContents(slot, cp); + if (r.matches(ci, w) && Platform.isSameItem(r.getCraftingResult(ci), output)) { + final IAEItemStack ax = x.copy(); + ax.setStackSize(multiple); + if (filter == null || filter.isListed(ax)) { + final IAEItemStack ex = src.extractItems(ax, realForFake, mySrc); + if (ex != null) { + energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); + return ex.getItemStack(); + } + } + } + ci.setInventorySlotContents(slot, providedTemplate); + } + } + } + } + return null; + } + + public static boolean isSameItemType(final ItemStack that, final ItemStack other) { + if (that != null && other != null && that.getItem() == other.getItem()) { + if (that.isItemStackDamageable()) { + return true; + } + return that.getItemDamage() == other.getItemDamage(); + } + return false; + } + + public static boolean isSameItem(@Nullable final ItemStack left, @Nullable final ItemStack right) { + return left != null && right != null && left.isItemEqual(right); + } + + public static ItemStack cloneItemStack(final ItemStack a) { + return a.copy(); + } + + public static ItemStack getContainerItem(final ItemStack stackInSlot) { + if (stackInSlot == null) { + return null; + } + + final Item i = stackInSlot.getItem(); + if (i == null || !i.hasContainerItem(stackInSlot)) { + if (stackInSlot.stackSize > 1) { + stackInSlot.stackSize--; + return stackInSlot; + } + return null; + } + + ItemStack ci = i.getContainerItem(stackInSlot.copy()); + if (ci != null && ci.isItemStackDamageable() && ci.getItemDamage() > ci.getMaxDamage()) { + ci = null; + } + + return ci; + } + + public static void notifyBlocksOfNeighbors(final World worldObj, final int xCoord, final int yCoord, + final int zCoord) { + if (!worldObj.isRemote) { + TickHandler.INSTANCE.addCallable(worldObj, new BlockUpdate(xCoord, yCoord, zCoord)); + } + } + + public static boolean canRepair(final AEFeature type, final ItemStack a, final ItemStack b) { + if (b == null || a == null) { + return false; + } + + if (type == AEFeature.CertusQuartzTools) { + final IItemDefinition certusQuartzCrystal = AEApi.instance().definitions().materials() + .certusQuartzCrystal(); + + return certusQuartzCrystal.isSameAs(b); + } + + if (type == AEFeature.NetherQuartzTools) { + return Items.quartz == b.getItem(); + } + + return false; + } + + public static Object findPreferred(final ItemStack[] is) { + final IParts parts = AEApi.instance().definitions().parts(); + + for (final ItemStack stack : is) { + if (parts.cableGlass().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableCovered().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableSmart().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableDense().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableDenseCovered().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableUltraDenseCovered().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableUltraDenseSmart().sameAs(AEColor.Transparent, stack)) { + return stack; + } + } + + return is; + } + + public static void sendChunk(final Chunk c, final int verticalBits) { + try { + final WorldServer ws = (WorldServer) c.worldObj; + final PlayerManager pm = ws.getPlayerManager(); + + if (getOrCreateChunkWatcher == null) { + getOrCreateChunkWatcher = ReflectionHelper.findMethod(PlayerManager.class, pm, + new String[] { "getOrCreateChunkWatcher", "func_72690_a" }, int.class, int.class, + boolean.class); + } + + if (getOrCreateChunkWatcher != null) { + final Object playerInstance = getOrCreateChunkWatcher.invoke(pm, c.xPosition, c.zPosition, false); + if (playerInstance != null) { + Platform.playerInstance = playerInstance.getClass(); + + if (sendToAllPlayersWatchingChunk == null) { + sendToAllPlayersWatchingChunk = ReflectionHelper.findMethod(Platform.playerInstance, + playerInstance, new String[] { "sendToAllPlayersWatchingChunk", "func_151251_a" }, + Packet.class); + } + + if (sendToAllPlayersWatchingChunk != null) { + sendToAllPlayersWatchingChunk.invoke(playerInstance, + new S21PacketChunkData(c, false, verticalBits)); + } + } + } + } catch (final Throwable t) { + AELog.debug(t); + } + } + + public static AxisAlignedBB getPrimaryBox(final ForgeDirection side, final int facadeThickness) { + switch (side) { + case DOWN -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, (facadeThickness) / 16.0, 1.0); + } + case EAST -> { + return AxisAlignedBB.getBoundingBox((16.0 - facadeThickness) / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0); + } + case NORTH -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, (facadeThickness) / 16.0); + } + case SOUTH -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, (16.0 - facadeThickness) / 16.0, 1.0, 1.0, 1.0); + } + case UP -> { + return AxisAlignedBB.getBoundingBox(0.0, (16.0 - facadeThickness) / 16.0, 0.0, 1.0, 1.0, 1.0); + } + case WEST -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, (facadeThickness) / 16.0, 1.0, 1.0); + } + default -> { + } + } + return AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1); + } + + public static float getEyeOffset(final EntityPlayer player) { + assert player.worldObj.isRemote : "Valid only on client"; + return (float) (player.posY + player.getEyeHeight() - player.getDefaultEyeHeight()); + } + + public static void addStat(final int playerID, final Achievement achievement) { + final EntityPlayer p = AEApi.instance().registries().players().findPlayer(playerID); + if (p != null) { + p.addStat(achievement, 1); + } + } + + public static boolean isRecipePrioritized(final ItemStack what) { + final IMaterials materials = AEApi.instance().definitions().materials(); + + boolean isPurified = materials.purifiedCertusQuartzCrystal().isSameAs(what); + isPurified |= materials.purifiedFluixCrystal().isSameAs(what); + isPurified |= materials.purifiedNetherQuartzCrystal().isSameAs(what); + + return isPurified; + } + + public static ItemStack loadItemStackFromNBT(NBTTagCompound tagCompound) { + ItemStack stack = ItemStack.loadItemStackFromNBT(tagCompound); + if (stack != null) { + stack.stackSize = tagCompound.getInteger("Count"); + } + return stack; + } + + public static NBTTagCompound writeItemStackToNBT(ItemStack is, NBTTagCompound tagCompound) { + is.writeToNBT(tagCompound); + tagCompound.setInteger("Count", is.stackSize); + return tagCompound; + } + + public static IAEItemStack getAEStackInSlot(Slot slot) { + if (slot == null || !slot.getHasStack()) { + return null; + } + + if (slot instanceof SlotME) { + return ((SlotME) slot).getAEStack(); + } + + if (slot instanceof SlotFake) { + return ((SlotFake) slot).getAEStack(); + } + + return AEItemStack.create(slot.getStack()); + } + + /** + * @return (a divided by b) rounded up + */ + public static long ceilDiv(long a, long b) { + return Math.addExact(Math.addExact(a, b), -1) / b; + } + + /** + * From bytes to K,M,G,T like + * + * @param n Bytes number + * @return String that like 1G or 1.4T + */ + public static String formatByteLong(final long n) { + int storageUnit = Long.toBinaryString(n).length() / 10; + final DecimalFormat df = new DecimalFormat("#.##"); + switch(storageUnit) { + case 6: + return df.format((double)n / 1152921504606846976d) + " EB"; + case 5: + return df.format((double)n / 1125899906842624d) + " PB"; + case 4: + return df.format((double)n / 1099511627776d) + " TB"; + case 3: + return df.format((double)n / 1073741824d) + " GB"; + case 2: + return df.format((double)n / 1048576d) + " MB"; + case 1: + return df.format((double)n / 1024d) + " kB"; + case 0: + return df.format((double) n) + " B"; + default: + return df.format((double) n) + " B"; + } + } } diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index a087d01e04c..feb44c80672 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -272,6 +272,10 @@ gui.appliedenergistics2.Nothing=Nothing gui.appliedenergistics2.VoidCellTooltip=Deletes §4everything§7 stored on it gui.appliedenergistics2.Deprecated=Deprecated, will be removed soon! +gui.appliedenergistics2.ByteTotal=Bytes Total +gui.appliedenergistics2.ByteUsage=Bytes Used +gui.appliedenergistics2.ByteFree=Bytes Free + # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 gui.color.appliedenergistics2.SearchboxUnfocused=00000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 671b912f32e..156fedaada6 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -265,6 +265,10 @@ gui.appliedenergistics2.HoldShiftClick_HIGHLIGHT_INTERFACE=shift点击,高亮ME gui.appliedenergistics2.VoidCellTooltip=删除§任何§7存储在里面的物品 gui.appliedenergistics2.Nothing=无 +gui.appliedenergistics2.ByteTotal=所有字节 +gui.appliedenergistics2.ByteUsage=已用字节 +gui.appliedenergistics2.ByteFree=剩余字节 + # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 gui.color.appliedenergistics2.SearchboxUnfocused=00000000 diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png b/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png index c3b8650aefa2966a95a9e08f5972db8f6e9d8d43..b1f38e0c21798ed6a8940ad7893f5109e8b21cf5 100644 GIT binary patch literal 2721 zcmd^BeN5bB81E@r*bI<36XQ&@b}<2=*N?kn*N$UhcL=Bl1W+JuX79CckA}Opwmq(} z2+SDC5)Cm?2+79&n8}QqWzmFf0rU?f{Nd0n7~O&h1|2RqCjsX+=k)D;?L&rSiHXt6 zd+FQ0zxR25&+~hpx7}Y`U6HeC%O(uNa;ho=br|MAQwNs40bO?K??~vfQLAh=Ff8{I z`|o(GF!x~$+fXkzG?`7oXLv!4I)SK$pwo(K2#sMSJ1h+dt~eEl5zf+#m!iEC<06@2-c9o?i>H1B@}`Rt zUl({XS&C&zgdmM}#RL|q7+cd80?-h2SujTZF|rZda8I6$cl1~WcZy=2a$TFnIJ*$|3`adBQ32i-tO z?+>U#%oaDjUqt(9R+JdG#FE>XkVG=T&5~YE2$F#DupUVg81}~g8eK-s1tNEC2Q|Ts z2-8-|P(%h&&q%e%P7qGbB66u6=6Y$CP6v ziNfT8U^kqP5bR2WB9VG5ucFBMGMY3SZ-L0@8s(RS8LDK)fey>UNWJw`ICUrf254KG z{rc)@RrY`Fh`VH;O0LiXlrThRI7Qg;B-BkxL*1@gV(q4rF%3t@tv$`0^XMk?rhp1E zt)utAv(Fv=5X0_WsS1=eSO+egIUSwa^Fa6M#dnv*ZYhVVE7<$pXrb6^6)j`g`Q?tR z*XOn`JiZ?`fAz*6HADSZLXZB?T-tT^*Kh8(uC1JWu;!6Icy{5v>@P}Q8?QO@OUJ>D zv%fo+pTMSvX4EZKcwxC+lAQgY{`lMA@Mi1s)t>P@GVgfYalP>#4E&>`_jsGt+1c64 z&Gmd4J2<~|d2(p>q;r<9o|(i>of;V#xpo09<@St4rZ3H0itX+??>#bgesccJ_N;E& z@!ucECZ6B^{vzKq_N`CacWCJ7;(_WTdwZ8YAAYENe#tvMG&)iA^VF{Xu2(Ct?9Ko7 z@xf;c%cB)1h9?FFVDq_-(W`#^9FY13ng<65fAZb;_4xPtz?BoZ`U{6vI{OReKI$77 tcrXGey{~s9>y`h5-YCXnd1Dh#`3oM)U$Q?UtIDebM|bXd`A=K!G=Bg9 literal 1792 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6&2?&#~tz_78O`%fY(kk47* z5n0T@z_%TQ8D;vTfszbTC9V-A!TD(=<%vb93;~Imc_n&&t|1C##(JiDhKBB+oy-{+ z*lIjo978JN-d+h@6?>D{HSqf>-IZZGxT>atYaE%Xa2Iclevl`~J+H zf2sMSzWqbj%HR9#8q5FMvF>^P`}_Oz{RiF$|C!Y6vHr{T`1;VFe08;a?|=S%`TNJ$ zIJN@}FCOwVFkUz;$-umz-I#&Rfj^yrr$O!|@Os(yOone)5*Nv< zOESco@AYNgu$)i$uf<7*7rS2ON;TM)&UkU$lg;6}Z~kS5H!Baj*!vkV?8+OpYBT^x zlf|IRSAQ*KVs2GU{|hW6*qIe-pAB#cxA^bRAM@oKuJ9}Ez4HG3gUrW?OU}pL`?ub| z!T$J!I8beZ3?9sX{QUgEExn!q}afx*+&&t;ucLK6VEQQfWp From 2fdbe1421ca5bc93c24e319e87b3a37aa4f565ea Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Tue, 31 Oct 2023 18:11:00 +0800 Subject: [PATCH 02/34] Add network bytes infomation for network status gui --- .../api/networking/storage/IStorageGrid.java | 55 +- .../gui/implementations/GuiNetworkStatus.java | 19 +- .../ContainerNetworkStatus.java | 329 +- .../appeng/core/localization/GuiText.java | 10 +- .../appeng/me/cache/GridStorageCache.java | 645 ++- src/main/java/appeng/util/Platform.java | 3473 +++++++++-------- 6 files changed, 2271 insertions(+), 2260 deletions(-) diff --git a/src/main/java/appeng/api/networking/storage/IStorageGrid.java b/src/main/java/appeng/api/networking/storage/IStorageGrid.java index 69980f25f50..cb6dc7d1133 100644 --- a/src/main/java/appeng/api/networking/storage/IStorageGrid.java +++ b/src/main/java/appeng/api/networking/storage/IStorageGrid.java @@ -13,8 +13,6 @@ package appeng.api.networking.storage; -import java.util.HashSet; - import appeng.api.networking.IGridCache; import appeng.api.networking.IGridHost; import appeng.api.networking.security.BaseActionSource; @@ -29,32 +27,31 @@ */ public interface IStorageGrid extends IGridCache, IStorageMonitorable { - /** - * Used to inform the network of alterations to the storage system that fall - * outside of the standard Network operations, Examples, ME Chest inputs from - * the world, or a Storage Bus detecting modifications made to the chest by an - * outside force. - *

- * Expects the input to have either a negative or a positive stack size to - * correspond to the injection, or extraction operation. - * - * @param input injected items - */ - void postAlterationOfStoredItems(StorageChannel chan, Iterable input, BaseActionSource src); - - /** - * Used to add a cell provider to the storage system - *

- * THIS IT NOT FOR USE {@link IGridHost} THAT PROVIDE {@link ICellContainer} - - * those are automatically handled by the storage system. - * - * @param cc to be added cell provider - */ - void registerCellProvider(ICellProvider cc); - - /** - * remove a provider added with addCellContainer - */ - void unregisterCellProvider(ICellProvider cc); + /** + * Used to inform the network of alterations to the storage system that fall outside of the standard Network + * operations, Examples, ME Chest inputs from the world, or a Storage Bus detecting modifications made to the chest + * by an outside force. + *

+ * Expects the input to have either a negative or a positive stack size to correspond to the injection, or + * extraction operation. + * + * @param input injected items + */ + void postAlterationOfStoredItems(StorageChannel chan, Iterable input, BaseActionSource src); + + /** + * Used to add a cell provider to the storage system + *

+ * THIS IT NOT FOR USE {@link IGridHost} THAT PROVIDE {@link ICellContainer} - those are automatically handled by + * the storage system. + * + * @param cc to be added cell provider + */ + void registerCellProvider(ICellProvider cc); + + /** + * remove a provider added with addCellContainer + */ + void unregisterCellProvider(ICellProvider cc); } diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index c3fc05b6a7a..c0475eab8e8 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -142,25 +142,28 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final 143 - 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); this.fontRendererObj.drawString( - GuiText.ByteTotal.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesTotal()), + GuiText.ByteTotal.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesTotal()), 13, 143, GuiColors.NetworkStatusPowerUsageRate.getColor()); this.fontRendererObj.drawString( - GuiText.ByteUsage.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesUsed()) - + " (" + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + "%)", + GuiText.ByteUsage.getLocal() + ": " + + Platform.formatByteLong(ns.getItemBytesUsed()) + + " (" + + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + + "%)", 13, 143 + 10, GuiColors.NetworkStatusPowerUsageRate.getColor()); this.fontRendererObj.drawString( - GuiText.ByteFree.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesFree()) - + " (" + df.format(ns.getItemBytesFree() * 100d / ns.getItemBytesTotal()) + "%)", + GuiText.ByteFree.getLocal() + ": " + + Platform.formatByteLong(ns.getItemBytesFree()) + + " (" + + df.format(ns.getItemBytesFree() * 100d / ns.getItemBytesTotal()) + + "%)", 13, 143 + 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); - - - final int sectionLength = 30; diff --git a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java index 766ff75522b..2ae47f02954 100644 --- a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java +++ b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java @@ -11,8 +11,6 @@ package appeng.container.implementations; import java.io.IOException; -import java.util.HashSet; -import java.util.List; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -29,185 +27,174 @@ import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.storage.IStorageGrid; -import appeng.api.storage.ICellInventory; -import appeng.api.storage.ICellInventoryHandler; -import appeng.api.storage.ICellProvider; -import appeng.api.storage.IMEInventoryHandler; -import appeng.api.storage.IMEMonitor; -import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.container.AEBaseContainer; import appeng.container.guisync.GuiSync; import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.packets.PacketMEInventoryUpdate; import appeng.me.cache.GridStorageCache; -import appeng.me.cache.NetworkMonitor; -import appeng.me.storage.CellInventoryHandler; -import appeng.me.storage.DriveWatcher; -import appeng.services.version.Channel; import appeng.util.Platform; import appeng.util.item.AEItemStack; public class ContainerNetworkStatus extends AEBaseContainer { - @GuiSync(0) - public long avgAddition; - - @GuiSync(1) - public long powerUsage; - - @GuiSync(2) - public long currentPower; - - @GuiSync(3) - public long maxPower; - - @GuiSync(4) - public long itemBytesTotal; - - @GuiSync(5) - public long itemBytesUsed; - - @GuiSync(6) - public long itemBytesFree; - - private IGrid network; - private int delay = 40; - - public ContainerNetworkStatus(final InventoryPlayer ip, final INetworkTool te) { - super(ip, null, null); - final IGridHost host = te.getGridHost(); - - if (host != null) { - this.findNode(host, ForgeDirection.UNKNOWN); - for (final ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { - this.findNode(host, d); - } - } - - if (this.network == null && Platform.isServer()) { - this.setValidContainer(false); - } - } - - private void findNode(final IGridHost host, final ForgeDirection d) { - if (this.network == null) { - final IGridNode node = host.getGridNode(d); - if (node != null) { - this.network = node.getGrid(); - } - } - } - - @Override - public void detectAndSendChanges() { - this.delay++; - if (Platform.isServer() && this.delay > 15 && this.network != null) { - this.delay = 0; - - final IEnergyGrid eg = this.network.getCache(IEnergyGrid.class); - if (eg != null) { - this.setAverageAddition((long) (100.0 * eg.getAvgPowerInjection())); - this.setPowerUsage((long) (100.0 * eg.getAvgPowerUsage())); - this.setCurrentPower((long) (100.0 * eg.getStoredPower())); - this.setMaxPower((long) (100.0 * eg.getMaxStoredPower())); - } - - try { - final PacketMEInventoryUpdate piu = new PacketMEInventoryUpdate(); - - for (final Class machineClass : this.network.getMachinesClasses()) { - final IItemList list = AEApi.instance().storage().createItemList(); - for (final IGridNode machine : this.network.getMachines(machineClass)) { - final IGridBlock blk = machine.getGridBlock(); - final ItemStack is = blk.getMachineRepresentation(); - if (is != null && is.getItem() != null) { - final IAEItemStack ais = AEItemStack.create(is); - ais.setStackSize(1); - ais.setCountRequestable( - (long) PowerMultiplier.CONFIG.multiply(blk.getIdlePowerUsage() * 100.0)); - list.add(ais); - } - } - - for (final IAEItemStack ais : list) { - piu.appendItem(ais); - } - } - - for (final Object c : this.crafters) { - if (c instanceof EntityPlayer) { - NetworkHandler.instance.sendTo(piu, (EntityPlayerMP) c); - } - } - } catch (final IOException e) { - // :P - } - final GridStorageCache sg = this.network.getCache(IStorageGrid.class); - if (sg != null) { - this.setItemBytesTotal(sg.getItemBytesTotal()); - this.setItemBytesUsed(sg.getItemBytesUsed()); - this.setItemBytesFree(this.getItemBytesTotal() - this.getItemBytesUsed()); - } - } - super.detectAndSendChanges(); - } - - public long getCurrentPower() { - return this.currentPower; - } - - private void setCurrentPower(final long currentPower) { - this.currentPower = currentPower; - } - - public long getMaxPower() { - return this.maxPower; - } - - private void setMaxPower(final long maxPower) { - this.maxPower = maxPower; - } - - public long getAverageAddition() { - return this.avgAddition; - } - - private void setAverageAddition(final long avgAddition) { - this.avgAddition = avgAddition; - } - - public long getPowerUsage() { - return this.powerUsage; - } - - private void setPowerUsage(final long powerUsage) { - this.powerUsage = powerUsage; - } - - public long getItemBytesTotal() { - return this.itemBytesTotal; - } - - public long getItemBytesUsed() { - return this.itemBytesUsed; - } - - public long getItemBytesFree() { - return this.itemBytesFree; - } - - public void setItemBytesTotal(final long itemBytesTotal) { - this.itemBytesTotal = itemBytesTotal; - } - - public void setItemBytesUsed(final long itemBytesUsed) { - this.itemBytesUsed = itemBytesUsed; - } - - public void setItemBytesFree(final long itemBytesFree) { - this.itemBytesFree = itemBytesFree; - } + @GuiSync(0) + public long avgAddition; + + @GuiSync(1) + public long powerUsage; + + @GuiSync(2) + public long currentPower; + + @GuiSync(3) + public long maxPower; + + @GuiSync(4) + public long itemBytesTotal; + + @GuiSync(5) + public long itemBytesUsed; + + @GuiSync(6) + public long itemBytesFree; + + private IGrid network; + private int delay = 40; + + public ContainerNetworkStatus(final InventoryPlayer ip, final INetworkTool te) { + super(ip, null, null); + final IGridHost host = te.getGridHost(); + + if (host != null) { + this.findNode(host, ForgeDirection.UNKNOWN); + for (final ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { + this.findNode(host, d); + } + } + + if (this.network == null && Platform.isServer()) { + this.setValidContainer(false); + } + } + + private void findNode(final IGridHost host, final ForgeDirection d) { + if (this.network == null) { + final IGridNode node = host.getGridNode(d); + if (node != null) { + this.network = node.getGrid(); + } + } + } + + @Override + public void detectAndSendChanges() { + this.delay++; + if (Platform.isServer() && this.delay > 15 && this.network != null) { + this.delay = 0; + + final IEnergyGrid eg = this.network.getCache(IEnergyGrid.class); + if (eg != null) { + this.setAverageAddition((long) (100.0 * eg.getAvgPowerInjection())); + this.setPowerUsage((long) (100.0 * eg.getAvgPowerUsage())); + this.setCurrentPower((long) (100.0 * eg.getStoredPower())); + this.setMaxPower((long) (100.0 * eg.getMaxStoredPower())); + } + + try { + final PacketMEInventoryUpdate piu = new PacketMEInventoryUpdate(); + + for (final Class machineClass : this.network.getMachinesClasses()) { + final IItemList list = AEApi.instance().storage().createItemList(); + for (final IGridNode machine : this.network.getMachines(machineClass)) { + final IGridBlock blk = machine.getGridBlock(); + final ItemStack is = blk.getMachineRepresentation(); + if (is != null && is.getItem() != null) { + final IAEItemStack ais = AEItemStack.create(is); + ais.setStackSize(1); + ais.setCountRequestable( + (long) PowerMultiplier.CONFIG.multiply(blk.getIdlePowerUsage() * 100.0)); + list.add(ais); + } + } + + for (final IAEItemStack ais : list) { + piu.appendItem(ais); + } + } + + for (final Object c : this.crafters) { + if (c instanceof EntityPlayer) { + NetworkHandler.instance.sendTo(piu, (EntityPlayerMP) c); + } + } + } catch (final IOException e) { + // :P + } + final GridStorageCache sg = this.network.getCache(IStorageGrid.class); + if (sg != null) { + this.setItemBytesTotal(sg.getItemBytesTotal()); + this.setItemBytesUsed(sg.getItemBytesUsed()); + this.setItemBytesFree(this.getItemBytesTotal() - this.getItemBytesUsed()); + } + } + super.detectAndSendChanges(); + } + + public long getCurrentPower() { + return this.currentPower; + } + + private void setCurrentPower(final long currentPower) { + this.currentPower = currentPower; + } + + public long getMaxPower() { + return this.maxPower; + } + + private void setMaxPower(final long maxPower) { + this.maxPower = maxPower; + } + + public long getAverageAddition() { + return this.avgAddition; + } + + private void setAverageAddition(final long avgAddition) { + this.avgAddition = avgAddition; + } + + public long getPowerUsage() { + return this.powerUsage; + } + + private void setPowerUsage(final long powerUsage) { + this.powerUsage = powerUsage; + } + + public long getItemBytesTotal() { + return this.itemBytesTotal; + } + + public long getItemBytesUsed() { + return this.itemBytesUsed; + } + + public long getItemBytesFree() { + return this.itemBytesFree; + } + + public void setItemBytesTotal(final long itemBytesTotal) { + this.itemBytesTotal = itemBytesTotal; + } + + public void setItemBytesUsed(final long itemBytesUsed) { + this.itemBytesUsed = itemBytesUsed; + } + + public void setItemBytesFree(final long itemBytesFree) { + this.itemBytesFree = itemBytesFree; + } } diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index eae559d2f93..abe2b8f0f66 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -206,11 +206,11 @@ public enum GuiText { // If a thing is deprecated Deprecated, - - //mine - ByteTotal, - ByteUsage, - ByteFree; + + // mine + ByteTotal, + ByteUsage, + ByteFree; private final String root; diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 9416db69961..2f1a6e785ee 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -49,329 +49,326 @@ public class GridStorageCache implements IStorageGrid { - private final IGrid myGrid; - private final HashSet activeCellProviders = new HashSet<>(); - private final HashSet inactiveCellProviders = new HashSet<>(); - private final SetMultimap interests = HashMultimap.create(); - private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); - private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); - private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); - private final HashMap watchers = new HashMap<>(); - private NetworkInventoryHandler myItemNetwork; - private NetworkInventoryHandler myFluidNetwork; - - // mine - private long itemBytesTotal; - private long itemBytesUsed; - - public GridStorageCache(final IGrid g) { - this.myGrid = g; - } - - @Override - public void onUpdateTick() { - this.itemMonitor.onTick(); - this.fluidMonitor.onTick(); - - this.itemBytesTotal = 0; - this.itemBytesUsed = 0; - try { - for (ICellProvider icp : this.activeCellProviders) { - if (icp.getClass() == Class.forName("appeng.tile.storage.TileDrive")) { - // All Item Cell - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { - if (((DriveWatcher) meih).getInternal().getClass() == Class - .forName("appeng.me.storage.VoidCellInventory")) { // exclude void cell and creative cell - continue; - } - if(((CellInventoryHandler) (((DriveWatcher) meih).getInternal())).getCellInv() != null) { - itemBytesTotal += ((CellInventoryHandler) (((DriveWatcher) meih).getInternal())) - .getCellInv().getTotalBytes(); - itemBytesUsed += ((CellInventoryHandler) (((DriveWatcher) meih).getInternal())) - .getCellInv().getUsedBytes(); - } - } - } - } - } catch (ClassNotFoundException e) { - // XD - } - } - - @Override - public void removeNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.removeCellProvider(cc, tracker); - this.inactiveCellProviders.remove(cc); - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - tracker.applyChanges(); - } - - if (machine instanceof IStackWatcherHost) { - final IStackWatcher myWatcher = this.watchers.get(machine); - - if (myWatcher != null) { - myWatcher.clear(); - this.watchers.remove(machine); - } - } - } - - @Override - public void addNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - this.inactiveCellProviders.add(cc); - - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - if (node.isActive()) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.addCellProvider(cc, tracker); - tracker.applyChanges(); - } - } - - if (machine instanceof IStackWatcherHost swh) { - final ItemWatcher iw = new ItemWatcher(this, swh); - this.watchers.put(node, iw); - swh.updateWatcher(iw); - } - } - - @Override - public void onSplit(final IGridStorage storageB) { - } - - @Override - public void onJoin(final IGridStorage storageB) { - } - - @Override - public void populateGridStorage(final IGridStorage storage) { - } - - private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.inactiveCellProviders.contains(cc)) { - this.inactiveCellProviders.remove(cc); - this.activeCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); - } - } - - return tracker; - } - - private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.activeCellProviders.contains(cc)) { - this.activeCellProviders.remove(cc); - this.inactiveCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); - } - } - - return tracker; - } - - @MENetworkEventSubscribe - public void cellUpdate(final MENetworkCellArrayUpdate ev) { - this.myItemNetwork = null; - this.myFluidNetwork = null; - - final LinkedList ll = new LinkedList(); - ll.addAll(this.inactiveCellProviders); - ll.addAll(this.activeCellProviders); - - final CellChangeTracker tracker = new CellChangeTracker(); - - for (final ICellProvider cc : ll) { - boolean active = true; - - if (cc instanceof IActionHost) { - final IGridNode node = ((IActionHost) cc).getActionableNode(); - active = node != null && node.isActive(); - } - - if (active) { - this.addCellProvider(cc, tracker); - } else { - this.removeCellProvider(cc, tracker); - } - } - - this.itemMonitor.forceUpdate(); - this.fluidMonitor.forceUpdate(); - - tracker.applyChanges(); - - } - - private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, - final BaseActionSource src) { - switch (chan) { - case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); - case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); - default -> { - } - } - } - - IMEInventoryHandler getItemInventoryHandler() { - if (this.myItemNetwork == null) { - this.buildNetworkStorage(StorageChannel.ITEMS); - } - return this.myItemNetwork; - } - - private void buildNetworkStorage(final StorageChannel chan) { - final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); - - switch (chan) { - case FLUIDS -> { - this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myFluidNetwork.addNewStorage(h); - } - } - } - case ITEMS -> { - this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myItemNetwork.addNewStorage(h); - } - } - } - default -> { - } - } - } - - IMEInventoryHandler getFluidInventoryHandler() { - if (this.myFluidNetwork == null) { - this.buildNetworkStorage(StorageChannel.FLUIDS); - } - return this.myFluidNetwork; - } - - @Override - public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, - final BaseActionSource src) { - if (chan == StorageChannel.ITEMS) { - this.itemMonitor.postChange(true, (Iterable) input, src); - } else if (chan == StorageChannel.FLUIDS) { - this.fluidMonitor.postChange(true, (Iterable) input, src); - } - } - - @Override - public void registerCellProvider(final ICellProvider provider) { - this.inactiveCellProviders.add(provider); - this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); - } - - @Override - public void unregisterCellProvider(final ICellProvider provider) { - this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); - this.inactiveCellProviders.remove(provider); - } - - @Override - public IMEMonitor getItemInventory() { - return this.itemMonitor; - } - - @Override - public IMEMonitor getFluidInventory() { - return this.fluidMonitor; - } - - public GenericInterestManager getInterestManager() { - return this.interestManager; - } - - IGrid getGrid() { - return this.myGrid; - } - - private class CellChangeTrackerRecord { - - final StorageChannel channel; - final int up_or_down; - final IItemList list; - final BaseActionSource src; - - public CellChangeTrackerRecord(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.channel = channel; - this.up_or_down = i; - this.src = actionSrc; - - if (channel == StorageChannel.ITEMS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createItemList()); - } else if (channel == StorageChannel.FLUIDS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createFluidList()); - } else { - this.list = null; - } - } - - public void applyChanges() { - GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); - } - } - - private class CellChangeTracker { - - final List data = new LinkedList<>(); - - public void postChanges(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); - } - - public void applyChanges() { - for (final CellChangeTrackerRecord rec : this.data) { - rec.applyChanges(); - } - } - } - - public long getItemBytesTotal() { - return this.itemBytesTotal; - } - - public long getItemBytesUsed() { - return this.itemBytesUsed; - } + private final IGrid myGrid; + private final HashSet activeCellProviders = new HashSet<>(); + private final HashSet inactiveCellProviders = new HashSet<>(); + private final SetMultimap interests = HashMultimap.create(); + private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); + private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); + private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); + private final HashMap watchers = new HashMap<>(); + private NetworkInventoryHandler myItemNetwork; + private NetworkInventoryHandler myFluidNetwork; + + // mine + private long itemBytesTotal; + private long itemBytesUsed; + + public GridStorageCache(final IGrid g) { + this.myGrid = g; + } + + @Override + public void onUpdateTick() { + this.itemMonitor.onTick(); + this.fluidMonitor.onTick(); + + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + try { + for (ICellProvider icp : this.activeCellProviders) { + if (icp.getClass() == Class.forName("appeng.tile.storage.TileDrive")) { + // All Item Cell + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + if (((DriveWatcher) meih).getInternal().getClass() + == Class.forName("appeng.me.storage.VoidCellInventory")) { // exclude void cell and + // creative cell + continue; + } + if (((CellInventoryHandler) (((DriveWatcher) meih).getInternal())).getCellInv() + != null) { + itemBytesTotal += ((CellInventoryHandler) (((DriveWatcher) meih) + .getInternal())).getCellInv().getTotalBytes(); + itemBytesUsed += ((CellInventoryHandler) (((DriveWatcher) meih) + .getInternal())).getCellInv().getUsedBytes(); + } + } + } + } + } catch (ClassNotFoundException e) { + // XD + } + } + + @Override + public void removeNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.removeCellProvider(cc, tracker); + this.inactiveCellProviders.remove(cc); + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + tracker.applyChanges(); + } + + if (machine instanceof IStackWatcherHost) { + final IStackWatcher myWatcher = this.watchers.get(machine); + + if (myWatcher != null) { + myWatcher.clear(); + this.watchers.remove(machine); + } + } + } + + @Override + public void addNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + this.inactiveCellProviders.add(cc); + + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + if (node.isActive()) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.addCellProvider(cc, tracker); + tracker.applyChanges(); + } + } + + if (machine instanceof IStackWatcherHost swh) { + final ItemWatcher iw = new ItemWatcher(this, swh); + this.watchers.put(node, iw); + swh.updateWatcher(iw); + } + } + + @Override + public void onSplit(final IGridStorage storageB) {} + + @Override + public void onJoin(final IGridStorage storageB) {} + + @Override + public void populateGridStorage(final IGridStorage storage) {} + + private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.inactiveCellProviders.contains(cc)) { + this.inactiveCellProviders.remove(cc); + this.activeCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); + } + } + + return tracker; + } + + private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.activeCellProviders.contains(cc)) { + this.activeCellProviders.remove(cc); + this.inactiveCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); + } + } + + return tracker; + } + + @MENetworkEventSubscribe + public void cellUpdate(final MENetworkCellArrayUpdate ev) { + this.myItemNetwork = null; + this.myFluidNetwork = null; + + final LinkedList ll = new LinkedList(); + ll.addAll(this.inactiveCellProviders); + ll.addAll(this.activeCellProviders); + + final CellChangeTracker tracker = new CellChangeTracker(); + + for (final ICellProvider cc : ll) { + boolean active = true; + + if (cc instanceof IActionHost) { + final IGridNode node = ((IActionHost) cc).getActionableNode(); + active = node != null && node.isActive(); + } + + if (active) { + this.addCellProvider(cc, tracker); + } else { + this.removeCellProvider(cc, tracker); + } + } + + this.itemMonitor.forceUpdate(); + this.fluidMonitor.forceUpdate(); + + tracker.applyChanges(); + + } + + private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, + final BaseActionSource src) { + switch (chan) { + case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); + case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); + default -> {} + } + } + + IMEInventoryHandler getItemInventoryHandler() { + if (this.myItemNetwork == null) { + this.buildNetworkStorage(StorageChannel.ITEMS); + } + return this.myItemNetwork; + } + + private void buildNetworkStorage(final StorageChannel chan) { + final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); + + switch (chan) { + case FLUIDS -> { + this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myFluidNetwork.addNewStorage(h); + } + } + } + case ITEMS -> { + this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myItemNetwork.addNewStorage(h); + } + } + } + default -> {} + } + } + + IMEInventoryHandler getFluidInventoryHandler() { + if (this.myFluidNetwork == null) { + this.buildNetworkStorage(StorageChannel.FLUIDS); + } + return this.myFluidNetwork; + } + + @Override + public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, + final BaseActionSource src) { + if (chan == StorageChannel.ITEMS) { + this.itemMonitor.postChange(true, (Iterable) input, src); + } else if (chan == StorageChannel.FLUIDS) { + this.fluidMonitor.postChange(true, (Iterable) input, src); + } + } + + @Override + public void registerCellProvider(final ICellProvider provider) { + this.inactiveCellProviders.add(provider); + this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); + } + + @Override + public void unregisterCellProvider(final ICellProvider provider) { + this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); + this.inactiveCellProviders.remove(provider); + } + + @Override + public IMEMonitor getItemInventory() { + return this.itemMonitor; + } + + @Override + public IMEMonitor getFluidInventory() { + return this.fluidMonitor; + } + + public GenericInterestManager getInterestManager() { + return this.interestManager; + } + + IGrid getGrid() { + return this.myGrid; + } + + private class CellChangeTrackerRecord { + + final StorageChannel channel; + final int up_or_down; + final IItemList list; + final BaseActionSource src; + + public CellChangeTrackerRecord(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.channel = channel; + this.up_or_down = i; + this.src = actionSrc; + + if (channel == StorageChannel.ITEMS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createItemList()); + } else if (channel == StorageChannel.FLUIDS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createFluidList()); + } else { + this.list = null; + } + } + + public void applyChanges() { + GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); + } + } + + private class CellChangeTracker { + + final List data = new LinkedList<>(); + + public void postChanges(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); + } + + public void applyChanges() { + for (final CellChangeTrackerRecord rec : this.data) { + rec.applyChanges(); + } + } + } + + public long getItemBytesTotal() { + return this.itemBytesTotal; + } + + public long getItemBytesUsed() { + return this.itemBytesUsed; + } } diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index 967897eef96..b313c3df14e 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -67,7 +67,6 @@ import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.oredict.OreDictionary; -import com.ibm.icu.text.NumberFormat; import com.mojang.authlib.GameProfile; import appeng.api.AEApi; @@ -143,1726 +142,1754 @@ */ public class Platform { - public static final Block AIR_BLOCK = Blocks.air; - - public static final int DEF_OFFSET = 16; - - /* - * random source, use it for item drop locations... - */ - private static final Random RANDOM_GENERATOR = new Random(); - private static final WeakHashMap FAKE_PLAYERS = new WeakHashMap<>(); - private static Field tagList; - private static Class playerInstance; - private static Method getOrCreateChunkWatcher; - private static Method sendToAllPlayersWatchingChunk; - private static GameProfile fakeProfile = new GameProfile(UUID.fromString("839eb18c-50bc-400c-8291-9383f09763e7"), - "[AE2Player]"); - - public static Random getRandom() { - return RANDOM_GENERATOR; - } - - public static float getRandomFloat() { - return RANDOM_GENERATOR.nextFloat(); - } - - /** - * Seed a random number generator from a world seed and grid location. The grid - * can be any arbitrary set of coordinates, e.g. chunk position or block - * position. This method guarantees that for the same inputs (worldSeed, x, z) - * the same seed will be used. - * - * @param rng The generator to re-seed. - * @param worldSeed Global seed independent of the grid position - * @param x X location in the grid - * @param z Z location in the grid - */ - public static void seedFromGrid(final Random rng, final long worldSeed, final long x, final long z) { - rng.setSeed(worldSeed); - final long xSeed = rng.nextLong() >> 2 + 1L; - final long zSeed = rng.nextLong() >> 2 + 1L; - final long gridSeed = (xSeed * x + zSeed * z) ^ worldSeed; - rng.setSeed(gridSeed); - } - - /** - * This displays the value for encoded longs ( double *100 ) - * - * @param n to be formatted long value - * @param isRate if true it adds a /t to the formatted string - * @return formatted long value - */ - public static String formatPowerLong(final long n, final boolean isRate) { - double p = ((double) n) / 100; - - final PowerUnits displayUnits = AEConfig.instance.selectedPowerUnit(); - p = PowerUnits.AE.convertTo(displayUnits, p); - - String unitName = displayUnits.name(); - - if (displayUnits == PowerUnits.WA) { - unitName = "J"; - } - - if (displayUnits == PowerUnits.MK) { - unitName = "J"; - } - - final String[] preFixes = { "k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y" }; - String level = ""; - int offset = 0; - while (p > 1000 && offset < preFixes.length) { - p /= 1000; - level = preFixes[offset]; - offset++; - } - - final DecimalFormat df = new DecimalFormat("#.##"); - return df.format(p) + ' ' + level + unitName + (isRate ? "/t" : ""); - } - - public static ForgeDirection crossProduct(final ForgeDirection forward, final ForgeDirection up) { - final int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; - final int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; - final int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; - - return switch (west_x + west_y * 2 + west_z * 3) { - case 1 -> ForgeDirection.EAST; - case -1 -> ForgeDirection.WEST; - case 2 -> ForgeDirection.UP; - case -2 -> ForgeDirection.DOWN; - case 3 -> ForgeDirection.SOUTH; - case -3 -> ForgeDirection.NORTH; - default -> ForgeDirection.UNKNOWN; - }; - - } - - public static T rotateEnum(T ce, final boolean backwards, final EnumSet validOptions) { - do { - if (backwards) { - ce = prevEnum(ce); - } else { - ce = nextEnum(ce); - } - } while (!validOptions.contains(ce) || isNotValidSetting(ce)); - - return ce; - } - - /* - * Simple way to cycle an enum... - */ - private static T prevEnum(final T ce) { - final EnumSet valList = EnumSet.allOf(ce.getClass()); - - int pLoc = ce.ordinal() - 1; - if (pLoc < 0) { - pLoc = valList.size() - 1; - } - - if (pLoc < 0 || pLoc >= valList.size()) { - pLoc = 0; - } - - int pos = 0; - for (final Object g : valList) { - if (pos == pLoc) { - return (T) g; - } - pos++; - } - - return null; - } - - /* - * Simple way to cycle an enum... - */ - public static T nextEnum(final T ce) { - final EnumSet valList = EnumSet.allOf(ce.getClass()); - - int pLoc = ce.ordinal() + 1; - if (pLoc >= valList.size()) { - pLoc = 0; - } - - if (pLoc < 0 || pLoc >= valList.size()) { - pLoc = 0; - } - - int pos = 0; - for (final Object g : valList) { - if (pos == pLoc) { - return (T) g; - } - pos++; - } - - return null; - } - - private static boolean isNotValidSetting(final Enum e) { - if (e == SortOrder.INVTWEAKS && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.InvTweaks)) { - return true; - } - - if (e == SearchBoxMode.NEI_AUTOSEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI)) { - return true; - } - - return e == SearchBoxMode.NEI_MANUAL_SEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI); - } - - public static void openGUI(@Nonnull final EntityPlayer p, @Nullable final TileEntity tile, - @Nullable final ForgeDirection side, @Nonnull final GuiBridge type) { - if (isClient()) { - return; - } - - int x = (int) p.posX; - int y = (int) p.posY; - int z = (int) p.posZ; - if (tile != null) { - x = tile.xCoord; - y = tile.yCoord; - z = tile.zCoord; - } - - if ((type.getType().isItem() && tile == null) || type.hasPermissions(tile, x, y, z, side, p)) { - if (tile == null && type.getType() == GuiHostType.ITEM) { - p.openGui(AppEng.instance(), type.ordinal() << 5 | (1 << 4), p.getEntityWorld(), - p.inventory.currentItem, 0, 0); - } else if (tile == null || type.getType() == GuiHostType.ITEM) { - p.openGui(AppEng.instance(), type.ordinal() << 5 | (1 << 3), p.getEntityWorld(), x, y, z); - } else { - p.openGui(AppEng.instance(), type.ordinal() << 5 | (side.ordinal()), tile.getWorldObj(), x, y, z); - } - } - } - - /* - * returns true if the code is on the client. - */ - public static boolean isClient() { - return FMLCommonHandler.instance().getEffectiveSide().isClient(); - } - - public static boolean hasPermissions(final DimensionalCoord dc, final EntityPlayer player) { - return dc.getWorld().canMineBlock(player, dc.x, dc.y, dc.z); - } - - /* - * Checks to see if a block is air? - */ - public static boolean isBlockAir(final World w, final int x, final int y, final int z) { - try { - return w.getBlock(x, y, z).isAir(w, x, y, z); - } catch (final Throwable e) { - return false; - } - } - - /* - * Lots of silliness to try and account for weird tag related junk, basically - * requires that two tags have at least something in their tags before it wasts - * its time comparing them. - */ - private static boolean sameStackStags(final ItemStack a, final ItemStack b) { - if (a == null && b == null) { - return true; - } - if (a == null || b == null) { - return false; - } - if (a == b) { - return true; - } - - final NBTTagCompound ta = a.getTagCompound(); - final NBTTagCompound tb = b.getTagCompound(); - if (ta == tb) { - return true; - } - - if ((ta == null && tb == null) || (ta != null && ta.hasNoTags() && tb == null) - || (tb != null && tb.hasNoTags() && ta == null) - || (ta != null && ta.hasNoTags() && tb != null && tb.hasNoTags())) { - return true; - } - - if ((ta == null && tb != null) || (ta != null && tb == null)) { - return false; - } - - // if both tags are shared this is easy... - if (AESharedNBT.isShared(ta) && AESharedNBT.isShared(tb)) { - return ta == tb; - } - - return NBTEqualityTest(ta, tb); - } - - /* - * recursive test for NBT Equality, this was faster then trying to compare / - * generate hashes, its also more reliable then the vanilla version which likes - * to fail when NBT Compound data changes order, it is pretty expensive - * performance wise, so try an use shared tag compounds as long as the system - * remains in AE. - */ - public static boolean NBTEqualityTest(final NBTBase left, final NBTBase right) { - // same type? - final byte id = left.getId(); - if (id == right.getId()) { - switch (id) { - case 10 -> { - final NBTTagCompound ctA = (NBTTagCompound) left; - final NBTTagCompound ctB = (NBTTagCompound) right; - - final Set cA = ctA.func_150296_c(); - final Set cB = ctB.func_150296_c(); - - if (cA.size() != cB.size()) { - return false; - } - - for (final String name : cA) { - final NBTBase tag = ctA.getTag(name); - final NBTBase aTag = ctB.getTag(name); - if (aTag == null) { - return false; - } - - if (!NBTEqualityTest(tag, aTag)) { - return false; - } - } - - return true; - } - case 9 -> // ) // A instanceof NBTTagList ) - { - final NBTTagList lA = (NBTTagList) left; - final NBTTagList lB = (NBTTagList) right; - if (lA.tagCount() != lB.tagCount()) { - return false; - } - - final List tag = tagList(lA); - final List aTag = tagList(lB); - if (tag.size() != aTag.size()) { - return false; - } - - for (int x = 0; x < tag.size(); x++) { - if (aTag.get(x) == null) { - return false; - } - - if (!NBTEqualityTest(tag.get(x), aTag.get(x))) { - return false; - } - } - - return true; - } - case 1 -> { // ( A instanceof NBTTagByte ) - return ((NBTBase.NBTPrimitive) left).func_150287_d() == ((NBTBase.NBTPrimitive) right).func_150287_d(); - } - case 4 -> { // else if ( A instanceof NBTTagLong ) - return ((NBTBase.NBTPrimitive) left).func_150291_c() == ((NBTBase.NBTPrimitive) right).func_150291_c(); - } - case 8 -> { // else if ( A instanceof NBTTagString ) - return ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()) - || ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()); - } - case 6 -> { // else if ( A instanceof NBTTagDouble ) - return ((NBTBase.NBTPrimitive) left).func_150286_g() == ((NBTBase.NBTPrimitive) right).func_150286_g(); - } - case 5 -> { // else if ( A instanceof NBTTagFloat ) - return ((NBTBase.NBTPrimitive) left).func_150288_h() == ((NBTBase.NBTPrimitive) right).func_150288_h(); - } - case 3 -> { // else if ( A instanceof NBTTagInt ) - return ((NBTBase.NBTPrimitive) left).func_150287_d() == ((NBTBase.NBTPrimitive) right).func_150287_d(); - } - default -> { - return left.equals(right); - } - } - } - - return false; - } - - private static List tagList(final NBTTagList lB) { - if (tagList == null) { - try { - tagList = lB.getClass().getDeclaredField("tagList"); - } catch (final Throwable t) { - try { - tagList = lB.getClass().getDeclaredField("field_74747_a"); - } catch (final Throwable z) { - AELog.debug(t); - AELog.debug(z); - } - } - } - - try { - tagList.setAccessible(true); - return (List) tagList.get(lB); - } catch (final Throwable t) { - AELog.debug(t); - } - - return new ArrayList<>(); - } - - /* - * Orderless hash on NBT Data, used to work thought huge piles fast, but ignores - * the order just in case MC decided to change it... WHICH IS BAD... - */ - public static int NBTOrderlessHash(final NBTBase nbt) { - // same type? - int hash = 0; - final byte id = nbt.getId(); - hash += id; - switch (id) { - case 10 -> { - final NBTTagCompound ctA = (NBTTagCompound) nbt; - - final Set cA = ctA.func_150296_c(); - - for (final String name : cA) { - hash += name.hashCode() ^ NBTOrderlessHash(ctA.getTag(name)); - } - - return hash; - } - case 9 -> // ) // A instanceof NBTTagList ) - { - final NBTTagList lA = (NBTTagList) nbt; - hash += 9 * lA.tagCount(); - - final List l = tagList(lA); - for (int x = 0; x < l.size(); x++) { - hash += ((Integer) x).hashCode() ^ NBTOrderlessHash(l.get(x)); - } - - return hash; - } - case 1 -> { // ( A instanceof NBTTagByte ) - return hash + ((NBTBase.NBTPrimitive) nbt).func_150290_f(); - } - case 4 -> { // else if ( A instanceof NBTTagLong ) - return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150291_c(); - } - case 8 -> { // else if ( A instanceof NBTTagString ) - return hash + ((NBTTagString) nbt).func_150285_a_().hashCode(); - } - case 6 -> { // else if ( A instanceof NBTTagDouble ) - return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150286_g(); - } - case 5 -> { // else if ( A instanceof NBTTagFloat ) - return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150288_h(); - } - case 3 -> { // else if ( A instanceof NBTTagInt ) - return hash + ((NBTBase.NBTPrimitive) nbt).func_150287_d(); - } - default -> { - return hash; - } - } - } - - private static IRecipe lastUsedRecipe = null; - - /* - * The usual version of this returns an ItemStack, this version returns the - * recipe. - */ - public static IRecipe findMatchingRecipe(final InventoryCrafting inventoryCrafting, final World par2World) { - if (lastUsedRecipe != null && lastUsedRecipe.matches(inventoryCrafting, par2World)) - return lastUsedRecipe; - - final CraftingManager cm = CraftingManager.getInstance(); - final List rl = cm.getRecipeList(); - - for (final IRecipe r : rl) { - if (r.matches(inventoryCrafting, par2World)) { - lastUsedRecipe = r; - return r; - } - } - - return null; - } - - public static ItemStack[] getBlockDrops(final World w, final int x, final int y, final int z) { - List out = new ArrayList<>(); - final Block which = w.getBlock(x, y, z); - - if (which != null) { - out = which.getDrops(w, x, y, z, w.getBlockMetadata(x, y, z), 0); - } - - if (out == null) { - return new ItemStack[0]; - } - return out.toArray(new ItemStack[0]); - } - - public static ForgeDirection cycleOrientations(final ForgeDirection dir, final boolean upAndDown) { - if (upAndDown) { - return switch (dir) { - case NORTH -> ForgeDirection.SOUTH; - case SOUTH -> ForgeDirection.EAST; - case EAST -> ForgeDirection.WEST; - case WEST -> ForgeDirection.NORTH; - case UP -> ForgeDirection.UP; - case DOWN -> ForgeDirection.DOWN; - case UNKNOWN -> ForgeDirection.UNKNOWN; - }; - } else { - return switch (dir) { - case UP -> ForgeDirection.DOWN; - case DOWN -> ForgeDirection.NORTH; - case NORTH -> ForgeDirection.SOUTH; - case SOUTH -> ForgeDirection.EAST; - case EAST -> ForgeDirection.WEST; - case WEST -> ForgeDirection.UP; - case UNKNOWN -> ForgeDirection.UNKNOWN; - }; - } - } - - /* - * Creates / or loads previous NBT Data on items, used for editing items owned - * by AE. - */ - public static NBTTagCompound openNbtData(final ItemStack i) { - NBTTagCompound compound = i.getTagCompound(); - - if (compound == null) { - i.setTagCompound(compound = new NBTTagCompound()); - } - - return compound; - } - - /* - * Generates Item entities in the world similar to how items are generally - * dropped. - */ - public static void spawnDrops(final World w, final int x, final int y, final int z, final List drops) { - if (isServer()) { - for (final ItemStack i : drops) { - if (i != null) { - if (i.stackSize > 0) { - final double offset_x = (getRandomInt() % 32 - 16) / 82; - final double offset_y = (getRandomInt() % 32 - 16) / 82; - final double offset_z = (getRandomInt() % 32 - 16) / 82; - final EntityItem ei = new EntityItem(w, 0.5 + offset_x + x, 0.5 + offset_y + y, - 0.2 + offset_z + z, i.copy()); - w.spawnEntityInWorld(ei); - } - } - } - } - } - - /* - * returns true if the code is on the server. - */ - public static boolean isServer() { - return FMLCommonHandler.instance().getEffectiveSide().isServer(); - } - - public static int getRandomInt() { - return Math.abs(RANDOM_GENERATOR.nextInt()); - } - - /* - * Utility function to get the full inventory for a Double Chest in the World. - */ - public static IInventory GetChestInv(final Object te) { - TileEntityChest teA = (TileEntityChest) te; - TileEntity teB = null; - final Block myBlockID = teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord); - - if (teA.getWorldObj().getBlock(teA.xCoord + 1, teA.yCoord, teA.zCoord) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord + 1, teA.yCoord, teA.zCoord); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } - } - - if (teB == null) { - if (teA.getWorldObj().getBlock(teA.xCoord - 1, teA.yCoord, teA.zCoord) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord - 1, teA.yCoord, teA.zCoord); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } else { - final TileEntityChest x = teA; - teA = (TileEntityChest) teB; - teB = x; - } - } - } - - if (teB == null) { - if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord + 1) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord + 1); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } - } - } - - if (teB == null) { - if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord - 1) == myBlockID) { - teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord - 1); - if (!(teB instanceof TileEntityChest)) { - teB = null; - } else { - final TileEntityChest x = teA; - teA = (TileEntityChest) teB; - teB = x; - } - } - } - - if (teB == null) { - return teA; - } - - return new InventoryLargeChest("", teA, (IInventory) teB); - } - - public static boolean isModLoaded(final String modid) { - try { - // if this fails for some reason, try the other method. - return Loader.isModLoaded(modid); - } catch (final Throwable ignored) { - } - - for (final ModContainer f : Loader.instance().getActiveModList()) { - if (f.getModId().equals(modid)) { - return true; - } - } - return false; - } - - public static ItemStack findMatchingRecipeOutput(final InventoryCrafting ic, final World worldObj) { - return CraftingManager.getInstance().findMatchingRecipe(ic, worldObj); - } - - @SideOnly(Side.CLIENT) - public static List getTooltip(final Object o) { - if (o == null) { - return new ArrayList<>(); - } - - ItemStack itemStack = null; - if (o instanceof AEItemStack ais) { - return ais.getToolTip(); - } else if (o instanceof ItemStack) { - itemStack = (ItemStack) o; - } else { - return new ArrayList<>(); - } - - try { - return itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } catch (final Exception errB) { - return new ArrayList<>(); - } - } - - public static String getModId(final IAEItemStack is) { - if (is == null) { - return "** Null"; - } - - final String n = ((AEItemStack) is).getModID(); - return n == null ? "** Null" : n; - } - - public static String getItemDisplayName(final Object o) { - if (o == null) { - return "** Null"; - } - - ItemStack itemStack = null; - if (o instanceof AEItemStack) { - final String n = ((AEItemStack) o).getDisplayName(); - return n == null ? "** Null" : n; - } else if (o instanceof ItemStack) { - itemStack = (ItemStack) o; - } else { - return "**Invalid Object"; - } - - try { - String name = itemStack.getDisplayName(); - if (name == null || name.isEmpty()) { - name = itemStack.getItem().getUnlocalizedName(itemStack); - } - return name == null ? "** Null" : name; - } catch (final Exception errA) { - try { - final String n = itemStack.getUnlocalizedName(); - return n == null ? "** Null" : n; - } catch (final Exception errB) { - return "** Exception"; - } - } - } - - public static boolean hasSpecialComparison(final IAEItemStack willAdd) { - if (willAdd == null) { - return false; - } - final IAETagCompound tag = willAdd.getTagCompound(); - return tag != null && tag.getSpecialComparison() != null; - } - - public static boolean hasSpecialComparison(final ItemStack willAdd) { - if (AESharedNBT.isShared(willAdd.getTagCompound())) { - if (((IAETagCompound) willAdd.getTagCompound()).getSpecialComparison() != null) { - return true; - } - } - return false; - } - - public static boolean isWrench(final EntityPlayer player, final ItemStack stack, final int x, final int y, - final int z) { - if (stack != null) { - Item itemWrench = stack.getItem(); - if (itemWrench instanceof IAEWrench wrench) { - return wrench.canWrench(stack, player, x, y, z); - } - - if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.CoFHWrench) - && itemWrench instanceof IToolHammer wrench) { - return wrench.isUsable(stack, player, x, y, z); - } - - if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.BuildCraftCore) - && itemWrench instanceof IToolWrench wrench) { - return wrench.canWrench(player, x, y, z); - } - } - return false; - } - - public static boolean isChargeable(final ItemStack i) { - if (i == null) { - return false; - } - final Item it = i.getItem(); - if (it instanceof IAEItemPowerStorage) { - return ((IAEItemPowerStorage) it).getPowerFlow(i) != AccessRestriction.READ; - } - return false; - } - - public static EntityPlayer getPlayer(final WorldServer w) { - if (w == null) { - throw new InvalidParameterException("World is null."); - } - - final EntityPlayer wrp = FAKE_PLAYERS.get(w); - if (wrp != null) { - return wrp; - } - - final EntityPlayer p = FakePlayerFactory.get(w, fakeProfile); - FAKE_PLAYERS.put(w, p); - return p; - } - - public static int MC2MEColor(final int color) { - switch (color) { - case 4: // "blue" - return 0; - case 0: // "black" - return 1; - case 15: // "white" - return 2; - case 3: // "brown" - return 3; - case 1: // "red" - return 4; - case 11: // "yellow" - return 5; - case 2: // "green" - return 6; - - case 5: // "purple" - case 6: // "cyan" - case 7: // "silver" - case 8: // "gray" - case 9: // "pink" - case 10: // "lime" - case 12: // "lightBlue" - case 13: // "magenta" - case 14: // "orange" - } - return -1; - } - - public static int findEmpty(final Object[] l) { - for (int x = 0; x < l.length; x++) { - if (l[x] == null) { - return x; - } - } - return -1; - } - - public static T pickRandom(final Collection outs) { - int index = RANDOM_GENERATOR.nextInt(outs.size()); - final Iterator i = outs.iterator(); - while (i.hasNext() && index > 0) { - index--; - i.next(); - } - index--; - if (i.hasNext()) { - return i.next(); - } - return null; // wtf? - } - - public static ForgeDirection rotateAround(final ForgeDirection forward, final ForgeDirection axis) { - if (axis == ForgeDirection.UNKNOWN || forward == ForgeDirection.UNKNOWN) { - return forward; - } - - switch (forward) { - case DOWN: - switch (axis) { - case DOWN -> { - return forward; - } - case UP -> { - return forward; - } - case NORTH -> { - return ForgeDirection.EAST; - } - case SOUTH -> { - return ForgeDirection.WEST; - } - case EAST -> { - return ForgeDirection.NORTH; - } - case WEST -> { - return ForgeDirection.SOUTH; - } - default -> { - } - } - break; - case UP: - switch (axis) { - case NORTH -> { - return ForgeDirection.WEST; - } - case SOUTH -> { - return ForgeDirection.EAST; - } - case EAST -> { - return ForgeDirection.SOUTH; - } - case WEST -> { - return ForgeDirection.NORTH; - } - default -> { - } - } - break; - case NORTH: - switch (axis) { - case UP -> { - return ForgeDirection.WEST; - } - case DOWN -> { - return ForgeDirection.EAST; - } - case EAST -> { - return ForgeDirection.UP; - } - case WEST -> { - return ForgeDirection.DOWN; - } - default -> { - } - } - break; - case SOUTH: - switch (axis) { - case UP -> { - return ForgeDirection.EAST; - } - case DOWN -> { - return ForgeDirection.WEST; - } - case EAST -> { - return ForgeDirection.DOWN; - } - case WEST -> { - return ForgeDirection.UP; - } - default -> { - } - } - break; - case EAST: - switch (axis) { - case UP -> { - return ForgeDirection.NORTH; - } - case DOWN -> { - return ForgeDirection.SOUTH; - } - case NORTH -> { - return ForgeDirection.UP; - } - case SOUTH -> { - return ForgeDirection.DOWN; - } - default -> { - } - } - case WEST: - switch (axis) { - case UP -> { - return ForgeDirection.SOUTH; - } - case DOWN -> { - return ForgeDirection.NORTH; - } - case NORTH -> { - return ForgeDirection.DOWN; - } - case SOUTH -> { - return ForgeDirection.UP; - } - default -> { - } - } - default: - break; - } - return forward; - } - - @SideOnly(Side.CLIENT) - public static String gui_localize(final String string) { - return StatCollector.translateToLocal(string); - } - - public static boolean isSameItemPrecise(@Nullable final ItemStack is, @Nullable final ItemStack filter) { - return isSameItem(is, filter) && sameStackStags(is, filter); - } - - public static boolean isSameItemFuzzy(final ItemStack a, final ItemStack b, final FuzzyMode mode) { - if (a == null && b == null) { - return true; - } - - if (a == null) { - return false; - } - - if (b == null) { - return false; - } - - /* - * if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! - * a.getHasSubtypes() && a.itemID == b.itemID ) { return (a.getItemDamage() > 0) - * == (b.getItemDamage() > 0); } - */ - - // test damageable items.. - if (a.getItem() != null && b.getItem() != null && a.getItem().isDamageable() && a.getItem() == b.getItem()) { - try { - if (mode == FuzzyMode.IGNORE_ALL) { - return true; - } else if (mode == FuzzyMode.PERCENT_99) { - return (a.getItemDamageForDisplay() > 1) == (b.getItemDamageForDisplay() > 1); - } else { - final float percentDamagedOfA = 1.0f - - (float) a.getItemDamageForDisplay() / (float) a.getMaxDamage(); - final float percentDamagedOfB = 1.0f - - (float) b.getItemDamageForDisplay() / (float) b.getMaxDamage(); - - return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); - } - } catch (final Throwable e) { - if (mode == FuzzyMode.IGNORE_ALL) { - return true; - } else if (mode == FuzzyMode.PERCENT_99) { - return (a.getItemDamage() > 1) == (b.getItemDamage() > 1); - } else { - final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage(); - final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage(); - - return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); - } - } - } - - final OreReference aOR = OreHelper.INSTANCE.isOre(a); - final OreReference bOR = OreHelper.INSTANCE.isOre(b); - - if (OreHelper.INSTANCE.sameOre(aOR, bOR)) { - return true; - } - - /* - * // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return - * OreID == getOreID( b ); if ( Mode != FuzzyMode.IGNORE_ALL ) { if ( - * a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a = - * Platform.getSharedItemStack( AEItemStack.create( a ) ); } if ( - * b.hasTagCompound() && !isShared( b.getTagCompound() ) ) { b = - * Platform.getSharedItemStack( AEItemStack.create( b ) ); } // test regular - * items with damage values and what not... if ( isShared( a.getTagCompound() ) - * && isShared( b.getTagCompound() ) && a.itemID == b.itemID ) { return - * ((AppEngSharedNBTTagCompound) a.getTagCompound()).compareFuzzyWithRegistry( - * (AppEngSharedNBTTagCompound) b.getTagCompound() ); } } - */ - - return a.isItemEqual(b); - } - - public static LookDirection getPlayerRay(final EntityPlayer player, final float eyeOffset) { - final float f = 1.0F; - final float f1 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * f; - final float f2 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * f; - final double d0 = player.prevPosX + (player.posX - player.prevPosX) * f; - final double d1 = eyeOffset; - final double d2 = player.prevPosZ + (player.posZ - player.prevPosZ) * f; - - final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); - final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); - final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); - final float f5 = -MathHelper.cos(-f1 * 0.017453292F); - final float f6 = MathHelper.sin(-f1 * 0.017453292F); - final float f7 = f4 * f5; - final float f8 = f3 * f5; - double d3 = 5.0D; - - if (player instanceof EntityPlayerMP) { - d3 = ((EntityPlayerMP) player).theItemInWorldManager.getBlockReachDistance(); - } - final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); - return new LookDirection(vec3, vec31); - } - - public static MovingObjectPosition rayTrace(final EntityPlayer p, final boolean hitBlocks, - final boolean hitEntities) { - final World w = p.getEntityWorld(); - - final float f = 1.0F; - float f1 = p.prevRotationPitch + (p.rotationPitch - p.prevRotationPitch) * f; - final float f2 = p.prevRotationYaw + (p.rotationYaw - p.prevRotationYaw) * f; - final double d0 = p.prevPosX + (p.posX - p.prevPosX) * f; - final double d1 = p.prevPosY + (p.posY - p.prevPosY) * f + 1.62D - p.yOffset; - final double d2 = p.prevPosZ + (p.posZ - p.prevPosZ) * f; - final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); - final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); - final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); - final float f5 = -MathHelper.cos(-f1 * 0.017453292F); - final float f6 = MathHelper.sin(-f1 * 0.017453292F); - final float f7 = f4 * f5; - final float f8 = f3 * f5; - final double d3 = 32.0D; - - final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); - - final AxisAlignedBB bb = AxisAlignedBB - .getBoundingBox(Math.min(vec3.xCoord, vec31.xCoord), Math.min(vec3.yCoord, vec31.yCoord), - Math.min(vec3.zCoord, vec31.zCoord), Math.max(vec3.xCoord, vec31.xCoord), - Math.max(vec3.yCoord, vec31.yCoord), Math.max(vec3.zCoord, vec31.zCoord)) - .expand(16, 16, 16); - - Entity entity = null; - double closest = 9999999.0D; - if (hitEntities) { - final List list = w.getEntitiesWithinAABBExcludingEntity(p, bb); - - for (Object o : list) { - final Entity entity1 = (Entity) o; - - if (!entity1.isDead && entity1 != p && !(entity1 instanceof EntityItem)) { - if (entity1.isEntityAlive()) { - // prevent killing / flying of mounts. - if (entity1.riddenByEntity == p) { - continue; - } - - f1 = 0.3F; - final AxisAlignedBB boundingBox = entity1.boundingBox.expand(f1, f1, f1); - final MovingObjectPosition movingObjectPosition = boundingBox.calculateIntercept(vec3, vec31); - - if (movingObjectPosition != null) { - final double nd = vec3.squareDistanceTo(movingObjectPosition.hitVec); - - if (nd < closest) { - entity = entity1; - closest = nd; - } - } - } - } - } - } - - MovingObjectPosition pos = null; - Vec3 vec = null; - - if (hitBlocks) { - vec = Vec3.createVectorHelper(d0, d1, d2); - pos = w.rayTraceBlocks(vec3, vec31, true); - } - - if (entity != null && pos != null && pos.hitVec.squareDistanceTo(vec) > closest) { - pos = new MovingObjectPosition(entity); - } else if (entity != null && pos == null) { - pos = new MovingObjectPosition(entity); - } - - return pos; - } - - public static long nanoTime() { - // if ( Configuration.INSTANCE.enableNetworkProfiler ) - // return System.nanoTime(); - return 0; - } - - public static StackType poweredExtraction(final IEnergySource energy, - final IMEInventory cell, final StackType request, final BaseActionSource src) { - final StackType possible = cell.extractItems((StackType) request.copy(), Actionable.SIMULATE, src); - - long retrieved = 0; - if (possible != null) { - retrieved = possible.getStackSize(); - } - - final double availablePower = energy.extractAEPower(retrieved, Actionable.SIMULATE, PowerMultiplier.CONFIG); - - final long itemToExtract = Math.min((long) (availablePower + 0.9), retrieved); - - if (itemToExtract > 0) { - energy.extractAEPower(retrieved, Actionable.MODULATE, PowerMultiplier.CONFIG); - - possible.setStackSize(itemToExtract); - final StackType ret = cell.extractItems(possible, Actionable.MODULATE, src); - - if (ret != null && src.isPlayer()) { - Stats.ItemsExtracted.addToPlayer(((PlayerSource) src).player, (int) ret.getStackSize()); - } - - return ret; - } - - return null; - } - - public static StackType poweredInsert(final IEnergySource energy, - final IMEInventory cell, final StackType input, final BaseActionSource src) { - final StackType possible = cell.injectItems((StackType) input.copy(), Actionable.SIMULATE, src); - - long stored = input.getStackSize(); - if (possible != null) { - stored -= possible.getStackSize(); - } - long typeMultiplier = input instanceof IAEFluidStack ? 1000 : 1; - - final double availablePower = energy.extractAEPower(Platform.ceilDiv(stored, typeMultiplier), - Actionable.SIMULATE, PowerMultiplier.CONFIG); - - final long itemToAdd = Math.min((long) (availablePower * typeMultiplier + 0.9), stored); - - if (itemToAdd > 0) { - energy.extractAEPower(Platform.ceilDiv(stored, typeMultiplier), Actionable.MODULATE, - PowerMultiplier.CONFIG); - - if (itemToAdd < input.getStackSize()) { - final long original = input.getStackSize(); - final StackType split = (StackType) input.copy(); - split.decStackSize(itemToAdd); - input.setStackSize(itemToAdd); - split.add(cell.injectItems(input, Actionable.MODULATE, src)); - - if (src.isPlayer()) { - final long diff = original - split.getStackSize(); - Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); - } - - return split; - } - - final StackType ret = cell.injectItems(input, Actionable.MODULATE, src); - - if (src.isPlayer()) { - final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize(); - Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); - } - - return ret; - } - - return input; - } - - @SuppressWarnings("unchecked") - public static void postChanges(final IStorageGrid gs, final ItemStack removed, final ItemStack added, - final BaseActionSource src) { - final IItemList itemChanges = AEApi.instance().storage().createItemList(); - final IItemList fluidChanges = AEApi.instance().storage().createFluidList(); - IMEInventory myItems = null; - IMEInventory myFluids = null; - if (removed != null) { - myItems = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.ITEMS); - - if (myItems != null) { - for (final IAEItemStack is : myItems.getAvailableItems(itemChanges)) { - is.setStackSize(-is.getStackSize()); - } - } - - myFluids = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.FLUIDS); - - if (myFluids != null) { - for (final IAEFluidStack is : myFluids.getAvailableItems(fluidChanges)) { - is.setStackSize(-is.getStackSize()); - } - } - } - - if (added != null) { - myItems = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.ITEMS); - - if (myItems != null) { - myItems.getAvailableItems(itemChanges); - } - - myFluids = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.FLUIDS); - - if (myFluids != null) { - myFluids.getAvailableItems(fluidChanges); - } - } - if (myItems == null) { - gs.postAlterationOfStoredItems(StorageChannel.FLUIDS, fluidChanges, src); - } else { - gs.postAlterationOfStoredItems(StorageChannel.ITEMS, itemChanges, src); - } - } - - public static > void postListChanges(final IItemList before, final IItemList after, - final IMEMonitorHandlerReceiver meMonitorPassthrough, final BaseActionSource source) { - final LinkedList changes = new LinkedList<>(); - - for (final T is : before) { - is.setStackSize(-is.getStackSize()); - } - - for (final T is : after) { - before.add(is); - } - - for (final T is : before) { - if (is.getStackSize() != 0) { - changes.add(is); - } - } - - if (!changes.isEmpty()) { - meMonitorPassthrough.postChange(null, changes, source); - } - } - - public static int generateTileHash(final TileEntity target) { - if (target == null) { - return 0; - } - - int hash = target.hashCode(); - - if (target instanceof ITileStorageMonitorable) { - return 0; - } else if (target instanceof TileEntityChest chest) { - chest.checkForAdjacentChests(); - if (chest.adjacentChestZNeg != null) { - hash ^= chest.adjacentChestZNeg.hashCode(); - } else if (chest.adjacentChestZPos != null) { - hash ^= chest.adjacentChestZPos.hashCode(); - } else if (chest.adjacentChestXPos != null) { - hash ^= chest.adjacentChestXPos.hashCode(); - } else if (chest.adjacentChestXNeg != null) { - hash ^= chest.adjacentChestXNeg.hashCode(); - } - } else if (target instanceof IInventory) { - hash ^= ((IInventory) target).getSizeInventory(); - - if (target instanceof ISidedInventory) { - for (final ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { - - final int[] sides = ((ISidedInventory) target).getAccessibleSlotsFromSide(dir.ordinal()); - - if (sides == null) { - return 0; - } - - int offset = 0; - for (final int side : sides) { - final int c = (side << (offset % 8)) ^ (1 << dir.ordinal()); - offset++; - hash = c + (hash << 6) + (hash << 16) - hash; - } - } - } - } - - return hash; - } - - public static boolean securityCheck(final GridNode a, final GridNode b) { - if (a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1) { - return false; - } else if (a.getLastSecurityKey() == b.getLastSecurityKey()) { - return false; - } - - final boolean a_isSecure = isPowered(a.getGrid()) && a.getLastSecurityKey() != -1; - final boolean b_isSecure = isPowered(b.getGrid()) && b.getLastSecurityKey() != -1; - - if (AEConfig.instance.isFeatureEnabled(AEFeature.LogSecurityAudits)) { - AELog.info("Audit: " + a_isSecure + " : " + b_isSecure + " @ " + a.getLastSecurityKey() + " vs " - + b.getLastSecurityKey() + " & " + a.getPlayerID() + " vs " + b.getPlayerID()); - } - - // can't do that son... - if (a_isSecure && b_isSecure) { - return true; - } - - if (!a_isSecure && b_isSecure) { - return checkPlayerPermissions(b.getGrid(), a.getPlayerID()); - } - - if (a_isSecure && !b_isSecure) { - return checkPlayerPermissions(a.getGrid(), b.getPlayerID()); - } - - return false; - } - - private static boolean isPowered(final IGrid grid) { - if (grid == null) { - return false; - } - - final IEnergyGrid eg = grid.getCache(IEnergyGrid.class); - return eg.isNetworkPowered(); - } - - private static boolean checkPlayerPermissions(final IGrid grid, final int playerID) { - if (grid == null) { - return false; - } - - final ISecurityGrid gs = grid.getCache(ISecurityGrid.class); - - if (gs == null) { - return false; - } - - if (!gs.isAvailable()) { - return false; - } - - return !gs.hasPermission(playerID, SecurityPermissions.BUILD); - } - - public static void configurePlayer(final EntityPlayer player, final ForgeDirection side, final TileEntity tile) { - player.yOffset = 1.8f; - - float yaw = 0.0f; - float pitch = 0.0f; - switch (side) { - case DOWN: - pitch = 90.0f; - player.yOffset = -1.8f; - break; - case EAST: - yaw = -90.0f; - break; - case NORTH: - yaw = 180.0f; - break; - case SOUTH: - yaw = 0.0f; - break; - case UNKNOWN: - break; - case UP: - pitch = 90.0f; - break; - case WEST: - yaw = 90.0f; - break; - } - - player.posX = tile.xCoord + 0.5; - player.posY = tile.yCoord + 0.5; - player.posZ = tile.zCoord + 0.5; - - player.rotationPitch = player.prevCameraPitch = player.cameraPitch = pitch; - player.rotationYaw = player.prevCameraYaw = player.cameraYaw = yaw; - } - - public static boolean canAccess(final AENetworkProxy gridProxy, final BaseActionSource src) { - try { - if (src.isPlayer()) { - return gridProxy.getSecurity().hasPermission(((PlayerSource) src).player, SecurityPermissions.BUILD); - } else if (src.isMachine()) { - final IActionHost te = ((MachineSource) src).via; - final IGridNode n = te.getActionableNode(); - if (n == null) { - return false; - } - - final int playerID = n.getPlayerID(); - return gridProxy.getSecurity().hasPermission(playerID, SecurityPermissions.BUILD); - } else { - return false; - } - } catch (final GridAccessException gae) { - return false; - } - } - - public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, - final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, - final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, - final IItemList items, final Actionable realForFake, - final IPartitionList filter) { - return extractItemsByRecipe(energySrc, mySrc, src, w, r, output, ci, providedTemplate, slot, items, realForFake, - filter, 1); - } - - public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, - final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, - final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, - final IItemList items, final Actionable realForFake, - final IPartitionList filter, int multiple) { - if (energySrc.extractAEPower(multiple, Actionable.SIMULATE, PowerMultiplier.CONFIG) > 0.9) { - if (providedTemplate == null) { - return null; - } - - final AEItemStack ae_req = AEItemStack.create(providedTemplate); - ae_req.setStackSize(multiple); - - if (filter == null || filter.isListed(ae_req)) { - final IAEItemStack ae_ext = src.extractItems(ae_req, realForFake, mySrc); - if (ae_ext != null) { - final ItemStack extracted = ae_ext.getItemStack(); - if (extracted != null) { - energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); - return extracted; - } - } - } - - final boolean checkFuzzy = ae_req.isOre() - || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE - || providedTemplate.hasTagCompound() || providedTemplate.isItemStackDamageable(); - - if (items != null && checkFuzzy) { - for (final IAEItemStack x : items) { - final ItemStack sh = x.getItemStack(); - if ((Platform.isSameItemType(providedTemplate, sh) || ae_req.sameOre(x)) - && !Platform.isSameItem(sh, output)) { // Platform.isSameItemType( sh, providedTemplate ) - final ItemStack cp = Platform.cloneItemStack(sh); - cp.stackSize = 1; - ci.setInventorySlotContents(slot, cp); - if (r.matches(ci, w) && Platform.isSameItem(r.getCraftingResult(ci), output)) { - final IAEItemStack ax = x.copy(); - ax.setStackSize(multiple); - if (filter == null || filter.isListed(ax)) { - final IAEItemStack ex = src.extractItems(ax, realForFake, mySrc); - if (ex != null) { - energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); - return ex.getItemStack(); - } - } - } - ci.setInventorySlotContents(slot, providedTemplate); - } - } - } - } - return null; - } - - public static boolean isSameItemType(final ItemStack that, final ItemStack other) { - if (that != null && other != null && that.getItem() == other.getItem()) { - if (that.isItemStackDamageable()) { - return true; - } - return that.getItemDamage() == other.getItemDamage(); - } - return false; - } - - public static boolean isSameItem(@Nullable final ItemStack left, @Nullable final ItemStack right) { - return left != null && right != null && left.isItemEqual(right); - } - - public static ItemStack cloneItemStack(final ItemStack a) { - return a.copy(); - } - - public static ItemStack getContainerItem(final ItemStack stackInSlot) { - if (stackInSlot == null) { - return null; - } - - final Item i = stackInSlot.getItem(); - if (i == null || !i.hasContainerItem(stackInSlot)) { - if (stackInSlot.stackSize > 1) { - stackInSlot.stackSize--; - return stackInSlot; - } - return null; - } - - ItemStack ci = i.getContainerItem(stackInSlot.copy()); - if (ci != null && ci.isItemStackDamageable() && ci.getItemDamage() > ci.getMaxDamage()) { - ci = null; - } - - return ci; - } - - public static void notifyBlocksOfNeighbors(final World worldObj, final int xCoord, final int yCoord, - final int zCoord) { - if (!worldObj.isRemote) { - TickHandler.INSTANCE.addCallable(worldObj, new BlockUpdate(xCoord, yCoord, zCoord)); - } - } - - public static boolean canRepair(final AEFeature type, final ItemStack a, final ItemStack b) { - if (b == null || a == null) { - return false; - } - - if (type == AEFeature.CertusQuartzTools) { - final IItemDefinition certusQuartzCrystal = AEApi.instance().definitions().materials() - .certusQuartzCrystal(); - - return certusQuartzCrystal.isSameAs(b); - } - - if (type == AEFeature.NetherQuartzTools) { - return Items.quartz == b.getItem(); - } - - return false; - } - - public static Object findPreferred(final ItemStack[] is) { - final IParts parts = AEApi.instance().definitions().parts(); - - for (final ItemStack stack : is) { - if (parts.cableGlass().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableCovered().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableSmart().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableDense().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableDenseCovered().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableUltraDenseCovered().sameAs(AEColor.Transparent, stack)) { - return stack; - } - - if (parts.cableUltraDenseSmart().sameAs(AEColor.Transparent, stack)) { - return stack; - } - } - - return is; - } - - public static void sendChunk(final Chunk c, final int verticalBits) { - try { - final WorldServer ws = (WorldServer) c.worldObj; - final PlayerManager pm = ws.getPlayerManager(); - - if (getOrCreateChunkWatcher == null) { - getOrCreateChunkWatcher = ReflectionHelper.findMethod(PlayerManager.class, pm, - new String[] { "getOrCreateChunkWatcher", "func_72690_a" }, int.class, int.class, - boolean.class); - } - - if (getOrCreateChunkWatcher != null) { - final Object playerInstance = getOrCreateChunkWatcher.invoke(pm, c.xPosition, c.zPosition, false); - if (playerInstance != null) { - Platform.playerInstance = playerInstance.getClass(); - - if (sendToAllPlayersWatchingChunk == null) { - sendToAllPlayersWatchingChunk = ReflectionHelper.findMethod(Platform.playerInstance, - playerInstance, new String[] { "sendToAllPlayersWatchingChunk", "func_151251_a" }, - Packet.class); - } - - if (sendToAllPlayersWatchingChunk != null) { - sendToAllPlayersWatchingChunk.invoke(playerInstance, - new S21PacketChunkData(c, false, verticalBits)); - } - } - } - } catch (final Throwable t) { - AELog.debug(t); - } - } - - public static AxisAlignedBB getPrimaryBox(final ForgeDirection side, final int facadeThickness) { - switch (side) { - case DOWN -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, (facadeThickness) / 16.0, 1.0); - } - case EAST -> { - return AxisAlignedBB.getBoundingBox((16.0 - facadeThickness) / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0); - } - case NORTH -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, (facadeThickness) / 16.0); - } - case SOUTH -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, (16.0 - facadeThickness) / 16.0, 1.0, 1.0, 1.0); - } - case UP -> { - return AxisAlignedBB.getBoundingBox(0.0, (16.0 - facadeThickness) / 16.0, 0.0, 1.0, 1.0, 1.0); - } - case WEST -> { - return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, (facadeThickness) / 16.0, 1.0, 1.0); - } - default -> { - } - } - return AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1); - } - - public static float getEyeOffset(final EntityPlayer player) { - assert player.worldObj.isRemote : "Valid only on client"; - return (float) (player.posY + player.getEyeHeight() - player.getDefaultEyeHeight()); - } - - public static void addStat(final int playerID, final Achievement achievement) { - final EntityPlayer p = AEApi.instance().registries().players().findPlayer(playerID); - if (p != null) { - p.addStat(achievement, 1); - } - } - - public static boolean isRecipePrioritized(final ItemStack what) { - final IMaterials materials = AEApi.instance().definitions().materials(); - - boolean isPurified = materials.purifiedCertusQuartzCrystal().isSameAs(what); - isPurified |= materials.purifiedFluixCrystal().isSameAs(what); - isPurified |= materials.purifiedNetherQuartzCrystal().isSameAs(what); - - return isPurified; - } - - public static ItemStack loadItemStackFromNBT(NBTTagCompound tagCompound) { - ItemStack stack = ItemStack.loadItemStackFromNBT(tagCompound); - if (stack != null) { - stack.stackSize = tagCompound.getInteger("Count"); - } - return stack; - } - - public static NBTTagCompound writeItemStackToNBT(ItemStack is, NBTTagCompound tagCompound) { - is.writeToNBT(tagCompound); - tagCompound.setInteger("Count", is.stackSize); - return tagCompound; - } - - public static IAEItemStack getAEStackInSlot(Slot slot) { - if (slot == null || !slot.getHasStack()) { - return null; - } - - if (slot instanceof SlotME) { - return ((SlotME) slot).getAEStack(); - } - - if (slot instanceof SlotFake) { - return ((SlotFake) slot).getAEStack(); - } - - return AEItemStack.create(slot.getStack()); - } - - /** - * @return (a divided by b) rounded up - */ - public static long ceilDiv(long a, long b) { - return Math.addExact(Math.addExact(a, b), -1) / b; - } - - /** - * From bytes to K,M,G,T like - * - * @param n Bytes number - * @return String that like 1G or 1.4T - */ - public static String formatByteLong(final long n) { - int storageUnit = Long.toBinaryString(n).length() / 10; - final DecimalFormat df = new DecimalFormat("#.##"); - switch(storageUnit) { - case 6: - return df.format((double)n / 1152921504606846976d) + " EB"; - case 5: - return df.format((double)n / 1125899906842624d) + " PB"; - case 4: - return df.format((double)n / 1099511627776d) + " TB"; - case 3: - return df.format((double)n / 1073741824d) + " GB"; - case 2: - return df.format((double)n / 1048576d) + " MB"; - case 1: - return df.format((double)n / 1024d) + " kB"; - case 0: - return df.format((double) n) + " B"; - default: - return df.format((double) n) + " B"; - } - } + public static final Block AIR_BLOCK = Blocks.air; + + public static final int DEF_OFFSET = 16; + + /* + * random source, use it for item drop locations... + */ + private static final Random RANDOM_GENERATOR = new Random(); + private static final WeakHashMap FAKE_PLAYERS = new WeakHashMap<>(); + private static Field tagList; + private static Class playerInstance; + private static Method getOrCreateChunkWatcher; + private static Method sendToAllPlayersWatchingChunk; + private static GameProfile fakeProfile = new GameProfile( + UUID.fromString("839eb18c-50bc-400c-8291-9383f09763e7"), + "[AE2Player]"); + + public static Random getRandom() { + return RANDOM_GENERATOR; + } + + public static float getRandomFloat() { + return RANDOM_GENERATOR.nextFloat(); + } + + /** + * Seed a random number generator from a world seed and grid location. The grid can be any arbitrary set of + * coordinates, e.g. chunk position or block position. This method guarantees that for the same inputs (worldSeed, + * x, z) the same seed will be used. + * + * @param rng The generator to re-seed. + * @param worldSeed Global seed independent of the grid position + * @param x X location in the grid + * @param z Z location in the grid + */ + public static void seedFromGrid(final Random rng, final long worldSeed, final long x, final long z) { + rng.setSeed(worldSeed); + final long xSeed = rng.nextLong() >> 2 + 1L; + final long zSeed = rng.nextLong() >> 2 + 1L; + final long gridSeed = (xSeed * x + zSeed * z) ^ worldSeed; + rng.setSeed(gridSeed); + } + + /** + * This displays the value for encoded longs ( double *100 ) + * + * @param n to be formatted long value + * @param isRate if true it adds a /t to the formatted string + * @return formatted long value + */ + public static String formatPowerLong(final long n, final boolean isRate) { + double p = ((double) n) / 100; + + final PowerUnits displayUnits = AEConfig.instance.selectedPowerUnit(); + p = PowerUnits.AE.convertTo(displayUnits, p); + + String unitName = displayUnits.name(); + + if (displayUnits == PowerUnits.WA) { + unitName = "J"; + } + + if (displayUnits == PowerUnits.MK) { + unitName = "J"; + } + + final String[] preFixes = { "k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y" }; + String level = ""; + int offset = 0; + while (p > 1000 && offset < preFixes.length) { + p /= 1000; + level = preFixes[offset]; + offset++; + } + + final DecimalFormat df = new DecimalFormat("#.##"); + return df.format(p) + ' ' + level + unitName + (isRate ? "/t" : ""); + } + + public static ForgeDirection crossProduct(final ForgeDirection forward, final ForgeDirection up) { + final int west_x = forward.offsetY * up.offsetZ - forward.offsetZ * up.offsetY; + final int west_y = forward.offsetZ * up.offsetX - forward.offsetX * up.offsetZ; + final int west_z = forward.offsetX * up.offsetY - forward.offsetY * up.offsetX; + + return switch (west_x + west_y * 2 + west_z * 3) { + case 1 -> ForgeDirection.EAST; + case -1 -> ForgeDirection.WEST; + case 2 -> ForgeDirection.UP; + case -2 -> ForgeDirection.DOWN; + case 3 -> ForgeDirection.SOUTH; + case -3 -> ForgeDirection.NORTH; + default -> ForgeDirection.UNKNOWN; + }; + + } + + public static T rotateEnum(T ce, final boolean backwards, final EnumSet validOptions) { + do { + if (backwards) { + ce = prevEnum(ce); + } else { + ce = nextEnum(ce); + } + } while (!validOptions.contains(ce) || isNotValidSetting(ce)); + + return ce; + } + + /* + * Simple way to cycle an enum... + */ + private static T prevEnum(final T ce) { + final EnumSet valList = EnumSet.allOf(ce.getClass()); + + int pLoc = ce.ordinal() - 1; + if (pLoc < 0) { + pLoc = valList.size() - 1; + } + + if (pLoc < 0 || pLoc >= valList.size()) { + pLoc = 0; + } + + int pos = 0; + for (final Object g : valList) { + if (pos == pLoc) { + return (T) g; + } + pos++; + } + + return null; + } + + /* + * Simple way to cycle an enum... + */ + public static T nextEnum(final T ce) { + final EnumSet valList = EnumSet.allOf(ce.getClass()); + + int pLoc = ce.ordinal() + 1; + if (pLoc >= valList.size()) { + pLoc = 0; + } + + if (pLoc < 0 || pLoc >= valList.size()) { + pLoc = 0; + } + + int pos = 0; + for (final Object g : valList) { + if (pos == pLoc) { + return (T) g; + } + pos++; + } + + return null; + } + + private static boolean isNotValidSetting(final Enum e) { + if (e == SortOrder.INVTWEAKS && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.InvTweaks)) { + return true; + } + + if (e == SearchBoxMode.NEI_AUTOSEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI)) { + return true; + } + + return e == SearchBoxMode.NEI_MANUAL_SEARCH && !IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI); + } + + public static void openGUI(@Nonnull final EntityPlayer p, @Nullable final TileEntity tile, + @Nullable final ForgeDirection side, @Nonnull final GuiBridge type) { + if (isClient()) { + return; + } + + int x = (int) p.posX; + int y = (int) p.posY; + int z = (int) p.posZ; + if (tile != null) { + x = tile.xCoord; + y = tile.yCoord; + z = tile.zCoord; + } + + if ((type.getType().isItem() && tile == null) || type.hasPermissions(tile, x, y, z, side, p)) { + if (tile == null && type.getType() == GuiHostType.ITEM) { + p.openGui( + AppEng.instance(), + type.ordinal() << 5 | (1 << 4), + p.getEntityWorld(), + p.inventory.currentItem, + 0, + 0); + } else if (tile == null || type.getType() == GuiHostType.ITEM) { + p.openGui(AppEng.instance(), type.ordinal() << 5 | (1 << 3), p.getEntityWorld(), x, y, z); + } else { + p.openGui(AppEng.instance(), type.ordinal() << 5 | (side.ordinal()), tile.getWorldObj(), x, y, z); + } + } + } + + /* + * returns true if the code is on the client. + */ + public static boolean isClient() { + return FMLCommonHandler.instance().getEffectiveSide().isClient(); + } + + public static boolean hasPermissions(final DimensionalCoord dc, final EntityPlayer player) { + return dc.getWorld().canMineBlock(player, dc.x, dc.y, dc.z); + } + + /* + * Checks to see if a block is air? + */ + public static boolean isBlockAir(final World w, final int x, final int y, final int z) { + try { + return w.getBlock(x, y, z).isAir(w, x, y, z); + } catch (final Throwable e) { + return false; + } + } + + /* + * Lots of silliness to try and account for weird tag related junk, basically requires that two tags have at least + * something in their tags before it wasts its time comparing them. + */ + private static boolean sameStackStags(final ItemStack a, final ItemStack b) { + if (a == null && b == null) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a == b) { + return true; + } + + final NBTTagCompound ta = a.getTagCompound(); + final NBTTagCompound tb = b.getTagCompound(); + if (ta == tb) { + return true; + } + + if ((ta == null && tb == null) || (ta != null && ta.hasNoTags() && tb == null) + || (tb != null && tb.hasNoTags() && ta == null) + || (ta != null && ta.hasNoTags() && tb != null && tb.hasNoTags())) { + return true; + } + + if ((ta == null && tb != null) || (ta != null && tb == null)) { + return false; + } + + // if both tags are shared this is easy... + if (AESharedNBT.isShared(ta) && AESharedNBT.isShared(tb)) { + return ta == tb; + } + + return NBTEqualityTest(ta, tb); + } + + /* + * recursive test for NBT Equality, this was faster then trying to compare / generate hashes, its also more reliable + * then the vanilla version which likes to fail when NBT Compound data changes order, it is pretty expensive + * performance wise, so try an use shared tag compounds as long as the system remains in AE. + */ + public static boolean NBTEqualityTest(final NBTBase left, final NBTBase right) { + // same type? + final byte id = left.getId(); + if (id == right.getId()) { + switch (id) { + case 10 -> { + final NBTTagCompound ctA = (NBTTagCompound) left; + final NBTTagCompound ctB = (NBTTagCompound) right; + + final Set cA = ctA.func_150296_c(); + final Set cB = ctB.func_150296_c(); + + if (cA.size() != cB.size()) { + return false; + } + + for (final String name : cA) { + final NBTBase tag = ctA.getTag(name); + final NBTBase aTag = ctB.getTag(name); + if (aTag == null) { + return false; + } + + if (!NBTEqualityTest(tag, aTag)) { + return false; + } + } + + return true; + } + case 9 -> // ) // A instanceof NBTTagList ) + { + final NBTTagList lA = (NBTTagList) left; + final NBTTagList lB = (NBTTagList) right; + if (lA.tagCount() != lB.tagCount()) { + return false; + } + + final List tag = tagList(lA); + final List aTag = tagList(lB); + if (tag.size() != aTag.size()) { + return false; + } + + for (int x = 0; x < tag.size(); x++) { + if (aTag.get(x) == null) { + return false; + } + + if (!NBTEqualityTest(tag.get(x), aTag.get(x))) { + return false; + } + } + + return true; + } + case 1 -> { // ( A instanceof NBTTagByte ) + return ((NBTBase.NBTPrimitive) left).func_150287_d() + == ((NBTBase.NBTPrimitive) right).func_150287_d(); + } + case 4 -> { // else if ( A instanceof NBTTagLong ) + return ((NBTBase.NBTPrimitive) left).func_150291_c() + == ((NBTBase.NBTPrimitive) right).func_150291_c(); + } + case 8 -> { // else if ( A instanceof NBTTagString ) + return ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()) + || ((NBTTagString) left).func_150285_a_().equals(((NBTTagString) right).func_150285_a_()); + } + case 6 -> { // else if ( A instanceof NBTTagDouble ) + return ((NBTBase.NBTPrimitive) left).func_150286_g() + == ((NBTBase.NBTPrimitive) right).func_150286_g(); + } + case 5 -> { // else if ( A instanceof NBTTagFloat ) + return ((NBTBase.NBTPrimitive) left).func_150288_h() + == ((NBTBase.NBTPrimitive) right).func_150288_h(); + } + case 3 -> { // else if ( A instanceof NBTTagInt ) + return ((NBTBase.NBTPrimitive) left).func_150287_d() + == ((NBTBase.NBTPrimitive) right).func_150287_d(); + } + default -> { + return left.equals(right); + } + } + } + + return false; + } + + private static List tagList(final NBTTagList lB) { + if (tagList == null) { + try { + tagList = lB.getClass().getDeclaredField("tagList"); + } catch (final Throwable t) { + try { + tagList = lB.getClass().getDeclaredField("field_74747_a"); + } catch (final Throwable z) { + AELog.debug(t); + AELog.debug(z); + } + } + } + + try { + tagList.setAccessible(true); + return (List) tagList.get(lB); + } catch (final Throwable t) { + AELog.debug(t); + } + + return new ArrayList<>(); + } + + /* + * Orderless hash on NBT Data, used to work thought huge piles fast, but ignores the order just in case MC decided + * to change it... WHICH IS BAD... + */ + public static int NBTOrderlessHash(final NBTBase nbt) { + // same type? + int hash = 0; + final byte id = nbt.getId(); + hash += id; + switch (id) { + case 10 -> { + final NBTTagCompound ctA = (NBTTagCompound) nbt; + + final Set cA = ctA.func_150296_c(); + + for (final String name : cA) { + hash += name.hashCode() ^ NBTOrderlessHash(ctA.getTag(name)); + } + + return hash; + } + case 9 -> // ) // A instanceof NBTTagList ) + { + final NBTTagList lA = (NBTTagList) nbt; + hash += 9 * lA.tagCount(); + + final List l = tagList(lA); + for (int x = 0; x < l.size(); x++) { + hash += ((Integer) x).hashCode() ^ NBTOrderlessHash(l.get(x)); + } + + return hash; + } + case 1 -> { // ( A instanceof NBTTagByte ) + return hash + ((NBTBase.NBTPrimitive) nbt).func_150290_f(); + } + case 4 -> { // else if ( A instanceof NBTTagLong ) + return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150291_c(); + } + case 8 -> { // else if ( A instanceof NBTTagString ) + return hash + ((NBTTagString) nbt).func_150285_a_().hashCode(); + } + case 6 -> { // else if ( A instanceof NBTTagDouble ) + return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150286_g(); + } + case 5 -> { // else if ( A instanceof NBTTagFloat ) + return hash + (int) ((NBTBase.NBTPrimitive) nbt).func_150288_h(); + } + case 3 -> { // else if ( A instanceof NBTTagInt ) + return hash + ((NBTBase.NBTPrimitive) nbt).func_150287_d(); + } + default -> { + return hash; + } + } + } + + private static IRecipe lastUsedRecipe = null; + + /* + * The usual version of this returns an ItemStack, this version returns the recipe. + */ + public static IRecipe findMatchingRecipe(final InventoryCrafting inventoryCrafting, final World par2World) { + if (lastUsedRecipe != null && lastUsedRecipe.matches(inventoryCrafting, par2World)) return lastUsedRecipe; + + final CraftingManager cm = CraftingManager.getInstance(); + final List rl = cm.getRecipeList(); + + for (final IRecipe r : rl) { + if (r.matches(inventoryCrafting, par2World)) { + lastUsedRecipe = r; + return r; + } + } + + return null; + } + + public static ItemStack[] getBlockDrops(final World w, final int x, final int y, final int z) { + List out = new ArrayList<>(); + final Block which = w.getBlock(x, y, z); + + if (which != null) { + out = which.getDrops(w, x, y, z, w.getBlockMetadata(x, y, z), 0); + } + + if (out == null) { + return new ItemStack[0]; + } + return out.toArray(new ItemStack[0]); + } + + public static ForgeDirection cycleOrientations(final ForgeDirection dir, final boolean upAndDown) { + if (upAndDown) { + return switch (dir) { + case NORTH -> ForgeDirection.SOUTH; + case SOUTH -> ForgeDirection.EAST; + case EAST -> ForgeDirection.WEST; + case WEST -> ForgeDirection.NORTH; + case UP -> ForgeDirection.UP; + case DOWN -> ForgeDirection.DOWN; + case UNKNOWN -> ForgeDirection.UNKNOWN; + }; + } else { + return switch (dir) { + case UP -> ForgeDirection.DOWN; + case DOWN -> ForgeDirection.NORTH; + case NORTH -> ForgeDirection.SOUTH; + case SOUTH -> ForgeDirection.EAST; + case EAST -> ForgeDirection.WEST; + case WEST -> ForgeDirection.UP; + case UNKNOWN -> ForgeDirection.UNKNOWN; + }; + } + } + + /* + * Creates / or loads previous NBT Data on items, used for editing items owned by AE. + */ + public static NBTTagCompound openNbtData(final ItemStack i) { + NBTTagCompound compound = i.getTagCompound(); + + if (compound == null) { + i.setTagCompound(compound = new NBTTagCompound()); + } + + return compound; + } + + /* + * Generates Item entities in the world similar to how items are generally dropped. + */ + public static void spawnDrops(final World w, final int x, final int y, final int z, final List drops) { + if (isServer()) { + for (final ItemStack i : drops) { + if (i != null) { + if (i.stackSize > 0) { + final double offset_x = (getRandomInt() % 32 - 16) / 82; + final double offset_y = (getRandomInt() % 32 - 16) / 82; + final double offset_z = (getRandomInt() % 32 - 16) / 82; + final EntityItem ei = new EntityItem( + w, + 0.5 + offset_x + x, + 0.5 + offset_y + y, + 0.2 + offset_z + z, + i.copy()); + w.spawnEntityInWorld(ei); + } + } + } + } + } + + /* + * returns true if the code is on the server. + */ + public static boolean isServer() { + return FMLCommonHandler.instance().getEffectiveSide().isServer(); + } + + public static int getRandomInt() { + return Math.abs(RANDOM_GENERATOR.nextInt()); + } + + /* + * Utility function to get the full inventory for a Double Chest in the World. + */ + public static IInventory GetChestInv(final Object te) { + TileEntityChest teA = (TileEntityChest) te; + TileEntity teB = null; + final Block myBlockID = teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord); + + if (teA.getWorldObj().getBlock(teA.xCoord + 1, teA.yCoord, teA.zCoord) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord + 1, teA.yCoord, teA.zCoord); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } + } + + if (teB == null) { + if (teA.getWorldObj().getBlock(teA.xCoord - 1, teA.yCoord, teA.zCoord) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord - 1, teA.yCoord, teA.zCoord); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } else { + final TileEntityChest x = teA; + teA = (TileEntityChest) teB; + teB = x; + } + } + } + + if (teB == null) { + if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord + 1) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord + 1); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } + } + } + + if (teB == null) { + if (teA.getWorldObj().getBlock(teA.xCoord, teA.yCoord, teA.zCoord - 1) == myBlockID) { + teB = teA.getWorldObj().getTileEntity(teA.xCoord, teA.yCoord, teA.zCoord - 1); + if (!(teB instanceof TileEntityChest)) { + teB = null; + } else { + final TileEntityChest x = teA; + teA = (TileEntityChest) teB; + teB = x; + } + } + } + + if (teB == null) { + return teA; + } + + return new InventoryLargeChest("", teA, (IInventory) teB); + } + + public static boolean isModLoaded(final String modid) { + try { + // if this fails for some reason, try the other method. + return Loader.isModLoaded(modid); + } catch (final Throwable ignored) {} + + for (final ModContainer f : Loader.instance().getActiveModList()) { + if (f.getModId().equals(modid)) { + return true; + } + } + return false; + } + + public static ItemStack findMatchingRecipeOutput(final InventoryCrafting ic, final World worldObj) { + return CraftingManager.getInstance().findMatchingRecipe(ic, worldObj); + } + + @SideOnly(Side.CLIENT) + public static List getTooltip(final Object o) { + if (o == null) { + return new ArrayList<>(); + } + + ItemStack itemStack = null; + if (o instanceof AEItemStack ais) { + return ais.getToolTip(); + } else if (o instanceof ItemStack) { + itemStack = (ItemStack) o; + } else { + return new ArrayList<>(); + } + + try { + return itemStack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } catch (final Exception errB) { + return new ArrayList<>(); + } + } + + public static String getModId(final IAEItemStack is) { + if (is == null) { + return "** Null"; + } + + final String n = ((AEItemStack) is).getModID(); + return n == null ? "** Null" : n; + } + + public static String getItemDisplayName(final Object o) { + if (o == null) { + return "** Null"; + } + + ItemStack itemStack = null; + if (o instanceof AEItemStack) { + final String n = ((AEItemStack) o).getDisplayName(); + return n == null ? "** Null" : n; + } else if (o instanceof ItemStack) { + itemStack = (ItemStack) o; + } else { + return "**Invalid Object"; + } + + try { + String name = itemStack.getDisplayName(); + if (name == null || name.isEmpty()) { + name = itemStack.getItem().getUnlocalizedName(itemStack); + } + return name == null ? "** Null" : name; + } catch (final Exception errA) { + try { + final String n = itemStack.getUnlocalizedName(); + return n == null ? "** Null" : n; + } catch (final Exception errB) { + return "** Exception"; + } + } + } + + public static boolean hasSpecialComparison(final IAEItemStack willAdd) { + if (willAdd == null) { + return false; + } + final IAETagCompound tag = willAdd.getTagCompound(); + return tag != null && tag.getSpecialComparison() != null; + } + + public static boolean hasSpecialComparison(final ItemStack willAdd) { + if (AESharedNBT.isShared(willAdd.getTagCompound())) { + if (((IAETagCompound) willAdd.getTagCompound()).getSpecialComparison() != null) { + return true; + } + } + return false; + } + + public static boolean isWrench(final EntityPlayer player, final ItemStack stack, final int x, final int y, + final int z) { + if (stack != null) { + Item itemWrench = stack.getItem(); + if (itemWrench instanceof IAEWrench wrench) { + return wrench.canWrench(stack, player, x, y, z); + } + + if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.CoFHWrench) + && itemWrench instanceof IToolHammer wrench) { + return wrench.isUsable(stack, player, x, y, z); + } + + if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.BuildCraftCore) + && itemWrench instanceof IToolWrench wrench) { + return wrench.canWrench(player, x, y, z); + } + } + return false; + } + + public static boolean isChargeable(final ItemStack i) { + if (i == null) { + return false; + } + final Item it = i.getItem(); + if (it instanceof IAEItemPowerStorage) { + return ((IAEItemPowerStorage) it).getPowerFlow(i) != AccessRestriction.READ; + } + return false; + } + + public static EntityPlayer getPlayer(final WorldServer w) { + if (w == null) { + throw new InvalidParameterException("World is null."); + } + + final EntityPlayer wrp = FAKE_PLAYERS.get(w); + if (wrp != null) { + return wrp; + } + + final EntityPlayer p = FakePlayerFactory.get(w, fakeProfile); + FAKE_PLAYERS.put(w, p); + return p; + } + + public static int MC2MEColor(final int color) { + switch (color) { + case 4: // "blue" + return 0; + case 0: // "black" + return 1; + case 15: // "white" + return 2; + case 3: // "brown" + return 3; + case 1: // "red" + return 4; + case 11: // "yellow" + return 5; + case 2: // "green" + return 6; + + case 5: // "purple" + case 6: // "cyan" + case 7: // "silver" + case 8: // "gray" + case 9: // "pink" + case 10: // "lime" + case 12: // "lightBlue" + case 13: // "magenta" + case 14: // "orange" + } + return -1; + } + + public static int findEmpty(final Object[] l) { + for (int x = 0; x < l.length; x++) { + if (l[x] == null) { + return x; + } + } + return -1; + } + + public static T pickRandom(final Collection outs) { + int index = RANDOM_GENERATOR.nextInt(outs.size()); + final Iterator i = outs.iterator(); + while (i.hasNext() && index > 0) { + index--; + i.next(); + } + index--; + if (i.hasNext()) { + return i.next(); + } + return null; // wtf? + } + + public static ForgeDirection rotateAround(final ForgeDirection forward, final ForgeDirection axis) { + if (axis == ForgeDirection.UNKNOWN || forward == ForgeDirection.UNKNOWN) { + return forward; + } + + switch (forward) { + case DOWN: + switch (axis) { + case DOWN -> { + return forward; + } + case UP -> { + return forward; + } + case NORTH -> { + return ForgeDirection.EAST; + } + case SOUTH -> { + return ForgeDirection.WEST; + } + case EAST -> { + return ForgeDirection.NORTH; + } + case WEST -> { + return ForgeDirection.SOUTH; + } + default -> {} + } + break; + case UP: + switch (axis) { + case NORTH -> { + return ForgeDirection.WEST; + } + case SOUTH -> { + return ForgeDirection.EAST; + } + case EAST -> { + return ForgeDirection.SOUTH; + } + case WEST -> { + return ForgeDirection.NORTH; + } + default -> {} + } + break; + case NORTH: + switch (axis) { + case UP -> { + return ForgeDirection.WEST; + } + case DOWN -> { + return ForgeDirection.EAST; + } + case EAST -> { + return ForgeDirection.UP; + } + case WEST -> { + return ForgeDirection.DOWN; + } + default -> {} + } + break; + case SOUTH: + switch (axis) { + case UP -> { + return ForgeDirection.EAST; + } + case DOWN -> { + return ForgeDirection.WEST; + } + case EAST -> { + return ForgeDirection.DOWN; + } + case WEST -> { + return ForgeDirection.UP; + } + default -> {} + } + break; + case EAST: + switch (axis) { + case UP -> { + return ForgeDirection.NORTH; + } + case DOWN -> { + return ForgeDirection.SOUTH; + } + case NORTH -> { + return ForgeDirection.UP; + } + case SOUTH -> { + return ForgeDirection.DOWN; + } + default -> {} + } + case WEST: + switch (axis) { + case UP -> { + return ForgeDirection.SOUTH; + } + case DOWN -> { + return ForgeDirection.NORTH; + } + case NORTH -> { + return ForgeDirection.DOWN; + } + case SOUTH -> { + return ForgeDirection.UP; + } + default -> {} + } + default: + break; + } + return forward; + } + + @SideOnly(Side.CLIENT) + public static String gui_localize(final String string) { + return StatCollector.translateToLocal(string); + } + + public static boolean isSameItemPrecise(@Nullable final ItemStack is, @Nullable final ItemStack filter) { + return isSameItem(is, filter) && sameStackStags(is, filter); + } + + public static boolean isSameItemFuzzy(final ItemStack a, final ItemStack b, final FuzzyMode mode) { + if (a == null && b == null) { + return true; + } + + if (a == null) { + return false; + } + + if (b == null) { + return false; + } + + /* + * if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! a.getHasSubtypes() && a.itemID == + * b.itemID ) { return (a.getItemDamage() > 0) == (b.getItemDamage() > 0); } + */ + + // test damageable items.. + if (a.getItem() != null && b.getItem() != null && a.getItem().isDamageable() && a.getItem() == b.getItem()) { + try { + if (mode == FuzzyMode.IGNORE_ALL) { + return true; + } else if (mode == FuzzyMode.PERCENT_99) { + return (a.getItemDamageForDisplay() > 1) == (b.getItemDamageForDisplay() > 1); + } else { + final float percentDamagedOfA = 1.0f + - (float) a.getItemDamageForDisplay() / (float) a.getMaxDamage(); + final float percentDamagedOfB = 1.0f + - (float) b.getItemDamageForDisplay() / (float) b.getMaxDamage(); + + return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); + } + } catch (final Throwable e) { + if (mode == FuzzyMode.IGNORE_ALL) { + return true; + } else if (mode == FuzzyMode.PERCENT_99) { + return (a.getItemDamage() > 1) == (b.getItemDamage() > 1); + } else { + final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage(); + final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage(); + + return (percentDamagedOfA > mode.breakPoint) == (percentDamagedOfB > mode.breakPoint); + } + } + } + + final OreReference aOR = OreHelper.INSTANCE.isOre(a); + final OreReference bOR = OreHelper.INSTANCE.isOre(b); + + if (OreHelper.INSTANCE.sameOre(aOR, bOR)) { + return true; + } + + /* + * // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return OreID == getOreID( b ); if ( + * Mode != FuzzyMode.IGNORE_ALL ) { if ( a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a = + * Platform.getSharedItemStack( AEItemStack.create( a ) ); } if ( b.hasTagCompound() && !isShared( + * b.getTagCompound() ) ) { b = Platform.getSharedItemStack( AEItemStack.create( b ) ); } // test regular items + * with damage values and what not... if ( isShared( a.getTagCompound() ) && isShared( b.getTagCompound() ) && + * a.itemID == b.itemID ) { return ((AppEngSharedNBTTagCompound) a.getTagCompound()).compareFuzzyWithRegistry( + * (AppEngSharedNBTTagCompound) b.getTagCompound() ); } } + */ + + return a.isItemEqual(b); + } + + public static LookDirection getPlayerRay(final EntityPlayer player, final float eyeOffset) { + final float f = 1.0F; + final float f1 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * f; + final float f2 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * f; + final double d0 = player.prevPosX + (player.posX - player.prevPosX) * f; + final double d1 = eyeOffset; + final double d2 = player.prevPosZ + (player.posZ - player.prevPosZ) * f; + + final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); + final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); + final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); + final float f5 = -MathHelper.cos(-f1 * 0.017453292F); + final float f6 = MathHelper.sin(-f1 * 0.017453292F); + final float f7 = f4 * f5; + final float f8 = f3 * f5; + double d3 = 5.0D; + + if (player instanceof EntityPlayerMP) { + d3 = ((EntityPlayerMP) player).theItemInWorldManager.getBlockReachDistance(); + } + final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); + return new LookDirection(vec3, vec31); + } + + public static MovingObjectPosition rayTrace(final EntityPlayer p, final boolean hitBlocks, + final boolean hitEntities) { + final World w = p.getEntityWorld(); + + final float f = 1.0F; + float f1 = p.prevRotationPitch + (p.rotationPitch - p.prevRotationPitch) * f; + final float f2 = p.prevRotationYaw + (p.rotationYaw - p.prevRotationYaw) * f; + final double d0 = p.prevPosX + (p.posX - p.prevPosX) * f; + final double d1 = p.prevPosY + (p.posY - p.prevPosY) * f + 1.62D - p.yOffset; + final double d2 = p.prevPosZ + (p.posZ - p.prevPosZ) * f; + final Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2); + final float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI); + final float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI); + final float f5 = -MathHelper.cos(-f1 * 0.017453292F); + final float f6 = MathHelper.sin(-f1 * 0.017453292F); + final float f7 = f4 * f5; + final float f8 = f3 * f5; + final double d3 = 32.0D; + + final Vec3 vec31 = vec3.addVector(f7 * d3, f6 * d3, f8 * d3); + + final AxisAlignedBB bb = AxisAlignedBB.getBoundingBox( + Math.min(vec3.xCoord, vec31.xCoord), + Math.min(vec3.yCoord, vec31.yCoord), + Math.min(vec3.zCoord, vec31.zCoord), + Math.max(vec3.xCoord, vec31.xCoord), + Math.max(vec3.yCoord, vec31.yCoord), + Math.max(vec3.zCoord, vec31.zCoord)).expand(16, 16, 16); + + Entity entity = null; + double closest = 9999999.0D; + if (hitEntities) { + final List list = w.getEntitiesWithinAABBExcludingEntity(p, bb); + + for (Object o : list) { + final Entity entity1 = (Entity) o; + + if (!entity1.isDead && entity1 != p && !(entity1 instanceof EntityItem)) { + if (entity1.isEntityAlive()) { + // prevent killing / flying of mounts. + if (entity1.riddenByEntity == p) { + continue; + } + + f1 = 0.3F; + final AxisAlignedBB boundingBox = entity1.boundingBox.expand(f1, f1, f1); + final MovingObjectPosition movingObjectPosition = boundingBox.calculateIntercept(vec3, vec31); + + if (movingObjectPosition != null) { + final double nd = vec3.squareDistanceTo(movingObjectPosition.hitVec); + + if (nd < closest) { + entity = entity1; + closest = nd; + } + } + } + } + } + } + + MovingObjectPosition pos = null; + Vec3 vec = null; + + if (hitBlocks) { + vec = Vec3.createVectorHelper(d0, d1, d2); + pos = w.rayTraceBlocks(vec3, vec31, true); + } + + if (entity != null && pos != null && pos.hitVec.squareDistanceTo(vec) > closest) { + pos = new MovingObjectPosition(entity); + } else if (entity != null && pos == null) { + pos = new MovingObjectPosition(entity); + } + + return pos; + } + + public static long nanoTime() { + // if ( Configuration.INSTANCE.enableNetworkProfiler ) + // return System.nanoTime(); + return 0; + } + + public static StackType poweredExtraction(final IEnergySource energy, + final IMEInventory cell, final StackType request, final BaseActionSource src) { + final StackType possible = cell.extractItems((StackType) request.copy(), Actionable.SIMULATE, src); + + long retrieved = 0; + if (possible != null) { + retrieved = possible.getStackSize(); + } + + final double availablePower = energy.extractAEPower(retrieved, Actionable.SIMULATE, PowerMultiplier.CONFIG); + + final long itemToExtract = Math.min((long) (availablePower + 0.9), retrieved); + + if (itemToExtract > 0) { + energy.extractAEPower(retrieved, Actionable.MODULATE, PowerMultiplier.CONFIG); + + possible.setStackSize(itemToExtract); + final StackType ret = cell.extractItems(possible, Actionable.MODULATE, src); + + if (ret != null && src.isPlayer()) { + Stats.ItemsExtracted.addToPlayer(((PlayerSource) src).player, (int) ret.getStackSize()); + } + + return ret; + } + + return null; + } + + public static StackType poweredInsert(final IEnergySource energy, + final IMEInventory cell, final StackType input, final BaseActionSource src) { + final StackType possible = cell.injectItems((StackType) input.copy(), Actionable.SIMULATE, src); + + long stored = input.getStackSize(); + if (possible != null) { + stored -= possible.getStackSize(); + } + long typeMultiplier = input instanceof IAEFluidStack ? 1000 : 1; + + final double availablePower = energy + .extractAEPower(Platform.ceilDiv(stored, typeMultiplier), Actionable.SIMULATE, PowerMultiplier.CONFIG); + + final long itemToAdd = Math.min((long) (availablePower * typeMultiplier + 0.9), stored); + + if (itemToAdd > 0) { + energy.extractAEPower( + Platform.ceilDiv(stored, typeMultiplier), + Actionable.MODULATE, + PowerMultiplier.CONFIG); + + if (itemToAdd < input.getStackSize()) { + final long original = input.getStackSize(); + final StackType split = (StackType) input.copy(); + split.decStackSize(itemToAdd); + input.setStackSize(itemToAdd); + split.add(cell.injectItems(input, Actionable.MODULATE, src)); + + if (src.isPlayer()) { + final long diff = original - split.getStackSize(); + Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); + } + + return split; + } + + final StackType ret = cell.injectItems(input, Actionable.MODULATE, src); + + if (src.isPlayer()) { + final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize(); + Stats.ItemsInserted.addToPlayer(((PlayerSource) src).player, (int) diff); + } + + return ret; + } + + return input; + } + + @SuppressWarnings("unchecked") + public static void postChanges(final IStorageGrid gs, final ItemStack removed, final ItemStack added, + final BaseActionSource src) { + final IItemList itemChanges = AEApi.instance().storage().createItemList(); + final IItemList fluidChanges = AEApi.instance().storage().createFluidList(); + IMEInventory myItems = null; + IMEInventory myFluids = null; + if (removed != null) { + myItems = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.ITEMS); + + if (myItems != null) { + for (final IAEItemStack is : myItems.getAvailableItems(itemChanges)) { + is.setStackSize(-is.getStackSize()); + } + } + + myFluids = AEApi.instance().registries().cell().getCellInventory(removed, null, StorageChannel.FLUIDS); + + if (myFluids != null) { + for (final IAEFluidStack is : myFluids.getAvailableItems(fluidChanges)) { + is.setStackSize(-is.getStackSize()); + } + } + } + + if (added != null) { + myItems = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.ITEMS); + + if (myItems != null) { + myItems.getAvailableItems(itemChanges); + } + + myFluids = AEApi.instance().registries().cell().getCellInventory(added, null, StorageChannel.FLUIDS); + + if (myFluids != null) { + myFluids.getAvailableItems(fluidChanges); + } + } + if (myItems == null) { + gs.postAlterationOfStoredItems(StorageChannel.FLUIDS, fluidChanges, src); + } else { + gs.postAlterationOfStoredItems(StorageChannel.ITEMS, itemChanges, src); + } + } + + public static > void postListChanges(final IItemList before, final IItemList after, + final IMEMonitorHandlerReceiver meMonitorPassthrough, final BaseActionSource source) { + final LinkedList changes = new LinkedList<>(); + + for (final T is : before) { + is.setStackSize(-is.getStackSize()); + } + + for (final T is : after) { + before.add(is); + } + + for (final T is : before) { + if (is.getStackSize() != 0) { + changes.add(is); + } + } + + if (!changes.isEmpty()) { + meMonitorPassthrough.postChange(null, changes, source); + } + } + + public static int generateTileHash(final TileEntity target) { + if (target == null) { + return 0; + } + + int hash = target.hashCode(); + + if (target instanceof ITileStorageMonitorable) { + return 0; + } else if (target instanceof TileEntityChest chest) { + chest.checkForAdjacentChests(); + if (chest.adjacentChestZNeg != null) { + hash ^= chest.adjacentChestZNeg.hashCode(); + } else if (chest.adjacentChestZPos != null) { + hash ^= chest.adjacentChestZPos.hashCode(); + } else if (chest.adjacentChestXPos != null) { + hash ^= chest.adjacentChestXPos.hashCode(); + } else if (chest.adjacentChestXNeg != null) { + hash ^= chest.adjacentChestXNeg.hashCode(); + } + } else if (target instanceof IInventory) { + hash ^= ((IInventory) target).getSizeInventory(); + + if (target instanceof ISidedInventory) { + for (final ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + + final int[] sides = ((ISidedInventory) target).getAccessibleSlotsFromSide(dir.ordinal()); + + if (sides == null) { + return 0; + } + + int offset = 0; + for (final int side : sides) { + final int c = (side << (offset % 8)) ^ (1 << dir.ordinal()); + offset++; + hash = c + (hash << 6) + (hash << 16) - hash; + } + } + } + } + + return hash; + } + + public static boolean securityCheck(final GridNode a, final GridNode b) { + if (a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1) { + return false; + } else if (a.getLastSecurityKey() == b.getLastSecurityKey()) { + return false; + } + + final boolean a_isSecure = isPowered(a.getGrid()) && a.getLastSecurityKey() != -1; + final boolean b_isSecure = isPowered(b.getGrid()) && b.getLastSecurityKey() != -1; + + if (AEConfig.instance.isFeatureEnabled(AEFeature.LogSecurityAudits)) { + AELog.info( + "Audit: " + a_isSecure + + " : " + + b_isSecure + + " @ " + + a.getLastSecurityKey() + + " vs " + + b.getLastSecurityKey() + + " & " + + a.getPlayerID() + + " vs " + + b.getPlayerID()); + } + + // can't do that son... + if (a_isSecure && b_isSecure) { + return true; + } + + if (!a_isSecure && b_isSecure) { + return checkPlayerPermissions(b.getGrid(), a.getPlayerID()); + } + + if (a_isSecure && !b_isSecure) { + return checkPlayerPermissions(a.getGrid(), b.getPlayerID()); + } + + return false; + } + + private static boolean isPowered(final IGrid grid) { + if (grid == null) { + return false; + } + + final IEnergyGrid eg = grid.getCache(IEnergyGrid.class); + return eg.isNetworkPowered(); + } + + private static boolean checkPlayerPermissions(final IGrid grid, final int playerID) { + if (grid == null) { + return false; + } + + final ISecurityGrid gs = grid.getCache(ISecurityGrid.class); + + if (gs == null) { + return false; + } + + if (!gs.isAvailable()) { + return false; + } + + return !gs.hasPermission(playerID, SecurityPermissions.BUILD); + } + + public static void configurePlayer(final EntityPlayer player, final ForgeDirection side, final TileEntity tile) { + player.yOffset = 1.8f; + + float yaw = 0.0f; + float pitch = 0.0f; + switch (side) { + case DOWN: + pitch = 90.0f; + player.yOffset = -1.8f; + break; + case EAST: + yaw = -90.0f; + break; + case NORTH: + yaw = 180.0f; + break; + case SOUTH: + yaw = 0.0f; + break; + case UNKNOWN: + break; + case UP: + pitch = 90.0f; + break; + case WEST: + yaw = 90.0f; + break; + } + + player.posX = tile.xCoord + 0.5; + player.posY = tile.yCoord + 0.5; + player.posZ = tile.zCoord + 0.5; + + player.rotationPitch = player.prevCameraPitch = player.cameraPitch = pitch; + player.rotationYaw = player.prevCameraYaw = player.cameraYaw = yaw; + } + + public static boolean canAccess(final AENetworkProxy gridProxy, final BaseActionSource src) { + try { + if (src.isPlayer()) { + return gridProxy.getSecurity().hasPermission(((PlayerSource) src).player, SecurityPermissions.BUILD); + } else if (src.isMachine()) { + final IActionHost te = ((MachineSource) src).via; + final IGridNode n = te.getActionableNode(); + if (n == null) { + return false; + } + + final int playerID = n.getPlayerID(); + return gridProxy.getSecurity().hasPermission(playerID, SecurityPermissions.BUILD); + } else { + return false; + } + } catch (final GridAccessException gae) { + return false; + } + } + + public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, + final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, + final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, + final IItemList items, final Actionable realForFake, + final IPartitionList filter) { + return extractItemsByRecipe( + energySrc, + mySrc, + src, + w, + r, + output, + ci, + providedTemplate, + slot, + items, + realForFake, + filter, + 1); + } + + public static ItemStack extractItemsByRecipe(final IEnergySource energySrc, final BaseActionSource mySrc, + final IMEMonitor src, final World w, final IRecipe r, final ItemStack output, + final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, + final IItemList items, final Actionable realForFake, + final IPartitionList filter, int multiple) { + if (energySrc.extractAEPower(multiple, Actionable.SIMULATE, PowerMultiplier.CONFIG) > 0.9) { + if (providedTemplate == null) { + return null; + } + + final AEItemStack ae_req = AEItemStack.create(providedTemplate); + ae_req.setStackSize(multiple); + + if (filter == null || filter.isListed(ae_req)) { + final IAEItemStack ae_ext = src.extractItems(ae_req, realForFake, mySrc); + if (ae_ext != null) { + final ItemStack extracted = ae_ext.getItemStack(); + if (extracted != null) { + energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); + return extracted; + } + } + } + + final boolean checkFuzzy = ae_req.isOre() + || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE + || providedTemplate.hasTagCompound() + || providedTemplate.isItemStackDamageable(); + + if (items != null && checkFuzzy) { + for (final IAEItemStack x : items) { + final ItemStack sh = x.getItemStack(); + if ((Platform.isSameItemType(providedTemplate, sh) || ae_req.sameOre(x)) + && !Platform.isSameItem(sh, output)) { // Platform.isSameItemType( sh, providedTemplate ) + final ItemStack cp = Platform.cloneItemStack(sh); + cp.stackSize = 1; + ci.setInventorySlotContents(slot, cp); + if (r.matches(ci, w) && Platform.isSameItem(r.getCraftingResult(ci), output)) { + final IAEItemStack ax = x.copy(); + ax.setStackSize(multiple); + if (filter == null || filter.isListed(ax)) { + final IAEItemStack ex = src.extractItems(ax, realForFake, mySrc); + if (ex != null) { + energySrc.extractAEPower(multiple, realForFake, PowerMultiplier.CONFIG); + return ex.getItemStack(); + } + } + } + ci.setInventorySlotContents(slot, providedTemplate); + } + } + } + } + return null; + } + + public static boolean isSameItemType(final ItemStack that, final ItemStack other) { + if (that != null && other != null && that.getItem() == other.getItem()) { + if (that.isItemStackDamageable()) { + return true; + } + return that.getItemDamage() == other.getItemDamage(); + } + return false; + } + + public static boolean isSameItem(@Nullable final ItemStack left, @Nullable final ItemStack right) { + return left != null && right != null && left.isItemEqual(right); + } + + public static ItemStack cloneItemStack(final ItemStack a) { + return a.copy(); + } + + public static ItemStack getContainerItem(final ItemStack stackInSlot) { + if (stackInSlot == null) { + return null; + } + + final Item i = stackInSlot.getItem(); + if (i == null || !i.hasContainerItem(stackInSlot)) { + if (stackInSlot.stackSize > 1) { + stackInSlot.stackSize--; + return stackInSlot; + } + return null; + } + + ItemStack ci = i.getContainerItem(stackInSlot.copy()); + if (ci != null && ci.isItemStackDamageable() && ci.getItemDamage() > ci.getMaxDamage()) { + ci = null; + } + + return ci; + } + + public static void notifyBlocksOfNeighbors(final World worldObj, final int xCoord, final int yCoord, + final int zCoord) { + if (!worldObj.isRemote) { + TickHandler.INSTANCE.addCallable(worldObj, new BlockUpdate(xCoord, yCoord, zCoord)); + } + } + + public static boolean canRepair(final AEFeature type, final ItemStack a, final ItemStack b) { + if (b == null || a == null) { + return false; + } + + if (type == AEFeature.CertusQuartzTools) { + final IItemDefinition certusQuartzCrystal = AEApi.instance().definitions().materials() + .certusQuartzCrystal(); + + return certusQuartzCrystal.isSameAs(b); + } + + if (type == AEFeature.NetherQuartzTools) { + return Items.quartz == b.getItem(); + } + + return false; + } + + public static Object findPreferred(final ItemStack[] is) { + final IParts parts = AEApi.instance().definitions().parts(); + + for (final ItemStack stack : is) { + if (parts.cableGlass().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableCovered().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableSmart().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableDense().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableDenseCovered().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableUltraDenseCovered().sameAs(AEColor.Transparent, stack)) { + return stack; + } + + if (parts.cableUltraDenseSmart().sameAs(AEColor.Transparent, stack)) { + return stack; + } + } + + return is; + } + + public static void sendChunk(final Chunk c, final int verticalBits) { + try { + final WorldServer ws = (WorldServer) c.worldObj; + final PlayerManager pm = ws.getPlayerManager(); + + if (getOrCreateChunkWatcher == null) { + getOrCreateChunkWatcher = ReflectionHelper.findMethod( + PlayerManager.class, + pm, + new String[] { "getOrCreateChunkWatcher", "func_72690_a" }, + int.class, + int.class, + boolean.class); + } + + if (getOrCreateChunkWatcher != null) { + final Object playerInstance = getOrCreateChunkWatcher.invoke(pm, c.xPosition, c.zPosition, false); + if (playerInstance != null) { + Platform.playerInstance = playerInstance.getClass(); + + if (sendToAllPlayersWatchingChunk == null) { + sendToAllPlayersWatchingChunk = ReflectionHelper.findMethod( + Platform.playerInstance, + playerInstance, + new String[] { "sendToAllPlayersWatchingChunk", "func_151251_a" }, + Packet.class); + } + + if (sendToAllPlayersWatchingChunk != null) { + sendToAllPlayersWatchingChunk + .invoke(playerInstance, new S21PacketChunkData(c, false, verticalBits)); + } + } + } + } catch (final Throwable t) { + AELog.debug(t); + } + } + + public static AxisAlignedBB getPrimaryBox(final ForgeDirection side, final int facadeThickness) { + switch (side) { + case DOWN -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, (facadeThickness) / 16.0, 1.0); + } + case EAST -> { + return AxisAlignedBB.getBoundingBox((16.0 - facadeThickness) / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0); + } + case NORTH -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, 1.0, 1.0, (facadeThickness) / 16.0); + } + case SOUTH -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, (16.0 - facadeThickness) / 16.0, 1.0, 1.0, 1.0); + } + case UP -> { + return AxisAlignedBB.getBoundingBox(0.0, (16.0 - facadeThickness) / 16.0, 0.0, 1.0, 1.0, 1.0); + } + case WEST -> { + return AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.0, (facadeThickness) / 16.0, 1.0, 1.0); + } + default -> {} + } + return AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1); + } + + public static float getEyeOffset(final EntityPlayer player) { + assert player.worldObj.isRemote : "Valid only on client"; + return (float) (player.posY + player.getEyeHeight() - player.getDefaultEyeHeight()); + } + + public static void addStat(final int playerID, final Achievement achievement) { + final EntityPlayer p = AEApi.instance().registries().players().findPlayer(playerID); + if (p != null) { + p.addStat(achievement, 1); + } + } + + public static boolean isRecipePrioritized(final ItemStack what) { + final IMaterials materials = AEApi.instance().definitions().materials(); + + boolean isPurified = materials.purifiedCertusQuartzCrystal().isSameAs(what); + isPurified |= materials.purifiedFluixCrystal().isSameAs(what); + isPurified |= materials.purifiedNetherQuartzCrystal().isSameAs(what); + + return isPurified; + } + + public static ItemStack loadItemStackFromNBT(NBTTagCompound tagCompound) { + ItemStack stack = ItemStack.loadItemStackFromNBT(tagCompound); + if (stack != null) { + stack.stackSize = tagCompound.getInteger("Count"); + } + return stack; + } + + public static NBTTagCompound writeItemStackToNBT(ItemStack is, NBTTagCompound tagCompound) { + is.writeToNBT(tagCompound); + tagCompound.setInteger("Count", is.stackSize); + return tagCompound; + } + + public static IAEItemStack getAEStackInSlot(Slot slot) { + if (slot == null || !slot.getHasStack()) { + return null; + } + + if (slot instanceof SlotME) { + return ((SlotME) slot).getAEStack(); + } + + if (slot instanceof SlotFake) { + return ((SlotFake) slot).getAEStack(); + } + + return AEItemStack.create(slot.getStack()); + } + + /** + * @return (a divided by b) rounded up + */ + public static long ceilDiv(long a, long b) { + return Math.addExact(Math.addExact(a, b), -1) / b; + } + + /** + * From bytes to K,M,G,T like + * + * @param n Bytes number + * @return String that like 1G or 1.4T + */ + public static String formatByteLong(final long n) { + int storageUnit = Long.toBinaryString(n).length() / 10; + final DecimalFormat df = new DecimalFormat("#.##"); + switch (storageUnit) { + case 6: + return df.format((double) n / 1152921504606846976d) + " EB"; + case 5: + return df.format((double) n / 1125899906842624d) + " PB"; + case 4: + return df.format((double) n / 1099511627776d) + " TB"; + case 3: + return df.format((double) n / 1073741824d) + " GB"; + case 2: + return df.format((double) n / 1048576d) + " MB"; + case 1: + return df.format((double) n / 1024d) + " kB"; + case 0: + return df.format((double) n) + " B"; + default: + return df.format((double) n) + " B"; + } + } } From d31900e1b2a24fe9fc15821bf4a7932be7839f55 Mon Sep 17 00:00:00 2001 From: MCTBL <30978504+MCTBL@users.noreply.github.com> Date: Tue, 31 Oct 2023 22:52:59 +0800 Subject: [PATCH 03/34] Update src/main/java/appeng/me/cache/GridStorageCache.java Co-authored-by: Andrei Antropov --- src/main/java/appeng/me/cache/GridStorageCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 2f1a6e785ee..9f56b3d51d0 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -79,7 +79,7 @@ public void onUpdateTick() { for (ICellProvider icp : this.activeCellProviders) { if (icp.getClass() == Class.forName("appeng.tile.storage.TileDrive")) { // All Item Cell - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { if (((DriveWatcher) meih).getInternal().getClass() == Class.forName("appeng.me.storage.VoidCellInventory")) { // exclude void cell and // creative cell From 93fc689a217de560fa8c37e82d522b95dd19fd2a Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Tue, 31 Oct 2023 23:15:47 +0800 Subject: [PATCH 04/34] swap some of Class.forName to instanceof --- .../appeng/me/cache/GridStorageCache.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 2f1a6e785ee..a60ad7673e9 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -46,6 +46,8 @@ import appeng.me.storage.DriveWatcher; import appeng.me.storage.ItemWatcher; import appeng.me.storage.NetworkInventoryHandler; +import appeng.me.storage.VoidCellInventory; +import appeng.tile.storage.TileDrive; public class GridStorageCache implements IStorageGrid { @@ -77,25 +79,24 @@ public void onUpdateTick() { this.itemBytesUsed = 0; try { for (ICellProvider icp : this.activeCellProviders) { - if (icp.getClass() == Class.forName("appeng.tile.storage.TileDrive")) { + if (icp instanceof TileDrive) { // All Item Cell for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { - if (((DriveWatcher) meih).getInternal().getClass() - == Class.forName("appeng.me.storage.VoidCellInventory")) { // exclude void cell and - // creative cell + // exclude void cell + if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { continue; } - if (((CellInventoryHandler) (((DriveWatcher) meih).getInternal())).getCellInv() - != null) { - itemBytesTotal += ((CellInventoryHandler) (((DriveWatcher) meih) - .getInternal())).getCellInv().getTotalBytes(); - itemBytesUsed += ((CellInventoryHandler) (((DriveWatcher) meih) - .getInternal())).getCellInv().getUsedBytes(); + // exclude creative cell + if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { + if (handler.getCellInv() != null) { + itemBytesTotal += handler.getCellInv().getTotalBytes(); + itemBytesUsed += handler.getCellInv().getUsedBytes(); + } } } } } - } catch (ClassNotFoundException e) { + } catch (Exception e) { // XD } } From e4a10fd3f00072d18f9bbc65cac9903a7630edf6 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Wed, 1 Nov 2023 00:17:02 +0800 Subject: [PATCH 05/34] make cache update delay --- .../appeng/me/cache/GridStorageCache.java | 652 +++++++++--------- 1 file changed, 332 insertions(+), 320 deletions(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 16eb132449e..370f08c5db1 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -51,325 +51,337 @@ public class GridStorageCache implements IStorageGrid { - private final IGrid myGrid; - private final HashSet activeCellProviders = new HashSet<>(); - private final HashSet inactiveCellProviders = new HashSet<>(); - private final SetMultimap interests = HashMultimap.create(); - private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); - private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); - private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); - private final HashMap watchers = new HashMap<>(); - private NetworkInventoryHandler myItemNetwork; - private NetworkInventoryHandler myFluidNetwork; - - // mine - private long itemBytesTotal; - private long itemBytesUsed; - - public GridStorageCache(final IGrid g) { - this.myGrid = g; - } - - @Override - public void onUpdateTick() { - this.itemMonitor.onTick(); - this.fluidMonitor.onTick(); - - this.itemBytesTotal = 0; - this.itemBytesUsed = 0; - try { - for (ICellProvider icp : this.activeCellProviders) { - if (icp instanceof TileDrive) { - // All Item Cell - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { - // exclude void cell - if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { - continue; - } - // exclude creative cell - if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { - if (handler.getCellInv() != null) { - itemBytesTotal += handler.getCellInv().getTotalBytes(); - itemBytesUsed += handler.getCellInv().getUsedBytes(); - } - } - } - } - } - } catch (Exception e) { - // XD - } - } - - @Override - public void removeNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.removeCellProvider(cc, tracker); - this.inactiveCellProviders.remove(cc); - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - tracker.applyChanges(); - } - - if (machine instanceof IStackWatcherHost) { - final IStackWatcher myWatcher = this.watchers.get(machine); - - if (myWatcher != null) { - myWatcher.clear(); - this.watchers.remove(machine); - } - } - } - - @Override - public void addNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - this.inactiveCellProviders.add(cc); - - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - if (node.isActive()) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.addCellProvider(cc, tracker); - tracker.applyChanges(); - } - } - - if (machine instanceof IStackWatcherHost swh) { - final ItemWatcher iw = new ItemWatcher(this, swh); - this.watchers.put(node, iw); - swh.updateWatcher(iw); - } - } - - @Override - public void onSplit(final IGridStorage storageB) {} - - @Override - public void onJoin(final IGridStorage storageB) {} - - @Override - public void populateGridStorage(final IGridStorage storage) {} - - private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.inactiveCellProviders.contains(cc)) { - this.inactiveCellProviders.remove(cc); - this.activeCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); - } - } - - return tracker; - } - - private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.activeCellProviders.contains(cc)) { - this.activeCellProviders.remove(cc); - this.inactiveCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); - } - } - - return tracker; - } - - @MENetworkEventSubscribe - public void cellUpdate(final MENetworkCellArrayUpdate ev) { - this.myItemNetwork = null; - this.myFluidNetwork = null; - - final LinkedList ll = new LinkedList(); - ll.addAll(this.inactiveCellProviders); - ll.addAll(this.activeCellProviders); - - final CellChangeTracker tracker = new CellChangeTracker(); - - for (final ICellProvider cc : ll) { - boolean active = true; - - if (cc instanceof IActionHost) { - final IGridNode node = ((IActionHost) cc).getActionableNode(); - active = node != null && node.isActive(); - } - - if (active) { - this.addCellProvider(cc, tracker); - } else { - this.removeCellProvider(cc, tracker); - } - } - - this.itemMonitor.forceUpdate(); - this.fluidMonitor.forceUpdate(); - - tracker.applyChanges(); - - } - - private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, - final BaseActionSource src) { - switch (chan) { - case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); - case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); - default -> {} - } - } - - IMEInventoryHandler getItemInventoryHandler() { - if (this.myItemNetwork == null) { - this.buildNetworkStorage(StorageChannel.ITEMS); - } - return this.myItemNetwork; - } - - private void buildNetworkStorage(final StorageChannel chan) { - final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); - - switch (chan) { - case FLUIDS -> { - this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myFluidNetwork.addNewStorage(h); - } - } - } - case ITEMS -> { - this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myItemNetwork.addNewStorage(h); - } - } - } - default -> {} - } - } - - IMEInventoryHandler getFluidInventoryHandler() { - if (this.myFluidNetwork == null) { - this.buildNetworkStorage(StorageChannel.FLUIDS); - } - return this.myFluidNetwork; - } - - @Override - public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, - final BaseActionSource src) { - if (chan == StorageChannel.ITEMS) { - this.itemMonitor.postChange(true, (Iterable) input, src); - } else if (chan == StorageChannel.FLUIDS) { - this.fluidMonitor.postChange(true, (Iterable) input, src); - } - } - - @Override - public void registerCellProvider(final ICellProvider provider) { - this.inactiveCellProviders.add(provider); - this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); - } - - @Override - public void unregisterCellProvider(final ICellProvider provider) { - this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); - this.inactiveCellProviders.remove(provider); - } - - @Override - public IMEMonitor getItemInventory() { - return this.itemMonitor; - } - - @Override - public IMEMonitor getFluidInventory() { - return this.fluidMonitor; - } - - public GenericInterestManager getInterestManager() { - return this.interestManager; - } - - IGrid getGrid() { - return this.myGrid; - } - - private class CellChangeTrackerRecord { - - final StorageChannel channel; - final int up_or_down; - final IItemList list; - final BaseActionSource src; - - public CellChangeTrackerRecord(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.channel = channel; - this.up_or_down = i; - this.src = actionSrc; - - if (channel == StorageChannel.ITEMS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createItemList()); - } else if (channel == StorageChannel.FLUIDS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createFluidList()); - } else { - this.list = null; - } - } - - public void applyChanges() { - GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); - } - } - - private class CellChangeTracker { - - final List data = new LinkedList<>(); - - public void postChanges(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); - } - - public void applyChanges() { - for (final CellChangeTrackerRecord rec : this.data) { - rec.applyChanges(); - } - } - } - - public long getItemBytesTotal() { - return this.itemBytesTotal; - } - - public long getItemBytesUsed() { - return this.itemBytesUsed; - } + private final IGrid myGrid; + private final HashSet activeCellProviders = new HashSet<>(); + private final HashSet inactiveCellProviders = new HashSet<>(); + private final SetMultimap interests = HashMultimap.create(); + private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); + private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); + private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); + private final HashMap watchers = new HashMap<>(); + private NetworkInventoryHandler myItemNetwork; + private NetworkInventoryHandler myFluidNetwork; + private long itemBytesTotal; + private long itemBytesUsed; + private short ticksCount; + + public GridStorageCache(final IGrid g) { + this.myGrid = g; + this.ticksCount = 0; + } + + @Override + public void onUpdateTick() { + this.itemMonitor.onTick(); + this.fluidMonitor.onTick(); + + // update every 1000Ticks + if (this.ticksCount >= 1000) { + this.ticksCount++; + } else { + this.ticksCount = 0; + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + try { + for (ICellProvider icp : this.activeCellProviders) { + if (icp instanceof TileDrive) { + // All Item Cell + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + // exclude void cell + if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { + continue; + } + // exclude creative cell + if (((DriveWatcher) meih) + .getInternal() instanceof CellInventoryHandler handler) { + if (handler.getCellInv() != null) { + itemBytesTotal += handler.getCellInv().getTotalBytes(); + itemBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + } + } + } + } catch (Exception e) { + // XD Normally won't be here, just normally.. + } + } + } + + @Override + public void removeNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.removeCellProvider(cc, tracker); + this.inactiveCellProviders.remove(cc); + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + tracker.applyChanges(); + } + + if (machine instanceof IStackWatcherHost) { + final IStackWatcher myWatcher = this.watchers.get(machine); + + if (myWatcher != null) { + myWatcher.clear(); + this.watchers.remove(machine); + } + } + } + + @Override + public void addNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + this.inactiveCellProviders.add(cc); + + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + if (node.isActive()) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.addCellProvider(cc, tracker); + tracker.applyChanges(); + } + } + + if (machine instanceof IStackWatcherHost swh) { + final ItemWatcher iw = new ItemWatcher(this, swh); + this.watchers.put(node, iw); + swh.updateWatcher(iw); + } + } + + @Override + public void onSplit(final IGridStorage storageB) { + } + + @Override + public void onJoin(final IGridStorage storageB) { + } + + @Override + public void populateGridStorage(final IGridStorage storage) { + } + + private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.inactiveCellProviders.contains(cc)) { + this.inactiveCellProviders.remove(cc); + this.activeCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); + } + } + + return tracker; + } + + private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.activeCellProviders.contains(cc)) { + this.activeCellProviders.remove(cc); + this.inactiveCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); + } + } + + return tracker; + } + + @MENetworkEventSubscribe + public void cellUpdate(final MENetworkCellArrayUpdate ev) { + this.myItemNetwork = null; + this.myFluidNetwork = null; + + final LinkedList ll = new LinkedList(); + ll.addAll(this.inactiveCellProviders); + ll.addAll(this.activeCellProviders); + + final CellChangeTracker tracker = new CellChangeTracker(); + + for (final ICellProvider cc : ll) { + boolean active = true; + + if (cc instanceof IActionHost) { + final IGridNode node = ((IActionHost) cc).getActionableNode(); + active = node != null && node.isActive(); + } + + if (active) { + this.addCellProvider(cc, tracker); + } else { + this.removeCellProvider(cc, tracker); + } + } + + this.itemMonitor.forceUpdate(); + this.fluidMonitor.forceUpdate(); + + tracker.applyChanges(); + + } + + private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, + final BaseActionSource src) { + switch (chan) { + case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); + case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); + default -> { + } + } + } + + IMEInventoryHandler getItemInventoryHandler() { + if (this.myItemNetwork == null) { + this.buildNetworkStorage(StorageChannel.ITEMS); + } + return this.myItemNetwork; + } + + private void buildNetworkStorage(final StorageChannel chan) { + final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); + + switch (chan) { + case FLUIDS -> { + this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myFluidNetwork.addNewStorage(h); + } + } + } + case ITEMS -> { + this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myItemNetwork.addNewStorage(h); + } + } + } + default -> { + } + } + } + + IMEInventoryHandler getFluidInventoryHandler() { + if (this.myFluidNetwork == null) { + this.buildNetworkStorage(StorageChannel.FLUIDS); + } + return this.myFluidNetwork; + } + + @Override + public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, + final BaseActionSource src) { + if (chan == StorageChannel.ITEMS) { + this.itemMonitor.postChange(true, (Iterable) input, src); + } else if (chan == StorageChannel.FLUIDS) { + this.fluidMonitor.postChange(true, (Iterable) input, src); + } + } + + @Override + public void registerCellProvider(final ICellProvider provider) { + this.inactiveCellProviders.add(provider); + this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); + } + + @Override + public void unregisterCellProvider(final ICellProvider provider) { + this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); + this.inactiveCellProviders.remove(provider); + } + + @Override + public IMEMonitor getItemInventory() { + return this.itemMonitor; + } + + @Override + public IMEMonitor getFluidInventory() { + return this.fluidMonitor; + } + + public GenericInterestManager getInterestManager() { + return this.interestManager; + } + + IGrid getGrid() { + return this.myGrid; + } + + private class CellChangeTrackerRecord { + + final StorageChannel channel; + final int up_or_down; + final IItemList list; + final BaseActionSource src; + + public CellChangeTrackerRecord(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.channel = channel; + this.up_or_down = i; + this.src = actionSrc; + + if (channel == StorageChannel.ITEMS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createItemList()); + } else if (channel == StorageChannel.FLUIDS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createFluidList()); + } else { + this.list = null; + } + } + + public void applyChanges() { + GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); + } + } + + private class CellChangeTracker { + + final List data = new LinkedList<>(); + + public void postChanges(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); + } + + public void applyChanges() { + for (final CellChangeTrackerRecord rec : this.data) { + rec.applyChanges(); + } + } + } + + public long getItemBytesTotal() { + return this.itemBytesTotal; + } + + public long getItemBytesUsed() { + return this.itemBytesUsed; + } } From 1ed55688e83d34fd7e442296dfa4f5afc4239c03 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Wed, 1 Nov 2023 00:18:51 +0800 Subject: [PATCH 06/34] make cache update delay --- .../appeng/me/cache/GridStorageCache.java | 659 +++++++++--------- 1 file changed, 327 insertions(+), 332 deletions(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 370f08c5db1..a246f7b93d5 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -51,337 +51,332 @@ public class GridStorageCache implements IStorageGrid { - private final IGrid myGrid; - private final HashSet activeCellProviders = new HashSet<>(); - private final HashSet inactiveCellProviders = new HashSet<>(); - private final SetMultimap interests = HashMultimap.create(); - private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); - private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); - private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); - private final HashMap watchers = new HashMap<>(); - private NetworkInventoryHandler myItemNetwork; - private NetworkInventoryHandler myFluidNetwork; - private long itemBytesTotal; - private long itemBytesUsed; - private short ticksCount; - - public GridStorageCache(final IGrid g) { - this.myGrid = g; - this.ticksCount = 0; - } - - @Override - public void onUpdateTick() { - this.itemMonitor.onTick(); - this.fluidMonitor.onTick(); - - // update every 1000Ticks - if (this.ticksCount >= 1000) { - this.ticksCount++; - } else { - this.ticksCount = 0; - this.itemBytesTotal = 0; - this.itemBytesUsed = 0; - try { - for (ICellProvider icp : this.activeCellProviders) { - if (icp instanceof TileDrive) { - // All Item Cell - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { - // exclude void cell - if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { - continue; - } - // exclude creative cell - if (((DriveWatcher) meih) - .getInternal() instanceof CellInventoryHandler handler) { - if (handler.getCellInv() != null) { - itemBytesTotal += handler.getCellInv().getTotalBytes(); - itemBytesUsed += handler.getCellInv().getUsedBytes(); - } - } - } - } - } - } catch (Exception e) { - // XD Normally won't be here, just normally.. - } - } - } - - @Override - public void removeNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.removeCellProvider(cc, tracker); - this.inactiveCellProviders.remove(cc); - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - tracker.applyChanges(); - } - - if (machine instanceof IStackWatcherHost) { - final IStackWatcher myWatcher = this.watchers.get(machine); - - if (myWatcher != null) { - myWatcher.clear(); - this.watchers.remove(machine); - } - } - } - - @Override - public void addNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - this.inactiveCellProviders.add(cc); - - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - if (node.isActive()) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.addCellProvider(cc, tracker); - tracker.applyChanges(); - } - } - - if (machine instanceof IStackWatcherHost swh) { - final ItemWatcher iw = new ItemWatcher(this, swh); - this.watchers.put(node, iw); - swh.updateWatcher(iw); - } - } - - @Override - public void onSplit(final IGridStorage storageB) { - } - - @Override - public void onJoin(final IGridStorage storageB) { - } - - @Override - public void populateGridStorage(final IGridStorage storage) { - } - - private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.inactiveCellProviders.contains(cc)) { - this.inactiveCellProviders.remove(cc); - this.activeCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); - } - } - - return tracker; - } - - private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.activeCellProviders.contains(cc)) { - this.activeCellProviders.remove(cc); - this.inactiveCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); - } - } - - return tracker; - } - - @MENetworkEventSubscribe - public void cellUpdate(final MENetworkCellArrayUpdate ev) { - this.myItemNetwork = null; - this.myFluidNetwork = null; - - final LinkedList ll = new LinkedList(); - ll.addAll(this.inactiveCellProviders); - ll.addAll(this.activeCellProviders); - - final CellChangeTracker tracker = new CellChangeTracker(); - - for (final ICellProvider cc : ll) { - boolean active = true; - - if (cc instanceof IActionHost) { - final IGridNode node = ((IActionHost) cc).getActionableNode(); - active = node != null && node.isActive(); - } - - if (active) { - this.addCellProvider(cc, tracker); - } else { - this.removeCellProvider(cc, tracker); - } - } - - this.itemMonitor.forceUpdate(); - this.fluidMonitor.forceUpdate(); - - tracker.applyChanges(); - - } - - private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, - final BaseActionSource src) { - switch (chan) { - case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); - case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); - default -> { - } - } - } - - IMEInventoryHandler getItemInventoryHandler() { - if (this.myItemNetwork == null) { - this.buildNetworkStorage(StorageChannel.ITEMS); - } - return this.myItemNetwork; - } - - private void buildNetworkStorage(final StorageChannel chan) { - final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); - - switch (chan) { - case FLUIDS -> { - this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myFluidNetwork.addNewStorage(h); - } - } - } - case ITEMS -> { - this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myItemNetwork.addNewStorage(h); - } - } - } - default -> { - } - } - } - - IMEInventoryHandler getFluidInventoryHandler() { - if (this.myFluidNetwork == null) { - this.buildNetworkStorage(StorageChannel.FLUIDS); - } - return this.myFluidNetwork; - } - - @Override - public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, - final BaseActionSource src) { - if (chan == StorageChannel.ITEMS) { - this.itemMonitor.postChange(true, (Iterable) input, src); - } else if (chan == StorageChannel.FLUIDS) { - this.fluidMonitor.postChange(true, (Iterable) input, src); - } - } - - @Override - public void registerCellProvider(final ICellProvider provider) { - this.inactiveCellProviders.add(provider); - this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); - } - - @Override - public void unregisterCellProvider(final ICellProvider provider) { - this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); - this.inactiveCellProviders.remove(provider); - } - - @Override - public IMEMonitor getItemInventory() { - return this.itemMonitor; - } - - @Override - public IMEMonitor getFluidInventory() { - return this.fluidMonitor; - } - - public GenericInterestManager getInterestManager() { - return this.interestManager; - } - - IGrid getGrid() { - return this.myGrid; - } - - private class CellChangeTrackerRecord { - - final StorageChannel channel; - final int up_or_down; - final IItemList list; - final BaseActionSource src; - - public CellChangeTrackerRecord(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.channel = channel; - this.up_or_down = i; - this.src = actionSrc; - - if (channel == StorageChannel.ITEMS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createItemList()); - } else if (channel == StorageChannel.FLUIDS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createFluidList()); - } else { - this.list = null; - } - } - - public void applyChanges() { - GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); - } - } - - private class CellChangeTracker { - - final List data = new LinkedList<>(); - - public void postChanges(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); - } - - public void applyChanges() { - for (final CellChangeTrackerRecord rec : this.data) { - rec.applyChanges(); - } - } - } - - public long getItemBytesTotal() { - return this.itemBytesTotal; - } - - public long getItemBytesUsed() { - return this.itemBytesUsed; - } + private final IGrid myGrid; + private final HashSet activeCellProviders = new HashSet<>(); + private final HashSet inactiveCellProviders = new HashSet<>(); + private final SetMultimap interests = HashMultimap.create(); + private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); + private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); + private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); + private final HashMap watchers = new HashMap<>(); + private NetworkInventoryHandler myItemNetwork; + private NetworkInventoryHandler myFluidNetwork; + private long itemBytesTotal; + private long itemBytesUsed; + private short ticksCount; + + public GridStorageCache(final IGrid g) { + this.myGrid = g; + this.ticksCount = 0; + } + + @Override + public void onUpdateTick() { + this.itemMonitor.onTick(); + this.fluidMonitor.onTick(); + + // update every 1000Ticks + if (this.ticksCount >= 1000) { + this.ticksCount++; + } else { + this.ticksCount = 0; + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + try { + for (ICellProvider icp : this.activeCellProviders) { + if (icp instanceof TileDrive) { + // All Item Cell + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + // exclude void cell + if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { + continue; + } + // exclude creative cell + if (((DriveWatcher) meih) + .getInternal() instanceof CellInventoryHandler handler) { + if (handler.getCellInv() != null) { + itemBytesTotal += handler.getCellInv().getTotalBytes(); + itemBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + } + } + } + } catch (Exception e) { + // XD Normally won't be here, just normally.. + } + } + } + + @Override + public void removeNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.removeCellProvider(cc, tracker); + this.inactiveCellProviders.remove(cc); + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + tracker.applyChanges(); + } + + if (machine instanceof IStackWatcherHost) { + final IStackWatcher myWatcher = this.watchers.get(machine); + + if (myWatcher != null) { + myWatcher.clear(); + this.watchers.remove(machine); + } + } + } + + @Override + public void addNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + this.inactiveCellProviders.add(cc); + + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + if (node.isActive()) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.addCellProvider(cc, tracker); + tracker.applyChanges(); + } + } + + if (machine instanceof IStackWatcherHost swh) { + final ItemWatcher iw = new ItemWatcher(this, swh); + this.watchers.put(node, iw); + swh.updateWatcher(iw); + } + } + + @Override + public void onSplit(final IGridStorage storageB) {} + + @Override + public void onJoin(final IGridStorage storageB) {} + + @Override + public void populateGridStorage(final IGridStorage storage) {} + + private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.inactiveCellProviders.contains(cc)) { + this.inactiveCellProviders.remove(cc); + this.activeCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); + } + } + + return tracker; + } + + private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.activeCellProviders.contains(cc)) { + this.activeCellProviders.remove(cc); + this.inactiveCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); + } + } + + return tracker; + } + + @MENetworkEventSubscribe + public void cellUpdate(final MENetworkCellArrayUpdate ev) { + this.myItemNetwork = null; + this.myFluidNetwork = null; + + final LinkedList ll = new LinkedList(); + ll.addAll(this.inactiveCellProviders); + ll.addAll(this.activeCellProviders); + + final CellChangeTracker tracker = new CellChangeTracker(); + + for (final ICellProvider cc : ll) { + boolean active = true; + + if (cc instanceof IActionHost) { + final IGridNode node = ((IActionHost) cc).getActionableNode(); + active = node != null && node.isActive(); + } + + if (active) { + this.addCellProvider(cc, tracker); + } else { + this.removeCellProvider(cc, tracker); + } + } + + this.itemMonitor.forceUpdate(); + this.fluidMonitor.forceUpdate(); + + tracker.applyChanges(); + + } + + private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, + final BaseActionSource src) { + switch (chan) { + case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); + case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); + default -> {} + } + } + + IMEInventoryHandler getItemInventoryHandler() { + if (this.myItemNetwork == null) { + this.buildNetworkStorage(StorageChannel.ITEMS); + } + return this.myItemNetwork; + } + + private void buildNetworkStorage(final StorageChannel chan) { + final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); + + switch (chan) { + case FLUIDS -> { + this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myFluidNetwork.addNewStorage(h); + } + } + } + case ITEMS -> { + this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myItemNetwork.addNewStorage(h); + } + } + } + default -> {} + } + } + + IMEInventoryHandler getFluidInventoryHandler() { + if (this.myFluidNetwork == null) { + this.buildNetworkStorage(StorageChannel.FLUIDS); + } + return this.myFluidNetwork; + } + + @Override + public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, + final BaseActionSource src) { + if (chan == StorageChannel.ITEMS) { + this.itemMonitor.postChange(true, (Iterable) input, src); + } else if (chan == StorageChannel.FLUIDS) { + this.fluidMonitor.postChange(true, (Iterable) input, src); + } + } + + @Override + public void registerCellProvider(final ICellProvider provider) { + this.inactiveCellProviders.add(provider); + this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); + } + + @Override + public void unregisterCellProvider(final ICellProvider provider) { + this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); + this.inactiveCellProviders.remove(provider); + } + + @Override + public IMEMonitor getItemInventory() { + return this.itemMonitor; + } + + @Override + public IMEMonitor getFluidInventory() { + return this.fluidMonitor; + } + + public GenericInterestManager getInterestManager() { + return this.interestManager; + } + + IGrid getGrid() { + return this.myGrid; + } + + private class CellChangeTrackerRecord { + + final StorageChannel channel; + final int up_or_down; + final IItemList list; + final BaseActionSource src; + + public CellChangeTrackerRecord(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.channel = channel; + this.up_or_down = i; + this.src = actionSrc; + + if (channel == StorageChannel.ITEMS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createItemList()); + } else if (channel == StorageChannel.FLUIDS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createFluidList()); + } else { + this.list = null; + } + } + + public void applyChanges() { + GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); + } + } + + private class CellChangeTracker { + + final List data = new LinkedList<>(); + + public void postChanges(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); + } + + public void applyChanges() { + for (final CellChangeTrackerRecord rec : this.data) { + rec.applyChanges(); + } + } + } + + public long getItemBytesTotal() { + return this.itemBytesTotal; + } + + public long getItemBytesUsed() { + return this.itemBytesUsed; + } } From 0524da5b182e3476f19b6178abdf45e7eb7306ea Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Wed, 1 Nov 2023 00:24:16 +0800 Subject: [PATCH 07/34] Change error conditions --- src/main/java/appeng/me/cache/GridStorageCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index a246f7b93d5..50675d87dd1 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -76,7 +76,7 @@ public void onUpdateTick() { this.fluidMonitor.onTick(); // update every 1000Ticks - if (this.ticksCount >= 1000) { + if (this.ticksCount <= 1000) { this.ticksCount++; } else { this.ticksCount = 0; From 4869ca9a3de154ccafc4c7c341006f56f164b3a7 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Wed, 1 Nov 2023 00:32:20 +0800 Subject: [PATCH 08/34] Change delay from 1000t(50s) to 100t(5s) --- src/main/java/appeng/me/cache/GridStorageCache.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 50675d87dd1..32b2ce6de40 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -75,8 +75,8 @@ public void onUpdateTick() { this.itemMonitor.onTick(); this.fluidMonitor.onTick(); - // update every 1000Ticks - if (this.ticksCount <= 1000) { + // update every 100Ticks + if (this.ticksCount <= 100) { this.ticksCount++; } else { this.ticksCount = 0; From 13fe5b02e0dc356c6e4861ff3d9c468dab8ba371 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Wed, 1 Nov 2023 00:35:57 +0800 Subject: [PATCH 09/34] Let cache update data at the beginning --- src/main/java/appeng/me/cache/GridStorageCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 32b2ce6de40..fc02797cd5c 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -67,7 +67,7 @@ public class GridStorageCache implements IStorageGrid { public GridStorageCache(final IGrid g) { this.myGrid = g; - this.ticksCount = 0; + this.ticksCount = 100; } @Override From d09184e8a376448f637df87eb0d490eb0fb4607a Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Thu, 2 Nov 2023 00:13:02 +0800 Subject: [PATCH 10/34] Add a cfg that can change the cache update rate --- src/main/java/appeng/core/AEConfig.java | 11 ++++ .../appeng/me/cache/GridStorageCache.java | 64 ++++++++++--------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/main/java/appeng/core/AEConfig.java b/src/main/java/appeng/core/AEConfig.java index bae760fb996..11ff9a63164 100644 --- a/src/main/java/appeng/core/AEConfig.java +++ b/src/main/java/appeng/core/AEConfig.java @@ -55,6 +55,7 @@ public final class AEConfig extends Configuration implements IConfigurableObject public int storageBiomeID = -1; public int storageProviderID = -1; public int formationPlaneEntityLimit = 128; + public int networkBytesUpdateFrequency = 5; public float spawnChargedChance = 0.92f; public int quartzOresPerCluster = 4; public int quartzOresClusterAmount = 15; @@ -191,6 +192,16 @@ public AEConfig(final File configFile) { this.formationPlaneEntityLimit = this .get("automation", "formationPlaneEntityLimit", this.formationPlaneEntityLimit) .getInt(this.formationPlaneEntityLimit); + this.networkBytesUpdateFrequency = this + .get("automation", "networkBytesUpdateFrequency", this.networkBytesUpdateFrequency) + .getInt(this.networkBytesUpdateFrequency); + if (this.networkBytesUpdateFrequency == 0) { + throw new IllegalArgumentException("networkBytesUpdateFrequency can not be 0!"); + } + this.get( + "automation", + "networkBytesUpdateFrequency", + this.networkBytesUpdateFrequency).comment = "#Network bytes information update Frequency(s) default:5"; this.wirelessTerminalBattery = this.get("battery", "wirelessTerminal", this.wirelessTerminalBattery) .getInt(this.wirelessTerminalBattery); diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index fc02797cd5c..ce44ecf94c5 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -41,6 +41,7 @@ import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; +import appeng.core.AEConfig; import appeng.me.helpers.GenericInterestManager; import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.DriveWatcher; @@ -63,11 +64,13 @@ public class GridStorageCache implements IStorageGrid { private NetworkInventoryHandler myFluidNetwork; private long itemBytesTotal; private long itemBytesUsed; - private short ticksCount; + private int ticksCount; + private int networkBytesUpdateFrequency; public GridStorageCache(final IGrid g) { this.myGrid = g; - this.ticksCount = 100; + this.networkBytesUpdateFrequency = AEConfig.instance.networkBytesUpdateFrequency * 20; + this.ticksCount = this.networkBytesUpdateFrequency; } @Override @@ -75,36 +78,12 @@ public void onUpdateTick() { this.itemMonitor.onTick(); this.fluidMonitor.onTick(); - // update every 100Ticks - if (this.ticksCount <= 100) { + // update every 100Ticks by default + if (this.ticksCount < this.networkBytesUpdateFrequency) { this.ticksCount++; } else { this.ticksCount = 0; - this.itemBytesTotal = 0; - this.itemBytesUsed = 0; - try { - for (ICellProvider icp : this.activeCellProviders) { - if (icp instanceof TileDrive) { - // All Item Cell - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { - // exclude void cell - if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { - continue; - } - // exclude creative cell - if (((DriveWatcher) meih) - .getInternal() instanceof CellInventoryHandler handler) { - if (handler.getCellInv() != null) { - itemBytesTotal += handler.getCellInv().getTotalBytes(); - itemBytesUsed += handler.getCellInv().getUsedBytes(); - } - } - } - } - } - } catch (Exception e) { - // XD Normally won't be here, just normally.. - } + this.updateBytesInfo(); } } @@ -371,6 +350,33 @@ public void applyChanges() { } } + private void updateBytesInfo() { + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + try { + for (ICellProvider icp : this.activeCellProviders) { + if (icp instanceof TileDrive) { + // All Item Cell + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + // exclude void cell + if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { + continue; + } + // exclude creative cell + if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { + if (handler.getCellInv() != null) { + itemBytesTotal += handler.getCellInv().getTotalBytes(); + itemBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + } + } + } + } catch (Exception e) { + // XD Normally won't be here, just normally.. + } + } + public long getItemBytesTotal() { return this.itemBytesTotal; } From 1bc8db3744041779df5e24b304b5d0b3ad2f16af Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Thu, 2 Nov 2023 23:42:02 +0800 Subject: [PATCH 11/34] Add fluid bytes information --- build.gradle | 5 ++- dependencies.gradle | 2 + .../gui/implementations/GuiNetworkStatus.java | 35 +++++++++++++++-- .../ContainerNetworkStatus.java | 36 ++++++++++++++++++ .../appeng/core/localization/GuiText.java | 11 ++++-- .../appeng/me/cache/GridStorageCache.java | 24 ++++++++++++ .../appliedenergistics2/lang/en_US.lang | 9 +++-- .../appliedenergistics2/lang/zh_CN.lang | 9 +++-- .../textures/guis/networkstatus.png | Bin 2721 -> 2929 bytes 9 files changed, 115 insertions(+), 16 deletions(-) diff --git a/build.gradle b/build.gradle index e59189c8951..068308e3e73 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1697697256 +//version: 1698936026 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -646,7 +646,7 @@ repositories { def mixinProviderGroup = "io.github.legacymoddingmc" def mixinProviderModule = "unimixins" -def mixinProviderVersion = "0.1.7.1" +def mixinProviderVersion = "0.1.13" def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" ext.mixinProviderSpec = mixinProviderSpec @@ -906,6 +906,7 @@ runClient17Task.configure { mainClass = "GradleStart" username = minecraft.username userUUID = minecraft.userUUID +// jvmArgs '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' } def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") diff --git a/dependencies.gradle b/dependencies.gradle index f0f0f9dfdb0..4884243e660 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,6 +3,8 @@ dependencies { implementation('com.github.GTNewHorizons:NotEnoughItems:2.4.6-GTNH:dev') implementation('curse.maven:cofh-core-69162:2388751') + compileOnly('com.github.GTNewHorizons:AE2FluidCraft-Rework:1.1.42-gtnh:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.4.13-GTNH:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.36:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.3.4:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.73:dev') {transitive = false} diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index c0475eab8e8..a9ba3d55076 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -52,7 +52,7 @@ public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkToo this.setScrollBar(scrollbar); this.repo = new ItemRepo(scrollbar, this); - this.ySize = 183; + this.ySize = 213; this.xSize = 195; this.repo.setRowSize(5); } @@ -141,13 +141,15 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final 13, 143 - 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); + + // Item byte status this.fontRendererObj.drawString( - GuiText.ByteTotal.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesTotal()), + GuiText.ItemBytesTotal.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesTotal()), 13, 143, GuiColors.NetworkStatusPowerUsageRate.getColor()); this.fontRendererObj.drawString( - GuiText.ByteUsage.getLocal() + ": " + GuiText.ItemBytesUsage.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesUsed()) + " (" + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) @@ -156,7 +158,7 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final 143 + 10, GuiColors.NetworkStatusPowerUsageRate.getColor()); this.fontRendererObj.drawString( - GuiText.ByteFree.getLocal() + ": " + GuiText.ItemBytesFree.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesFree()) + " (" + df.format(ns.getItemBytesFree() * 100d / ns.getItemBytesTotal()) @@ -165,6 +167,31 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final 143 + 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); + // Fluid byte status + this.fontRendererObj.drawString( + GuiText.FluidBytesTotal.getLocal() + ": " + Platform.formatByteLong(ns.getFluidBytesTotal()), + 13, + 143 + 30, + GuiColors.NetworkStatusPowerUsageRate.getColor()); + this.fontRendererObj.drawString( + GuiText.FluidBytesUsage.getLocal() + ": " + + Platform.formatByteLong(ns.getFluidBytesUsed()) + + " (" + + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) + + "%)", + 13, + 143 + 40, + GuiColors.NetworkStatusPowerUsageRate.getColor()); + this.fontRendererObj.drawString( + GuiText.FluidBytesFree.getLocal() + ": " + + Platform.formatByteLong(ns.getFluidBytesFree()) + + " (" + + df.format(ns.getFluidBytesFree() * 100d / ns.getFluidBytesTotal()) + + "%)", + 13, + 143 + 50, + GuiColors.NetworkStatusPowerUsageRate.getColor()); + final int sectionLength = 30; int x = 0; diff --git a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java index 2ae47f02954..be774b2ffdd 100644 --- a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java +++ b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java @@ -60,6 +60,15 @@ public class ContainerNetworkStatus extends AEBaseContainer { @GuiSync(6) public long itemBytesFree; + @GuiSync(7) + public long fluidBytesTotal; + + @GuiSync(8) + public long fluidBytesUsed; + + @GuiSync(9) + public long fluidBytesFree; + private IGrid network; private int delay = 40; @@ -137,6 +146,9 @@ public void detectAndSendChanges() { this.setItemBytesTotal(sg.getItemBytesTotal()); this.setItemBytesUsed(sg.getItemBytesUsed()); this.setItemBytesFree(this.getItemBytesTotal() - this.getItemBytesUsed()); + this.setFluidBytesTotal(sg.getFluidBytesTotal()); + this.setFluidBytesUsed(sg.getFluidBytesUsed()); + this.setFluidBytesFree(this.getFluidBytesTotal() - this.getFluidBytesUsed()); } } super.detectAndSendChanges(); @@ -197,4 +209,28 @@ public void setItemBytesUsed(final long itemBytesUsed) { public void setItemBytesFree(final long itemBytesFree) { this.itemBytesFree = itemBytesFree; } + + public long getFluidBytesTotal() { + return this.fluidBytesTotal; + } + + public long getFluidBytesUsed() { + return this.fluidBytesUsed; + } + + public long getFluidBytesFree() { + return this.fluidBytesFree; + } + + public void setFluidBytesTotal(final long fluidBytesTotal) { + this.fluidBytesTotal = fluidBytesTotal; + } + + public void setFluidBytesUsed(final long fluidBytesUsed) { + this.fluidBytesUsed = fluidBytesUsed; + } + + public void setFluidBytesFree(final long fluidBytesFree) { + this.fluidBytesFree = fluidBytesFree; + } } diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index abe2b8f0f66..b6b8d7e6b14 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -207,10 +207,13 @@ public enum GuiText { // If a thing is deprecated Deprecated, - // mine - ByteTotal, - ByteUsage, - ByteFree; + // Network bytes status + ItemBytesTotal, + ItemBytesUsage, + ItemBytesFree, + FluidBytesTotal, + FluidBytesUsage, + FluidBytesFree; private final String root; diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index ce44ecf94c5..e165d4e8ec2 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -15,6 +15,7 @@ import java.util.LinkedList; import java.util.List; +import com.glodblock.github.common.storage.FluidCellInventoryHandler; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; @@ -46,6 +47,7 @@ import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.DriveWatcher; import appeng.me.storage.ItemWatcher; +import appeng.me.storage.MEInventoryHandler; import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.VoidCellInventory; import appeng.tile.storage.TileDrive; @@ -64,6 +66,8 @@ public class GridStorageCache implements IStorageGrid { private NetworkInventoryHandler myFluidNetwork; private long itemBytesTotal; private long itemBytesUsed; + private long fluidBytesTotal; + private long fluidBytesUsed; private int ticksCount; private int networkBytesUpdateFrequency; @@ -353,6 +357,8 @@ public void applyChanges() { private void updateBytesInfo() { this.itemBytesTotal = 0; this.itemBytesUsed = 0; + this.fluidBytesTotal = 0; + this.fluidBytesUsed = 0; try { for (ICellProvider icp : this.activeCellProviders) { if (icp instanceof TileDrive) { @@ -370,6 +376,16 @@ private void updateBytesInfo() { } } } + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { + // FluidCellInventoryHandler MEInventoryHandler + if (((MEInventoryHandler) meih) + .getInternal() instanceof FluidCellInventoryHandler handler) { + if (handler.getCellInv() != null) { + fluidBytesTotal += handler.getCellInv().getTotalBytes(); + fluidBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + } } } } catch (Exception e) { @@ -385,4 +401,12 @@ public long getItemBytesUsed() { return this.itemBytesUsed; } + public long getFluidBytesTotal() { + return this.fluidBytesTotal; + } + + public long getFluidBytesUsed() { + return this.fluidBytesUsed; + } + } diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index feb44c80672..4af272dacc0 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -272,9 +272,12 @@ gui.appliedenergistics2.Nothing=Nothing gui.appliedenergistics2.VoidCellTooltip=Deletes §4everything§7 stored on it gui.appliedenergistics2.Deprecated=Deprecated, will be removed soon! -gui.appliedenergistics2.ByteTotal=Bytes Total -gui.appliedenergistics2.ByteUsage=Bytes Used -gui.appliedenergistics2.ByteFree=Bytes Free +gui.appliedenergistics2.ItemBytesTotal=Item Bytes Total +gui.appliedenergistics2.ItemBytesUsage=Item Bytes Used +gui.appliedenergistics2.ItemBytesFree=Item Bytes Free +gui.appliedenergistics2.FluidBytesTotal=Fluid Bytes Total +gui.appliedenergistics2.FluidBytesUsage=Fluid Bytes Used +gui.appliedenergistics2.FluidBytesFree=Fluid Bytes Free # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 156fedaada6..759b5248d25 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -265,9 +265,12 @@ gui.appliedenergistics2.HoldShiftClick_HIGHLIGHT_INTERFACE=shift点击,高亮ME gui.appliedenergistics2.VoidCellTooltip=删除§任何§7存储在里面的物品 gui.appliedenergistics2.Nothing=无 -gui.appliedenergistics2.ByteTotal=所有字节 -gui.appliedenergistics2.ByteUsage=已用字节 -gui.appliedenergistics2.ByteFree=剩余字节 +gui.appliedenergistics2.ItemBytesTotal=物品字节总数 +gui.appliedenergistics2.ItemBytesUsage=已使用物品字节 +gui.appliedenergistics2.ItemBytesFree=剩余物品字节 +gui.appliedenergistics2.FluidBytesTotal=流体字节总数 +gui.appliedenergistics2.FluidBytesUsage=已使用流体字节 +gui.appliedenergistics2.FluidBytesFree=剩余流体字节 # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png b/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png index b1f38e0c21798ed6a8940ad7893f5109e8b21cf5..302c10f40ea0bbd4036b42052db3a2b46a18770f 100644 GIT binary patch delta 213 zcmZ1|`cZ6x1rxjSMyoC+UPE02qYxt_D-$CtBZJ8onH11O{xJopSQr~6o1_^V=o%Ya z8t59Dm?Y|2rY0xrnwzE=8Jim!n42b>ZZ2Xz#xyyD)y#z$)k+G*C9Y*9R^=I~dA3SM z21drZhR80NtitLrS&1#5<-xDIu+3B1E-+30z!5b$mGg|)2L8uPUe40?Wl{`4;OXk; Jvd$@?2>_;WI~xE1 delta 83 zcmew;wor6}1ruBFMyoES$=6s#C*Nd}0Ml&D9+T&>s% Date: Fri, 3 Nov 2023 12:57:42 +0800 Subject: [PATCH 12/34] Add essentia status and change gui form --- dependencies.gradle | 2 +- .../gui/implementations/GuiNetworkStatus.java | 53 +- .../ContainerNetworkStatus.java | 46 +- .../appeng/core/localization/GuiText.java | 9 +- .../appeng/me/cache/GridStorageCache.java | 735 +++++++++--------- .../appliedenergistics2/lang/en_US.lang | 9 +- .../appliedenergistics2/lang/zh_CN.lang | 9 +- .../appliedenergistics2/lang/zh_TW.lang | 4 + .../textures/guis/networkstatus.png | Bin 2929 -> 2929 bytes 9 files changed, 436 insertions(+), 431 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 4884243e660..80ba0962c38 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,8 +3,8 @@ dependencies { implementation('com.github.GTNewHorizons:NotEnoughItems:2.4.6-GTNH:dev') implementation('curse.maven:cofh-core-69162:2388751') + compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.4.13-GTNH:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:AE2FluidCraft-Rework:1.1.42-gtnh:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.4.13-GTNH:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.36:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.3.4:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.73:dev') {transitive = false} diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index a9ba3d55076..31acef46b8b 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -52,7 +52,7 @@ public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkToo this.setScrollBar(scrollbar); this.repo = new ItemRepo(scrollbar, this); - this.ySize = 213; + this.ySize = 183; this.xSize = 195; this.repo.setRowSize(5); } @@ -144,53 +144,34 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final // Item byte status this.fontRendererObj.drawString( - GuiText.ItemBytesTotal.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesTotal()), + GuiText.Items.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesUsed()) + + " / " + Platform.formatByteLong(ns.getItemBytesTotal()) + + " (" + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + + "%)", 13, 143, GuiColors.NetworkStatusPowerUsageRate.getColor()); + + // Fluid byte status this.fontRendererObj.drawString( - GuiText.ItemBytesUsage.getLocal() + ": " - + Platform.formatByteLong(ns.getItemBytesUsed()) - + " (" - + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) - + "%)", + GuiText.Fluids.getLocal() + ": " + Platform.formatByteLong(ns.getFluidBytesUsed()) + + " / " + Platform.formatByteLong(ns.getFluidBytesTotal()) + + " (" + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) + + "%)", 13, 143 + 10, GuiColors.NetworkStatusPowerUsageRate.getColor()); + + // Essential byte status this.fontRendererObj.drawString( - GuiText.ItemBytesFree.getLocal() + ": " - + Platform.formatByteLong(ns.getItemBytesFree()) - + " (" - + df.format(ns.getItemBytesFree() * 100d / ns.getItemBytesTotal()) - + "%)", + GuiText.Essentias.getLocal() + ": " + Platform.formatByteLong(ns.getEssentiaBytesUsed()) + + " / " + Platform.formatByteLong(ns.getEssentiaBytesTotal()) + + " (" + df.format(ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal()) + + "%)", 13, 143 + 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); - // Fluid byte status - this.fontRendererObj.drawString( - GuiText.FluidBytesTotal.getLocal() + ": " + Platform.formatByteLong(ns.getFluidBytesTotal()), - 13, - 143 + 30, - GuiColors.NetworkStatusPowerUsageRate.getColor()); - this.fontRendererObj.drawString( - GuiText.FluidBytesUsage.getLocal() + ": " - + Platform.formatByteLong(ns.getFluidBytesUsed()) - + " (" - + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) - + "%)", - 13, - 143 + 40, - GuiColors.NetworkStatusPowerUsageRate.getColor()); - this.fontRendererObj.drawString( - GuiText.FluidBytesFree.getLocal() + ": " - + Platform.formatByteLong(ns.getFluidBytesFree()) - + " (" - + df.format(ns.getFluidBytesFree() * 100d / ns.getFluidBytesTotal()) - + "%)", - 13, - 143 + 50, - GuiColors.NetworkStatusPowerUsageRate.getColor()); final int sectionLength = 30; diff --git a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java index be774b2ffdd..6b80e79d463 100644 --- a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java +++ b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java @@ -58,16 +58,17 @@ public class ContainerNetworkStatus extends AEBaseContainer { public long itemBytesUsed; @GuiSync(6) - public long itemBytesFree; - - @GuiSync(7) public long fluidBytesTotal; - @GuiSync(8) + @GuiSync(7) public long fluidBytesUsed; + + @GuiSync(8) + public long essentiaBytesTotal; @GuiSync(9) - public long fluidBytesFree; + public long essentiaBytesUsed; + private IGrid network; private int delay = 40; @@ -145,10 +146,10 @@ public void detectAndSendChanges() { if (sg != null) { this.setItemBytesTotal(sg.getItemBytesTotal()); this.setItemBytesUsed(sg.getItemBytesUsed()); - this.setItemBytesFree(this.getItemBytesTotal() - this.getItemBytesUsed()); this.setFluidBytesTotal(sg.getFluidBytesTotal()); this.setFluidBytesUsed(sg.getFluidBytesUsed()); - this.setFluidBytesFree(this.getFluidBytesTotal() - this.getFluidBytesUsed()); + this.setEssentiaBytesTotal(sg.getEssentiaBytesTotal()); + this.setEssentiaBytesUsed(sg.getEssentiaBytesUsed()); } } super.detectAndSendChanges(); @@ -194,10 +195,6 @@ public long getItemBytesUsed() { return this.itemBytesUsed; } - public long getItemBytesFree() { - return this.itemBytesFree; - } - public void setItemBytesTotal(final long itemBytesTotal) { this.itemBytesTotal = itemBytesTotal; } @@ -206,10 +203,6 @@ public void setItemBytesUsed(final long itemBytesUsed) { this.itemBytesUsed = itemBytesUsed; } - public void setItemBytesFree(final long itemBytesFree) { - this.itemBytesFree = itemBytesFree; - } - public long getFluidBytesTotal() { return this.fluidBytesTotal; } @@ -218,10 +211,6 @@ public long getFluidBytesUsed() { return this.fluidBytesUsed; } - public long getFluidBytesFree() { - return this.fluidBytesFree; - } - public void setFluidBytesTotal(final long fluidBytesTotal) { this.fluidBytesTotal = fluidBytesTotal; } @@ -230,7 +219,20 @@ public void setFluidBytesUsed(final long fluidBytesUsed) { this.fluidBytesUsed = fluidBytesUsed; } - public void setFluidBytesFree(final long fluidBytesFree) { - this.fluidBytesFree = fluidBytesFree; - } + public long getEssentiaBytesTotal() { + return essentiaBytesTotal; + } + + public long getEssentiaBytesUsed() { + return essentiaBytesUsed; + } + + public void setEssentiaBytesTotal(long essentiaBytesTotal) { + this.essentiaBytesTotal = essentiaBytesTotal; + } + + public void setEssentiaBytesUsed(long essentiaBytesUsed) { + this.essentiaBytesUsed = essentiaBytesUsed; + } + } diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index b6b8d7e6b14..bac6ba14825 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -208,12 +208,9 @@ public enum GuiText { Deprecated, // Network bytes status - ItemBytesTotal, - ItemBytesUsage, - ItemBytesFree, - FluidBytesTotal, - FluidBytesUsage, - FluidBytesFree; + Items, + Fluids, + Essentias; private final String root; diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index e165d4e8ec2..aa8e3a849d4 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -51,362 +51,389 @@ import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.VoidCellInventory; import appeng.tile.storage.TileDrive; +import thaumicenergistics.common.inventory.HandlerItemEssentiaCell; +import thaumicenergistics.common.inventory.HandlerItemEssentiaCellCreative; public class GridStorageCache implements IStorageGrid { - private final IGrid myGrid; - private final HashSet activeCellProviders = new HashSet<>(); - private final HashSet inactiveCellProviders = new HashSet<>(); - private final SetMultimap interests = HashMultimap.create(); - private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); - private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); - private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); - private final HashMap watchers = new HashMap<>(); - private NetworkInventoryHandler myItemNetwork; - private NetworkInventoryHandler myFluidNetwork; - private long itemBytesTotal; - private long itemBytesUsed; - private long fluidBytesTotal; - private long fluidBytesUsed; - private int ticksCount; - private int networkBytesUpdateFrequency; - - public GridStorageCache(final IGrid g) { - this.myGrid = g; - this.networkBytesUpdateFrequency = AEConfig.instance.networkBytesUpdateFrequency * 20; - this.ticksCount = this.networkBytesUpdateFrequency; - } - - @Override - public void onUpdateTick() { - this.itemMonitor.onTick(); - this.fluidMonitor.onTick(); - - // update every 100Ticks by default - if (this.ticksCount < this.networkBytesUpdateFrequency) { - this.ticksCount++; - } else { - this.ticksCount = 0; - this.updateBytesInfo(); - } - } - - @Override - public void removeNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.removeCellProvider(cc, tracker); - this.inactiveCellProviders.remove(cc); - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - tracker.applyChanges(); - } - - if (machine instanceof IStackWatcherHost) { - final IStackWatcher myWatcher = this.watchers.get(machine); - - if (myWatcher != null) { - myWatcher.clear(); - this.watchers.remove(machine); - } - } - } - - @Override - public void addNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - this.inactiveCellProviders.add(cc); - - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - if (node.isActive()) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.addCellProvider(cc, tracker); - tracker.applyChanges(); - } - } - - if (machine instanceof IStackWatcherHost swh) { - final ItemWatcher iw = new ItemWatcher(this, swh); - this.watchers.put(node, iw); - swh.updateWatcher(iw); - } - } - - @Override - public void onSplit(final IGridStorage storageB) {} - - @Override - public void onJoin(final IGridStorage storageB) {} - - @Override - public void populateGridStorage(final IGridStorage storage) {} - - private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.inactiveCellProviders.contains(cc)) { - this.inactiveCellProviders.remove(cc); - this.activeCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); - } - } - - return tracker; - } - - private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.activeCellProviders.contains(cc)) { - this.activeCellProviders.remove(cc); - this.inactiveCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); - } - } - - return tracker; - } - - @MENetworkEventSubscribe - public void cellUpdate(final MENetworkCellArrayUpdate ev) { - this.myItemNetwork = null; - this.myFluidNetwork = null; - - final LinkedList ll = new LinkedList(); - ll.addAll(this.inactiveCellProviders); - ll.addAll(this.activeCellProviders); - - final CellChangeTracker tracker = new CellChangeTracker(); - - for (final ICellProvider cc : ll) { - boolean active = true; - - if (cc instanceof IActionHost) { - final IGridNode node = ((IActionHost) cc).getActionableNode(); - active = node != null && node.isActive(); - } - - if (active) { - this.addCellProvider(cc, tracker); - } else { - this.removeCellProvider(cc, tracker); - } - } - - this.itemMonitor.forceUpdate(); - this.fluidMonitor.forceUpdate(); - - tracker.applyChanges(); - - } - - private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, - final BaseActionSource src) { - switch (chan) { - case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); - case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); - default -> {} - } - } - - IMEInventoryHandler getItemInventoryHandler() { - if (this.myItemNetwork == null) { - this.buildNetworkStorage(StorageChannel.ITEMS); - } - return this.myItemNetwork; - } - - private void buildNetworkStorage(final StorageChannel chan) { - final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); - - switch (chan) { - case FLUIDS -> { - this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myFluidNetwork.addNewStorage(h); - } - } - } - case ITEMS -> { - this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myItemNetwork.addNewStorage(h); - } - } - } - default -> {} - } - } - - IMEInventoryHandler getFluidInventoryHandler() { - if (this.myFluidNetwork == null) { - this.buildNetworkStorage(StorageChannel.FLUIDS); - } - return this.myFluidNetwork; - } - - @Override - public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, - final BaseActionSource src) { - if (chan == StorageChannel.ITEMS) { - this.itemMonitor.postChange(true, (Iterable) input, src); - } else if (chan == StorageChannel.FLUIDS) { - this.fluidMonitor.postChange(true, (Iterable) input, src); - } - } - - @Override - public void registerCellProvider(final ICellProvider provider) { - this.inactiveCellProviders.add(provider); - this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); - } - - @Override - public void unregisterCellProvider(final ICellProvider provider) { - this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); - this.inactiveCellProviders.remove(provider); - } - - @Override - public IMEMonitor getItemInventory() { - return this.itemMonitor; - } - - @Override - public IMEMonitor getFluidInventory() { - return this.fluidMonitor; - } - - public GenericInterestManager getInterestManager() { - return this.interestManager; - } - - IGrid getGrid() { - return this.myGrid; - } - - private class CellChangeTrackerRecord { - - final StorageChannel channel; - final int up_or_down; - final IItemList list; - final BaseActionSource src; - - public CellChangeTrackerRecord(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.channel = channel; - this.up_or_down = i; - this.src = actionSrc; - - if (channel == StorageChannel.ITEMS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createItemList()); - } else if (channel == StorageChannel.FLUIDS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createFluidList()); - } else { - this.list = null; - } - } - - public void applyChanges() { - GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); - } - } - - private class CellChangeTracker { - - final List data = new LinkedList<>(); - - public void postChanges(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); - } - - public void applyChanges() { - for (final CellChangeTrackerRecord rec : this.data) { - rec.applyChanges(); - } - } - } - - private void updateBytesInfo() { - this.itemBytesTotal = 0; - this.itemBytesUsed = 0; - this.fluidBytesTotal = 0; - this.fluidBytesUsed = 0; - try { - for (ICellProvider icp : this.activeCellProviders) { - if (icp instanceof TileDrive) { - // All Item Cell - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { - // exclude void cell - if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { - continue; - } - // exclude creative cell - if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { - if (handler.getCellInv() != null) { - itemBytesTotal += handler.getCellInv().getTotalBytes(); - itemBytesUsed += handler.getCellInv().getUsedBytes(); - } - } - } - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { - // FluidCellInventoryHandler MEInventoryHandler - if (((MEInventoryHandler) meih) - .getInternal() instanceof FluidCellInventoryHandler handler) { - if (handler.getCellInv() != null) { - fluidBytesTotal += handler.getCellInv().getTotalBytes(); - fluidBytesUsed += handler.getCellInv().getUsedBytes(); - } - } - } - } - } - } catch (Exception e) { - // XD Normally won't be here, just normally.. - } - } - - public long getItemBytesTotal() { - return this.itemBytesTotal; - } - - public long getItemBytesUsed() { - return this.itemBytesUsed; - } - - public long getFluidBytesTotal() { - return this.fluidBytesTotal; - } - - public long getFluidBytesUsed() { - return this.fluidBytesUsed; - } + private final IGrid myGrid; + private final HashSet activeCellProviders = new HashSet<>(); + private final HashSet inactiveCellProviders = new HashSet<>(); + private final SetMultimap interests = HashMultimap.create(); + private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); + private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); + private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); + private final HashMap watchers = new HashMap<>(); + private NetworkInventoryHandler myItemNetwork; + private NetworkInventoryHandler myFluidNetwork; + private long itemBytesTotal; + private long itemBytesUsed; + private long fluidBytesTotal; + private long fluidBytesUsed; + private long essentiaBytesTotal; + private long essentiaBytesUsed; + private int ticksCount; + private int networkBytesUpdateFrequency; + + public GridStorageCache(final IGrid g) { + this.myGrid = g; + this.networkBytesUpdateFrequency = AEConfig.instance.networkBytesUpdateFrequency * 20; + this.ticksCount = this.networkBytesUpdateFrequency; + } + + @Override + public void onUpdateTick() { + this.itemMonitor.onTick(); + this.fluidMonitor.onTick(); + + // update every 100Ticks by default + if (this.ticksCount < this.networkBytesUpdateFrequency) { + this.ticksCount++; + } else { + this.ticksCount = 0; + this.updateBytesInfo(); + } + } + + @Override + public void removeNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.removeCellProvider(cc, tracker); + this.inactiveCellProviders.remove(cc); + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + tracker.applyChanges(); + } + + if (machine instanceof IStackWatcherHost) { + final IStackWatcher myWatcher = this.watchers.get(machine); + + if (myWatcher != null) { + myWatcher.clear(); + this.watchers.remove(machine); + } + } + } + + @Override + public void addNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + this.inactiveCellProviders.add(cc); + + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + if (node.isActive()) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.addCellProvider(cc, tracker); + tracker.applyChanges(); + } + } + + if (machine instanceof IStackWatcherHost swh) { + final ItemWatcher iw = new ItemWatcher(this, swh); + this.watchers.put(node, iw); + swh.updateWatcher(iw); + } + } + + @Override + public void onSplit(final IGridStorage storageB) { + } + + @Override + public void onJoin(final IGridStorage storageB) { + } + + @Override + public void populateGridStorage(final IGridStorage storage) { + } + + private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.inactiveCellProviders.contains(cc)) { + this.inactiveCellProviders.remove(cc); + this.activeCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); + } + } + + return tracker; + } + + private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.activeCellProviders.contains(cc)) { + this.activeCellProviders.remove(cc); + this.inactiveCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); + } + } + + return tracker; + } + + @MENetworkEventSubscribe + public void cellUpdate(final MENetworkCellArrayUpdate ev) { + this.myItemNetwork = null; + this.myFluidNetwork = null; + + final LinkedList ll = new LinkedList(); + ll.addAll(this.inactiveCellProviders); + ll.addAll(this.activeCellProviders); + + final CellChangeTracker tracker = new CellChangeTracker(); + + for (final ICellProvider cc : ll) { + boolean active = true; + + if (cc instanceof IActionHost) { + final IGridNode node = ((IActionHost) cc).getActionableNode(); + active = node != null && node.isActive(); + } + + if (active) { + this.addCellProvider(cc, tracker); + } else { + this.removeCellProvider(cc, tracker); + } + } + + this.itemMonitor.forceUpdate(); + this.fluidMonitor.forceUpdate(); + + tracker.applyChanges(); + + } + + private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, + final BaseActionSource src) { + switch (chan) { + case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); + case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); + default -> { + } + } + } + + IMEInventoryHandler getItemInventoryHandler() { + if (this.myItemNetwork == null) { + this.buildNetworkStorage(StorageChannel.ITEMS); + } + return this.myItemNetwork; + } + + private void buildNetworkStorage(final StorageChannel chan) { + final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); + + switch (chan) { + case FLUIDS -> { + this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myFluidNetwork.addNewStorage(h); + } + } + } + case ITEMS -> { + this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myItemNetwork.addNewStorage(h); + } + } + } + default -> { + } + } + } + + IMEInventoryHandler getFluidInventoryHandler() { + if (this.myFluidNetwork == null) { + this.buildNetworkStorage(StorageChannel.FLUIDS); + } + return this.myFluidNetwork; + } + + @Override + public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, + final BaseActionSource src) { + if (chan == StorageChannel.ITEMS) { + this.itemMonitor.postChange(true, (Iterable) input, src); + } else if (chan == StorageChannel.FLUIDS) { + this.fluidMonitor.postChange(true, (Iterable) input, src); + } + } + + @Override + public void registerCellProvider(final ICellProvider provider) { + this.inactiveCellProviders.add(provider); + this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); + } + + @Override + public void unregisterCellProvider(final ICellProvider provider) { + this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); + this.inactiveCellProviders.remove(provider); + } + + @Override + public IMEMonitor getItemInventory() { + return this.itemMonitor; + } + + @Override + public IMEMonitor getFluidInventory() { + return this.fluidMonitor; + } + + public GenericInterestManager getInterestManager() { + return this.interestManager; + } + + IGrid getGrid() { + return this.myGrid; + } + + private class CellChangeTrackerRecord { + + final StorageChannel channel; + final int up_or_down; + final IItemList list; + final BaseActionSource src; + + public CellChangeTrackerRecord(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.channel = channel; + this.up_or_down = i; + this.src = actionSrc; + + if (channel == StorageChannel.ITEMS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createItemList()); + } else if (channel == StorageChannel.FLUIDS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createFluidList()); + } else { + this.list = null; + } + } + + public void applyChanges() { + GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); + } + } + + private class CellChangeTracker { + + final List data = new LinkedList<>(); + + public void postChanges(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); + } + + public void applyChanges() { + for (final CellChangeTrackerRecord rec : this.data) { + rec.applyChanges(); + } + } + } + + private void updateBytesInfo() { + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + this.fluidBytesTotal = 0; + this.fluidBytesUsed = 0; + this.essentiaBytesTotal = 0; + this.essentiaBytesUsed = 0; + try { + for (ICellProvider icp : this.activeCellProviders) { + if (icp instanceof TileDrive) { + System.out.println(); + // All Item Cell + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + // exclude void cell + if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { + continue; + } + // exclude creative cell + if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { + if (handler.getCellInv() != null) { + itemBytesTotal += handler.getCellInv().getTotalBytes(); + itemBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + } + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { + // Fluid Cell + if (((MEInventoryHandler) meih) + .getInternal() instanceof FluidCellInventoryHandler handler) { + if (handler.getCellInv() != null) { + fluidBytesTotal += handler.getCellInv().getTotalBytes(); + fluidBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + // Essentia Cell + if (((MEInventoryHandler) meih) + .getInternal() instanceof HandlerItemEssentiaCell handler) { + essentiaBytesTotal += handler.getTotalBytes(); + essentiaBytesUsed += handler.getUsedBytes(); + } + } + + } + } + } catch (Exception e) { + // XD Normally won't be here, just normally.. + } + } + + public long getItemBytesTotal() { + return itemBytesTotal; + } + + public long getItemBytesUsed() { + return itemBytesUsed; + } + + public long getFluidBytesTotal() { + return fluidBytesTotal; + } + + public long getFluidBytesUsed() { + return fluidBytesUsed; + } + + public long getEssentiaBytesTotal() { + return essentiaBytesTotal; + } + + public long getEssentiaBytesUsed() { + return essentiaBytesUsed; + } } diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 4af272dacc0..1163c5ac9c0 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -272,12 +272,9 @@ gui.appliedenergistics2.Nothing=Nothing gui.appliedenergistics2.VoidCellTooltip=Deletes §4everything§7 stored on it gui.appliedenergistics2.Deprecated=Deprecated, will be removed soon! -gui.appliedenergistics2.ItemBytesTotal=Item Bytes Total -gui.appliedenergistics2.ItemBytesUsage=Item Bytes Used -gui.appliedenergistics2.ItemBytesFree=Item Bytes Free -gui.appliedenergistics2.FluidBytesTotal=Fluid Bytes Total -gui.appliedenergistics2.FluidBytesUsage=Fluid Bytes Used -gui.appliedenergistics2.FluidBytesFree=Fluid Bytes Free +gui.appliedenergistics2.Items=Items +gui.appliedenergistics2.Fluids=Fluids +gui.appliedenergistics2.Essentias=Essen # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 759b5248d25..9350785b116 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -265,12 +265,9 @@ gui.appliedenergistics2.HoldShiftClick_HIGHLIGHT_INTERFACE=shift点击,高亮ME gui.appliedenergistics2.VoidCellTooltip=删除§任何§7存储在里面的物品 gui.appliedenergistics2.Nothing=无 -gui.appliedenergistics2.ItemBytesTotal=物品字节总数 -gui.appliedenergistics2.ItemBytesUsage=已使用物品字节 -gui.appliedenergistics2.ItemBytesFree=剩余物品字节 -gui.appliedenergistics2.FluidBytesTotal=流体字节总数 -gui.appliedenergistics2.FluidBytesUsage=已使用流体字节 -gui.appliedenergistics2.FluidBytesFree=剩余流体字节 +gui.appliedenergistics2.Items=物品 +gui.appliedenergistics2.Fluids=流体 +gui.appliedenergistics2.Essentias=源质 # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang index 63fb6a97a3f..2e613f95488 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang @@ -77,6 +77,10 @@ gui.appliedenergistics2.EUTunnel=EU gui.appliedenergistics2.RFTunnel=RF gui.appliedenergistics2.LightTunnel=光 +gui.appliedenergistics2.Items=物品 +gui.appliedenergistics2.Fluids=流體 +gui.appliedenergistics2.Essentias=源質 + gui.appliedenergistics2.security.extract.name=取出 gui.appliedenergistics2.security.inject.name=存入 gui.appliedenergistics2.security.craft.name=合成 diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png b/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png index 302c10f40ea0bbd4036b42052db3a2b46a18770f..185bdc36f77e87a2dac3e599afa0c757cbff858e 100644 GIT binary patch delta 198 zcmew;_EBuZaV9R~5JMv?6LTw565O})!xvX Date: Fri, 3 Nov 2023 16:05:48 +0800 Subject: [PATCH 13/34] Apply the spotlessApply --- .../gui/implementations/GuiNetworkStatus.java | 36 +- .../ContainerNetworkStatus.java | 27 +- .../appeng/me/cache/GridStorageCache.java | 754 +++++++++--------- 3 files changed, 409 insertions(+), 408 deletions(-) diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index 31acef46b8b..d8084f20ad4 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -144,35 +144,43 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final // Item byte status this.fontRendererObj.drawString( - GuiText.Items.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesUsed()) - + " / " + Platform.formatByteLong(ns.getItemBytesTotal()) - + " (" + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) - + "%)", + GuiText.Items.getLocal() + ": " + + Platform.formatByteLong(ns.getItemBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getItemBytesTotal()) + + " (" + + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + + "%)", 13, 143, GuiColors.NetworkStatusPowerUsageRate.getColor()); // Fluid byte status this.fontRendererObj.drawString( - GuiText.Fluids.getLocal() + ": " + Platform.formatByteLong(ns.getFluidBytesUsed()) - + " / " + Platform.formatByteLong(ns.getFluidBytesTotal()) - + " (" + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) - + "%)", + GuiText.Fluids.getLocal() + ": " + + Platform.formatByteLong(ns.getFluidBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getFluidBytesTotal()) + + " (" + + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) + + "%)", 13, 143 + 10, GuiColors.NetworkStatusPowerUsageRate.getColor()); - + // Essential byte status this.fontRendererObj.drawString( - GuiText.Essentias.getLocal() + ": " + Platform.formatByteLong(ns.getEssentiaBytesUsed()) - + " / " + Platform.formatByteLong(ns.getEssentiaBytesTotal()) - + " (" + df.format(ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal()) - + "%)", + GuiText.Essentias.getLocal() + ": " + + Platform.formatByteLong(ns.getEssentiaBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getEssentiaBytesTotal()) + + " (" + + df.format(ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal()) + + "%)", 13, 143 + 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); - final int sectionLength = 30; int x = 0; diff --git a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java index 6b80e79d463..946fe2a33b7 100644 --- a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java +++ b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java @@ -62,14 +62,13 @@ public class ContainerNetworkStatus extends AEBaseContainer { @GuiSync(7) public long fluidBytesUsed; - + @GuiSync(8) public long essentiaBytesTotal; @GuiSync(9) public long essentiaBytesUsed; - private IGrid network; private int delay = 40; @@ -219,20 +218,20 @@ public void setFluidBytesUsed(final long fluidBytesUsed) { this.fluidBytesUsed = fluidBytesUsed; } - public long getEssentiaBytesTotal() { - return essentiaBytesTotal; - } + public long getEssentiaBytesTotal() { + return essentiaBytesTotal; + } - public long getEssentiaBytesUsed() { - return essentiaBytesUsed; - } + public long getEssentiaBytesUsed() { + return essentiaBytesUsed; + } - public void setEssentiaBytesTotal(long essentiaBytesTotal) { - this.essentiaBytesTotal = essentiaBytesTotal; - } + public void setEssentiaBytesTotal(long essentiaBytesTotal) { + this.essentiaBytesTotal = essentiaBytesTotal; + } - public void setEssentiaBytesUsed(long essentiaBytesUsed) { - this.essentiaBytesUsed = essentiaBytesUsed; - } + public void setEssentiaBytesUsed(long essentiaBytesUsed) { + this.essentiaBytesUsed = essentiaBytesUsed; + } } diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index aa8e3a849d4..75c86748850 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -52,388 +52,382 @@ import appeng.me.storage.VoidCellInventory; import appeng.tile.storage.TileDrive; import thaumicenergistics.common.inventory.HandlerItemEssentiaCell; -import thaumicenergistics.common.inventory.HandlerItemEssentiaCellCreative; public class GridStorageCache implements IStorageGrid { - private final IGrid myGrid; - private final HashSet activeCellProviders = new HashSet<>(); - private final HashSet inactiveCellProviders = new HashSet<>(); - private final SetMultimap interests = HashMultimap.create(); - private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); - private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); - private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); - private final HashMap watchers = new HashMap<>(); - private NetworkInventoryHandler myItemNetwork; - private NetworkInventoryHandler myFluidNetwork; - private long itemBytesTotal; - private long itemBytesUsed; - private long fluidBytesTotal; - private long fluidBytesUsed; - private long essentiaBytesTotal; - private long essentiaBytesUsed; - private int ticksCount; - private int networkBytesUpdateFrequency; - - public GridStorageCache(final IGrid g) { - this.myGrid = g; - this.networkBytesUpdateFrequency = AEConfig.instance.networkBytesUpdateFrequency * 20; - this.ticksCount = this.networkBytesUpdateFrequency; - } - - @Override - public void onUpdateTick() { - this.itemMonitor.onTick(); - this.fluidMonitor.onTick(); - - // update every 100Ticks by default - if (this.ticksCount < this.networkBytesUpdateFrequency) { - this.ticksCount++; - } else { - this.ticksCount = 0; - this.updateBytesInfo(); - } - } - - @Override - public void removeNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.removeCellProvider(cc, tracker); - this.inactiveCellProviders.remove(cc); - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - tracker.applyChanges(); - } - - if (machine instanceof IStackWatcherHost) { - final IStackWatcher myWatcher = this.watchers.get(machine); - - if (myWatcher != null) { - myWatcher.clear(); - this.watchers.remove(machine); - } - } - } - - @Override - public void addNode(final IGridNode node, final IGridHost machine) { - if (machine instanceof ICellContainer cc) { - this.inactiveCellProviders.add(cc); - - this.getGrid().postEvent(new MENetworkCellArrayUpdate()); - - if (node.isActive()) { - final CellChangeTracker tracker = new CellChangeTracker(); - - this.addCellProvider(cc, tracker); - tracker.applyChanges(); - } - } - - if (machine instanceof IStackWatcherHost swh) { - final ItemWatcher iw = new ItemWatcher(this, swh); - this.watchers.put(node, iw); - swh.updateWatcher(iw); - } - } - - @Override - public void onSplit(final IGridStorage storageB) { - } - - @Override - public void onJoin(final IGridStorage storageB) { - } - - @Override - public void populateGridStorage(final IGridStorage storage) { - } - - private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.inactiveCellProviders.contains(cc)) { - this.inactiveCellProviders.remove(cc); - this.activeCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); - } - } - - return tracker; - } - - private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { - if (this.activeCellProviders.contains(cc)) { - this.activeCellProviders.remove(cc); - this.inactiveCellProviders.add(cc); - - BaseActionSource actionSrc = new BaseActionSource(); - - if (cc instanceof IActionHost) { - actionSrc = new MachineSource((IActionHost) cc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { - tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); - } - - for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { - tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); - } - } - - return tracker; - } - - @MENetworkEventSubscribe - public void cellUpdate(final MENetworkCellArrayUpdate ev) { - this.myItemNetwork = null; - this.myFluidNetwork = null; - - final LinkedList ll = new LinkedList(); - ll.addAll(this.inactiveCellProviders); - ll.addAll(this.activeCellProviders); - - final CellChangeTracker tracker = new CellChangeTracker(); - - for (final ICellProvider cc : ll) { - boolean active = true; - - if (cc instanceof IActionHost) { - final IGridNode node = ((IActionHost) cc).getActionableNode(); - active = node != null && node.isActive(); - } - - if (active) { - this.addCellProvider(cc, tracker); - } else { - this.removeCellProvider(cc, tracker); - } - } - - this.itemMonitor.forceUpdate(); - this.fluidMonitor.forceUpdate(); - - tracker.applyChanges(); - - } - - private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, - final BaseActionSource src) { - switch (chan) { - case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); - case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); - default -> { - } - } - } - - IMEInventoryHandler getItemInventoryHandler() { - if (this.myItemNetwork == null) { - this.buildNetworkStorage(StorageChannel.ITEMS); - } - return this.myItemNetwork; - } - - private void buildNetworkStorage(final StorageChannel chan) { - final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); - - switch (chan) { - case FLUIDS -> { - this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myFluidNetwork.addNewStorage(h); - } - } - } - case ITEMS -> { - this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); - for (final ICellProvider cc : this.activeCellProviders) { - for (final IMEInventoryHandler h : cc.getCellArray(chan)) { - this.myItemNetwork.addNewStorage(h); - } - } - } - default -> { - } - } - } - - IMEInventoryHandler getFluidInventoryHandler() { - if (this.myFluidNetwork == null) { - this.buildNetworkStorage(StorageChannel.FLUIDS); - } - return this.myFluidNetwork; - } - - @Override - public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, - final BaseActionSource src) { - if (chan == StorageChannel.ITEMS) { - this.itemMonitor.postChange(true, (Iterable) input, src); - } else if (chan == StorageChannel.FLUIDS) { - this.fluidMonitor.postChange(true, (Iterable) input, src); - } - } - - @Override - public void registerCellProvider(final ICellProvider provider) { - this.inactiveCellProviders.add(provider); - this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); - } - - @Override - public void unregisterCellProvider(final ICellProvider provider) { - this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); - this.inactiveCellProviders.remove(provider); - } - - @Override - public IMEMonitor getItemInventory() { - return this.itemMonitor; - } - - @Override - public IMEMonitor getFluidInventory() { - return this.fluidMonitor; - } - - public GenericInterestManager getInterestManager() { - return this.interestManager; - } - - IGrid getGrid() { - return this.myGrid; - } - - private class CellChangeTrackerRecord { - - final StorageChannel channel; - final int up_or_down; - final IItemList list; - final BaseActionSource src; - - public CellChangeTrackerRecord(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.channel = channel; - this.up_or_down = i; - this.src = actionSrc; - - if (channel == StorageChannel.ITEMS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createItemList()); - } else if (channel == StorageChannel.FLUIDS) { - this.list = ((IMEInventoryHandler) h) - .getAvailableItems(AEApi.instance().storage().createFluidList()); - } else { - this.list = null; - } - } - - public void applyChanges() { - GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); - } - } - - private class CellChangeTracker { - - final List data = new LinkedList<>(); - - public void postChanges(final StorageChannel channel, final int i, - final IMEInventoryHandler h, final BaseActionSource actionSrc) { - this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); - } - - public void applyChanges() { - for (final CellChangeTrackerRecord rec : this.data) { - rec.applyChanges(); - } - } - } - - private void updateBytesInfo() { - this.itemBytesTotal = 0; - this.itemBytesUsed = 0; - this.fluidBytesTotal = 0; - this.fluidBytesUsed = 0; - this.essentiaBytesTotal = 0; - this.essentiaBytesUsed = 0; - try { - for (ICellProvider icp : this.activeCellProviders) { - if (icp instanceof TileDrive) { - System.out.println(); - // All Item Cell - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { - // exclude void cell - if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { - continue; - } - // exclude creative cell - if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { - if (handler.getCellInv() != null) { - itemBytesTotal += handler.getCellInv().getTotalBytes(); - itemBytesUsed += handler.getCellInv().getUsedBytes(); - } - } - } - for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { - // Fluid Cell - if (((MEInventoryHandler) meih) - .getInternal() instanceof FluidCellInventoryHandler handler) { - if (handler.getCellInv() != null) { - fluidBytesTotal += handler.getCellInv().getTotalBytes(); - fluidBytesUsed += handler.getCellInv().getUsedBytes(); - } - } - // Essentia Cell - if (((MEInventoryHandler) meih) - .getInternal() instanceof HandlerItemEssentiaCell handler) { - essentiaBytesTotal += handler.getTotalBytes(); - essentiaBytesUsed += handler.getUsedBytes(); - } - } - - } - } - } catch (Exception e) { - // XD Normally won't be here, just normally.. - } - } - - public long getItemBytesTotal() { - return itemBytesTotal; - } - - public long getItemBytesUsed() { - return itemBytesUsed; - } - - public long getFluidBytesTotal() { - return fluidBytesTotal; - } - - public long getFluidBytesUsed() { - return fluidBytesUsed; - } - - public long getEssentiaBytesTotal() { - return essentiaBytesTotal; - } - - public long getEssentiaBytesUsed() { - return essentiaBytesUsed; - } + private final IGrid myGrid; + private final HashSet activeCellProviders = new HashSet<>(); + private final HashSet inactiveCellProviders = new HashSet<>(); + private final SetMultimap interests = HashMultimap.create(); + private final GenericInterestManager interestManager = new GenericInterestManager<>(this.interests); + private final NetworkMonitor itemMonitor = new NetworkMonitor<>(this, StorageChannel.ITEMS); + private final NetworkMonitor fluidMonitor = new NetworkMonitor<>(this, StorageChannel.FLUIDS); + private final HashMap watchers = new HashMap<>(); + private NetworkInventoryHandler myItemNetwork; + private NetworkInventoryHandler myFluidNetwork; + private long itemBytesTotal; + private long itemBytesUsed; + private long fluidBytesTotal; + private long fluidBytesUsed; + private long essentiaBytesTotal; + private long essentiaBytesUsed; + private int ticksCount; + private int networkBytesUpdateFrequency; + + public GridStorageCache(final IGrid g) { + this.myGrid = g; + this.networkBytesUpdateFrequency = AEConfig.instance.networkBytesUpdateFrequency * 20; + this.ticksCount = this.networkBytesUpdateFrequency; + } + + @Override + public void onUpdateTick() { + this.itemMonitor.onTick(); + this.fluidMonitor.onTick(); + + // update every 100Ticks by default + if (this.ticksCount < this.networkBytesUpdateFrequency) { + this.ticksCount++; + } else { + this.ticksCount = 0; + this.updateBytesInfo(); + } + } + + @Override + public void removeNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.removeCellProvider(cc, tracker); + this.inactiveCellProviders.remove(cc); + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + tracker.applyChanges(); + } + + if (machine instanceof IStackWatcherHost) { + final IStackWatcher myWatcher = this.watchers.get(machine); + + if (myWatcher != null) { + myWatcher.clear(); + this.watchers.remove(machine); + } + } + } + + @Override + public void addNode(final IGridNode node, final IGridHost machine) { + if (machine instanceof ICellContainer cc) { + this.inactiveCellProviders.add(cc); + + this.getGrid().postEvent(new MENetworkCellArrayUpdate()); + + if (node.isActive()) { + final CellChangeTracker tracker = new CellChangeTracker(); + + this.addCellProvider(cc, tracker); + tracker.applyChanges(); + } + } + + if (machine instanceof IStackWatcherHost swh) { + final ItemWatcher iw = new ItemWatcher(this, swh); + this.watchers.put(node, iw); + swh.updateWatcher(iw); + } + } + + @Override + public void onSplit(final IGridStorage storageB) {} + + @Override + public void onJoin(final IGridStorage storageB) {} + + @Override + public void populateGridStorage(final IGridStorage storage) {} + + private CellChangeTracker addCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.inactiveCellProviders.contains(cc)) { + this.inactiveCellProviders.remove(cc); + this.activeCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, 1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, 1, h, actionSrc); + } + } + + return tracker; + } + + private CellChangeTracker removeCellProvider(final ICellProvider cc, final CellChangeTracker tracker) { + if (this.activeCellProviders.contains(cc)) { + this.activeCellProviders.remove(cc); + this.inactiveCellProviders.add(cc); + + BaseActionSource actionSrc = new BaseActionSource(); + + if (cc instanceof IActionHost) { + actionSrc = new MachineSource((IActionHost) cc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.ITEMS)) { + tracker.postChanges(StorageChannel.ITEMS, -1, h, actionSrc); + } + + for (final IMEInventoryHandler h : cc.getCellArray(StorageChannel.FLUIDS)) { + tracker.postChanges(StorageChannel.FLUIDS, -1, h, actionSrc); + } + } + + return tracker; + } + + @MENetworkEventSubscribe + public void cellUpdate(final MENetworkCellArrayUpdate ev) { + this.myItemNetwork = null; + this.myFluidNetwork = null; + + final LinkedList ll = new LinkedList(); + ll.addAll(this.inactiveCellProviders); + ll.addAll(this.activeCellProviders); + + final CellChangeTracker tracker = new CellChangeTracker(); + + for (final ICellProvider cc : ll) { + boolean active = true; + + if (cc instanceof IActionHost) { + final IGridNode node = ((IActionHost) cc).getActionableNode(); + active = node != null && node.isActive(); + } + + if (active) { + this.addCellProvider(cc, tracker); + } else { + this.removeCellProvider(cc, tracker); + } + } + + this.itemMonitor.forceUpdate(); + this.fluidMonitor.forceUpdate(); + + tracker.applyChanges(); + + } + + private void postChangesToNetwork(final StorageChannel chan, final int upOrDown, final IItemList availableItems, + final BaseActionSource src) { + switch (chan) { + case FLUIDS -> this.fluidMonitor.postChange(upOrDown > 0, availableItems, src); + case ITEMS -> this.itemMonitor.postChange(upOrDown > 0, availableItems, src); + default -> {} + } + } + + IMEInventoryHandler getItemInventoryHandler() { + if (this.myItemNetwork == null) { + this.buildNetworkStorage(StorageChannel.ITEMS); + } + return this.myItemNetwork; + } + + private void buildNetworkStorage(final StorageChannel chan) { + final SecurityCache security = this.getGrid().getCache(ISecurityGrid.class); + + switch (chan) { + case FLUIDS -> { + this.myFluidNetwork = new NetworkInventoryHandler<>(StorageChannel.FLUIDS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myFluidNetwork.addNewStorage(h); + } + } + } + case ITEMS -> { + this.myItemNetwork = new NetworkInventoryHandler<>(StorageChannel.ITEMS, security); + for (final ICellProvider cc : this.activeCellProviders) { + for (final IMEInventoryHandler h : cc.getCellArray(chan)) { + this.myItemNetwork.addNewStorage(h); + } + } + } + default -> {} + } + } + + IMEInventoryHandler getFluidInventoryHandler() { + if (this.myFluidNetwork == null) { + this.buildNetworkStorage(StorageChannel.FLUIDS); + } + return this.myFluidNetwork; + } + + @Override + public void postAlterationOfStoredItems(final StorageChannel chan, final Iterable input, + final BaseActionSource src) { + if (chan == StorageChannel.ITEMS) { + this.itemMonitor.postChange(true, (Iterable) input, src); + } else if (chan == StorageChannel.FLUIDS) { + this.fluidMonitor.postChange(true, (Iterable) input, src); + } + } + + @Override + public void registerCellProvider(final ICellProvider provider) { + this.inactiveCellProviders.add(provider); + this.addCellProvider(provider, new CellChangeTracker()).applyChanges(); + } + + @Override + public void unregisterCellProvider(final ICellProvider provider) { + this.removeCellProvider(provider, new CellChangeTracker()).applyChanges(); + this.inactiveCellProviders.remove(provider); + } + + @Override + public IMEMonitor getItemInventory() { + return this.itemMonitor; + } + + @Override + public IMEMonitor getFluidInventory() { + return this.fluidMonitor; + } + + public GenericInterestManager getInterestManager() { + return this.interestManager; + } + + IGrid getGrid() { + return this.myGrid; + } + + private class CellChangeTrackerRecord { + + final StorageChannel channel; + final int up_or_down; + final IItemList list; + final BaseActionSource src; + + public CellChangeTrackerRecord(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.channel = channel; + this.up_or_down = i; + this.src = actionSrc; + + if (channel == StorageChannel.ITEMS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createItemList()); + } else if (channel == StorageChannel.FLUIDS) { + this.list = ((IMEInventoryHandler) h) + .getAvailableItems(AEApi.instance().storage().createFluidList()); + } else { + this.list = null; + } + } + + public void applyChanges() { + GridStorageCache.this.postChangesToNetwork(this.channel, this.up_or_down, this.list, this.src); + } + } + + private class CellChangeTracker { + + final List data = new LinkedList<>(); + + public void postChanges(final StorageChannel channel, final int i, + final IMEInventoryHandler h, final BaseActionSource actionSrc) { + this.data.add(new CellChangeTrackerRecord(channel, i, h, actionSrc)); + } + + public void applyChanges() { + for (final CellChangeTrackerRecord rec : this.data) { + rec.applyChanges(); + } + } + } + + private void updateBytesInfo() { + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + this.fluidBytesTotal = 0; + this.fluidBytesUsed = 0; + this.essentiaBytesTotal = 0; + this.essentiaBytesUsed = 0; + try { + for (ICellProvider icp : this.activeCellProviders) { + if (icp instanceof TileDrive) { + System.out.println(); + // All Item Cell + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { + // exclude void cell + if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { + continue; + } + // exclude creative cell + if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { + if (handler.getCellInv() != null) { + itemBytesTotal += handler.getCellInv().getTotalBytes(); + itemBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + } + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { + // Fluid Cell + if (((MEInventoryHandler) meih) + .getInternal() instanceof FluidCellInventoryHandler handler) { + if (handler.getCellInv() != null) { + fluidBytesTotal += handler.getCellInv().getTotalBytes(); + fluidBytesUsed += handler.getCellInv().getUsedBytes(); + } + } + // Essentia Cell + if (((MEInventoryHandler) meih) + .getInternal() instanceof HandlerItemEssentiaCell handler) { + essentiaBytesTotal += handler.getTotalBytes(); + essentiaBytesUsed += handler.getUsedBytes(); + } + } + + } + } + } catch (Exception e) { + // XD Normally won't be here, just normally.. + } + } + + public long getItemBytesTotal() { + return itemBytesTotal; + } + + public long getItemBytesUsed() { + return itemBytesUsed; + } + + public long getFluidBytesTotal() { + return fluidBytesTotal; + } + + public long getFluidBytesUsed() { + return fluidBytesUsed; + } + + public long getEssentiaBytesTotal() { + return essentiaBytesTotal; + } + + public long getEssentiaBytesUsed() { + return essentiaBytesUsed; + } } From 9747e1fcb81ed3aa52e59ff5a2f2bb3383b6b229 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Fri, 3 Nov 2023 16:38:44 +0800 Subject: [PATCH 14/34] Delete useless rows --- .../appeng/client/gui/implementations/GuiNetworkStatus.java | 5 +++-- src/main/java/appeng/me/cache/GridStorageCache.java | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index d8084f20ad4..7c9d9ef9a27 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -45,11 +45,13 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource { private final int rows = 4; private GuiImgButton units; private int tooltip = -1; + private final DecimalFormat df; public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkTool te) { super(new ContainerNetworkStatus(inventoryPlayer, te)); final GuiScrollbar scrollbar = new GuiScrollbar(); - + + this.df = new DecimalFormat("#.##"); this.setScrollBar(scrollbar); this.repo = new ItemRepo(scrollbar, this); this.ySize = 183; @@ -116,7 +118,6 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { @Override public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; - final DecimalFormat df = new DecimalFormat("#.##"); this.fontRendererObj .drawString(GuiText.NetworkDetails.getLocal(), 8, 6, GuiColors.NetworkStatusDetails.getColor()); diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 75c86748850..2228b149ef5 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -367,7 +367,6 @@ private void updateBytesInfo() { try { for (ICellProvider icp : this.activeCellProviders) { if (icp instanceof TileDrive) { - System.out.println(); // All Item Cell for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { // exclude void cell From ff3b6eed55c67c831b38d3b64548707b19047f57 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Fri, 3 Nov 2023 16:39:23 +0800 Subject: [PATCH 15/34] Delete useless rows --- .../appeng/client/gui/implementations/GuiNetworkStatus.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index 7c9d9ef9a27..325c66e29bc 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -50,7 +50,7 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource { public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkTool te) { super(new ContainerNetworkStatus(inventoryPlayer, te)); final GuiScrollbar scrollbar = new GuiScrollbar(); - + this.df = new DecimalFormat("#.##"); this.setScrollBar(scrollbar); this.repo = new ItemRepo(scrollbar, this); From 864bbd494c9f9f46ef5f30648fe6663701da1be8 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Fri, 3 Nov 2023 19:21:36 +0800 Subject: [PATCH 16/34] Revert "Merge branch 'GTNewHorizons:master' into master" This reverts commit 01dde621b8a40ea870c3d61a8e9f2dc8c18475f9, reversing changes made to d09184e8a376448f637df87eb0d490eb0fb4607a. --- dependencies.gradle | 10 +- .../gui/implementations/GuiCraftingCPU.java | 48 +- .../implementations/GuiCraftingStatus.java | 80 +- .../appliedenergistics2/lang/uk_UA.lang | 737 ------------------ 4 files changed, 30 insertions(+), 845 deletions(-) delete mode 100644 src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang diff --git a/dependencies.gradle b/dependencies.gradle index 80ba0962c38..b84818a71a4 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,16 +1,16 @@ // Add your dependencies here dependencies { - implementation('com.github.GTNewHorizons:NotEnoughItems:2.4.6-GTNH:dev') + implementation('com.github.GTNewHorizons:NotEnoughItems:2.4.5-GTNH:dev') implementation('curse.maven:cofh-core-69162:2388751') compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.4.13-GTNH:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:AE2FluidCraft-Rework:1.1.42-gtnh:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.36:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.3.4:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.73:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.68:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:Jabba:1.3.0:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:inventory-tweaks:1.6.0:api') {transitive = false} - compileOnly('com.github.GTNewHorizons:OpenComputers:1.9.19-GTNH:api') {transitive = false} + compileOnly('com.github.GTNewHorizons:inventory-tweaks:1.5.16:api') {transitive = false} + compileOnly('com.github.GTNewHorizons:OpenComputers:1.9.17-GTNH:api') {transitive = false} compileOnly('com.github.GTNewHorizons:waila:1.6.2:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:Railcraft:9.15.0:api') {transitive = false} compileOnly('net.industrial-craft:industrialcraft-2:2.2.828-experimental:api') @@ -29,7 +29,7 @@ dependencies { functionalTestImplementation('org.junit.platform:junit-platform-engine') functionalTestImplementation('org.junit.platform:junit-platform-launcher') functionalTestImplementation('org.junit.platform:junit-platform-reporting') - functionalTestImplementation('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.73:dev') { + functionalTestImplementation('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.68:dev') { exclude module: "Applied-Energistics-2-Unofficial" } diff --git a/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java b/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java index cec78750f33..cc9677d27b2 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java +++ b/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java @@ -58,19 +58,16 @@ public class GuiCraftingCPU extends AEBaseGui implements ISortSource, IGuiTooltipHandler { - protected static final int GUI_HEIGHT = 184; - protected static final int GUI_WIDTH = 238; + private static final int GUI_HEIGHT = 184; + private static final int GUI_WIDTH = 238; - protected static final int TEXTURE_BELOW_TOP_ROW_Y = 41; - protected static final int TEXTURE_ABOVE_BOTTOM_ROW_Y = 51; - protected static final int DISPLAYED_ROWS = 6; + private static final int DISPLAYED_ROWS = 6; - protected static final int SECTION_LENGTH = 67; - protected static final int SECTION_HEIGHT = 23; + private static final int SECTION_LENGTH = 67; - protected static final int SCROLLBAR_TOP = 19; - protected static final int SCROLLBAR_LEFT = 218; - protected static final int SCROLLBAR_HEIGHT = 137; + private static final int SCROLLBAR_TOP = 19; + private static final int SCROLLBAR_LEFT = 218; + private static final int SCROLLBAR_HEIGHT = 137; private static final int CANCEL_LEFT_OFFSET = 163; private static final int CANCEL_TOP_OFFSET = 25; @@ -82,15 +79,12 @@ public class GuiCraftingCPU extends AEBaseGui implements ISortSource, IGuiToolti private static final int ITEMSTACK_LEFT_OFFSET = 9; private static final int ITEMSTACK_TOP_OFFSET = 22; - private static final int ITEMS_PER_ROW = 3; private final ContainerCraftingCPU craftingCpu; - protected IItemList storage = AEApi.instance().storage().createItemList(); - protected IItemList active = AEApi.instance().storage().createItemList(); - protected IItemList pending = AEApi.instance().storage().createItemList(); - - protected int rows = DISPLAYED_ROWS; + private IItemList storage = AEApi.instance().storage().createItemList(); + private IItemList active = AEApi.instance().storage().createItemList(); + private IItemList pending = AEApi.instance().storage().createItemList(); private class RemainingOperations implements ITooltip { @@ -158,7 +152,7 @@ public int getStringWidth() { } } - protected List visual = new ArrayList<>(); + private List visual = new ArrayList<>(); private GuiButton cancel; private int tooltip = -1; private final RemainingOperations remainingOperations = new RemainingOperations(); @@ -243,7 +237,7 @@ private void setScrollBar() { final int size = this.visual.size(); this.getScrollBar().setTop(SCROLLBAR_TOP).setLeft(SCROLLBAR_LEFT).setHeight(SCROLLBAR_HEIGHT); - this.getScrollBar().setRange(0, (size + 2) / ITEMS_PER_ROW - rows, 1); + this.getScrollBar().setRange(0, (size + 2) / 3 - DISPLAYED_ROWS, 1); } @Override @@ -255,15 +249,15 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { this.tooltip = -1; - final int offY = SECTION_HEIGHT; + final int offY = 23; int y = 0; int x = 0; - for (int z = 0; z <= ITEMS_PER_ROW * rows; z++) { - final int minX = gx + ITEMSTACK_LEFT_OFFSET + x * SECTION_LENGTH; - final int minY = gy + ITEMSTACK_TOP_OFFSET + y * offY; + for (int z = 0; z <= 4 * 5; z++) { + final int minX = gx + 9 + x * 67; + final int minY = gy + 22 + y * offY; - if (minX < mouseX && minX + SECTION_LENGTH > mouseX) { - if (minY < mouseY && minY + offY > mouseY) { + if (minX < mouseX && minX + 67 > mouseX) { + if (minY < mouseY && minY + offY - 2 > mouseY) { this.tooltip = z; break; } @@ -271,7 +265,7 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { x++; - if (x == ITEMS_PER_ROW) { + if (x > 2) { y++; x = 0; } @@ -316,8 +310,8 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int x = 0; int y = 0; - final int viewStart = this.getScrollBar().getCurrentScroll() * ITEMS_PER_ROW; - final int viewEnd = viewStart + ITEMS_PER_ROW * rows; + final int viewStart = this.getScrollBar().getCurrentScroll() * 3; + final int viewEnd = viewStart + 3 * 6; String dspToolTip = ""; final List lineList = new LinkedList<>(); diff --git a/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java b/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java index 85aae6b93ef..622c2077d3c 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java @@ -13,8 +13,6 @@ */ package appeng.client.gui.implementations; -import java.util.List; - import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; @@ -22,18 +20,13 @@ import org.lwjgl.input.Mouse; import appeng.api.AEApi; -import appeng.api.config.Settings; -import appeng.api.config.TerminalStyle; import appeng.api.definitions.IDefinitions; import appeng.api.definitions.IParts; import appeng.api.storage.ITerminalHost; -import appeng.api.storage.data.IAEItemStack; import appeng.client.gui.widgets.GuiCraftingCPUTable; -import appeng.client.gui.widgets.GuiImgButton; import appeng.client.gui.widgets.GuiTabButton; import appeng.client.gui.widgets.ICraftingCPUTableHolder; import appeng.container.implementations.ContainerCraftingStatus; -import appeng.core.AEConfig; import appeng.core.localization.GuiText; import appeng.core.sync.GuiBridge; import appeng.core.sync.network.NetworkHandler; @@ -53,16 +46,11 @@ public class GuiCraftingStatus extends GuiCraftingCPU implements ICraftingCPUTab private GuiTabButton originalGuiBtn; private GuiBridge originalGui; private ItemStack myIcon = null; - private boolean tallMode; - private GuiImgButton switchTallMode; public GuiCraftingStatus(final InventoryPlayer inventoryPlayer, final ITerminalHost te) { super(new ContainerCraftingStatus(inventoryPlayer, te)); this.status = (ContainerCraftingStatus) this.inventorySlots; - this.tallMode = AEConfig.instance.getConfigManager().getSetting(Settings.TERMINAL_STYLE) == TerminalStyle.TALL; - recalculateScreenSize(); - final Object target = this.status.getTarget(); final IDefinitions definitions = AEApi.instance().definitions(); final IParts parts = definitions.parts(); @@ -118,21 +106,16 @@ protected void actionPerformed(final GuiButton btn) { if (btn == this.selectCPU) { cpuTable.cycleCPU(backwards); - } else if (btn == this.originalGuiBtn) { + } + + if (btn == this.originalGuiBtn) { NetworkHandler.instance.sendToServer(new PacketSwitchGuis(this.originalGui)); - } else if (btn == this.switchTallMode) { - tallMode = !tallMode; - switchTallMode.set(tallMode ? TerminalStyle.TALL : TerminalStyle.SMALL); - recalculateScreenSize(); - this.setWorldAndResolution(mc, width, height); } } @Override public void initGui() { - recalculateScreenSize(); super.initGui(); - this.setScrollBar(); this.selectCPU = new GuiButton( 0, @@ -153,12 +136,6 @@ public void initGui() { itemRender)); this.originalGuiBtn.setHideEdge(13); } - this.switchTallMode = new GuiImgButton( - this.guiLeft - 18, - this.guiTop + 166, - Settings.TERMINAL_STYLE, - tallMode ? TerminalStyle.TALL : TerminalStyle.SMALL); - this.buttonList.add(switchTallMode); } @Override @@ -176,31 +153,7 @@ public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { @Override public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { - this.bindTexture("guis/craftingcpu.png"); - if (tallMode) { - this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, TEXTURE_BELOW_TOP_ROW_Y); - int y = TEXTURE_BELOW_TOP_ROW_Y; - // first and last row are pre-baked - for (int row = 1; row < rows - 1; row++) { - this.drawTexturedModalRect( - offsetX, - offsetY + y, - 0, - TEXTURE_BELOW_TOP_ROW_Y, - this.xSize, - SECTION_HEIGHT); - y += SECTION_HEIGHT; - } - this.drawTexturedModalRect( - offsetX, - offsetY + y, - 0, - GUI_HEIGHT - TEXTURE_ABOVE_BOTTOM_ROW_Y, - this.xSize, - TEXTURE_ABOVE_BOTTOM_ROW_Y); - } else { - this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); - } + super.drawBG(offsetX, offsetY, mouseX, mouseY); this.cpuTable.drawBG(offsetX, offsetY); } @@ -253,29 +206,4 @@ private void updateCPUButtonText() { protected String getGuiDisplayName(final String in) { return in; // the cup name is on the button } - - protected void recalculateScreenSize() { - final int maxAvailableHeight = height - 64; - this.xSize = GUI_WIDTH; - if (tallMode) { - this.rows = (maxAvailableHeight - (SCROLLBAR_TOP + SECTION_HEIGHT)) / SECTION_HEIGHT; - this.ySize = SCROLLBAR_TOP + SECTION_HEIGHT + 5 + this.rows * SECTION_HEIGHT; - } else { - this.rows = DISPLAYED_ROWS; - this.ySize = GUI_HEIGHT; - } - } - - private void setScrollBar() { - final int size = this.visual.size(); - - this.getScrollBar().setTop(SCROLLBAR_TOP).setLeft(SCROLLBAR_LEFT).setHeight(ySize - 47); - this.getScrollBar().setRange(0, (size + 2) / 3 - this.rows, 1); - } - - @Override - public void postUpdate(List list, byte ref) { - super.postUpdate(list, ref); - setScrollBar(); - } } diff --git a/src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang b/src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang deleted file mode 100644 index 2edbc7bb7cc..00000000000 --- a/src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang +++ /dev/null @@ -1,737 +0,0 @@ -# Blocks -tile.appliedenergistics2.BlockCableBus.name=AE2 кабель та/або шина -tile.appliedenergistics2.BlockCellWorkbench.name=Верстак для роботи з дисками -tile.appliedenergistics2.BlockCharger.name=Зарядний пристрій -tile.appliedenergistics2.BlockChest.name=ME-Скриня -tile.appliedenergistics2.BlockCondenser.name=Конденсатор матерії -tile.appliedenergistics2.BlockController.name=МЕ-Контролер -tile.appliedenergistics2.BlockCrank.name=Дерев’яна ручка -tile.appliedenergistics2.BlockCreativeEnergyCell.name=Творчий накопичувач енергії -tile.appliedenergistics2.BlockDenseEnergyCell.name=Щільний накопичувач енергії -tile.appliedenergistics2.BlockEnergyCell.name=Накопичувач енергії -tile.appliedenergistics2.BlockDrive.name=ME-Привід -tile.appliedenergistics2.BlockEnergyAcceptor.name=Приймач енергії -tile.appliedenergistics2.BlockGrinder.name=Кварцовий точильний камінь -tile.appliedenergistics2.BlockMatrixFrame.name=Каркас матриці -tile.appliedenergistics2.BlockIOPort.name=ME-Порт вводу/виводу -tile.appliedenergistics2.BlockInscriber.name=Штампувальний прес -tile.appliedenergistics2.BlockInterface.name=Постачальник шаблонів -tile.appliedenergistics2.BlockQuantumLinkChamber.name=МЕ-Камера квантового зв'язку -tile.appliedenergistics2.BlockQuantumRing.name=МЕ-Квантове кільце -tile.appliedenergistics2.BlockFluix.name=Блок мінливого кристалу -tile.appliedenergistics2.BlockQuartz.name=Блок істинного кварцу -tile.appliedenergistics2.BlockQuartzChiseled.name=Точений блок істинного кварцу -tile.appliedenergistics2.BlockQuartzGlass.name=Кварцове скло -tile.appliedenergistics2.BlockQuartzLamp.name=Яскраве кварцове скло -tile.appliedenergistics2.BlockQuartzPillar.name=Колона з істинного кварцу -tile.appliedenergistics2.BlockQuartzTorch.name=Заряджений кварцовий світильник -tile.appliedenergistics2.BlockLightDetector.name=Детектор світла -tile.appliedenergistics2.BlockSpatialIOPort.name=Просторовий порт IO -tile.appliedenergistics2.BlockSpatialPylon.name=Просторовий пілон -tile.appliedenergistics2.BlockTinyTNT.name=Крихітний динаміт -tile.appliedenergistics2.BlockVibrationChamber.name=Вібраційна камера -tile.appliedenergistics2.BlockWireless.name=ME-Бездротова точка доступу -tile.appliedenergistics2.OreQuartz.name=Руда істинного кварцу -tile.appliedenergistics2.OreQuartzCharged.name=Руда зарядженного істиного кварцу -tile.appliedenergistics2.BlockSecurity.name=ME-Термінал безпеки -tile.appliedenergistics2.BlockQuartzGrowthAccelerator.name=Прискорювач росту кристалів -tile.appliedenergistics2.BlockSkyStone.name=Небесний камінь -tile.appliedenergistics2.BlockSkyStone.Block.name=Небесний камінь -tile.appliedenergistics2.BlockSkyStone.Brick.name=Цегла з небесного каменю -tile.appliedenergistics2.BlockSkyStone.SmallBrick.name=Дрібна цегла з небесного каменю -tile.appliedenergistics2.BlockSkyChest.name=Скриня з небесного каменю -tile.appliedenergistics2.BlockSkyChest.Block.name=Скриня з небесного каменю -tile.appliedenergistics2.BlockSkyCompass.name=Метеоритний компас -tile.appliedenergistics2.BlockCraftingMonitor.name=Монітор створення -tile.appliedenergistics2.BlockCraftingStorage.name=1К Сховище для створення -tile.appliedenergistics2.BlockCraftingStorage4k.name=4К Сховище для створення -tile.appliedenergistics2.BlockCraftingStorage16k.name=16К Сховище для створення -tile.appliedenergistics2.BlockCraftingStorage64k.name=64К Сховище для створення -tile.appliedenergistics2.BlockCraftingStorage256k.name=256К Сховище для створення -tile.appliedenergistics2.BlockCraftingStorage1024k.name=1024К Сховище для створення -tile.appliedenergistics2.BlockCraftingStorage4096k.name=4096К Сховище для створення -tile.appliedenergistics2.BlockCraftingStorage16384k.name=16384К Сховище для створення -tile.appliedenergistics2.BlockCraftingAccelerator.name=Блок сумісної обробки -tile.appliedenergistics2.BlockCraftingAccelerator4x.name=4-ох ядерний блок сумісної обробки -tile.appliedenergistics2.BlockCraftingAccelerator16x.name=16-ти ядерний блок сумісної обробки -tile.appliedenergistics2.BlockCraftingAccelerator64x.name=64-ох ядерний блок сумісної обробки -tile.appliedenergistics2.BlockCraftingAccelerator256x.name=256-и ядерний блок сумісної обробки -tile.appliedenergistics2.BlockCraftingAccelerator1024x.name=1024-ох ядерний блок сумісної обробки -tile.appliedenergistics2.BlockCraftingAccelerator4096x.name=4096-и ядерний блок сумісної обробки -tile.appliedenergistics2.BlockCraftingUnit.name=Блок створення -tile.appliedenergistics2.BlockMolecularAssembler.name=Молекулярний збирач - -# Stairs -tile.appliedenergistics2.ChiseledQuartzStairBlock.name=Виточені сходи з істинного кварцу -tile.appliedenergistics2.FluixStairBlock.name=Сходи з мінливого кристалу -tile.appliedenergistics2.QuartzPillarStairBlock.name=Сходи з колони істинного кварцу -tile.appliedenergistics2.QuartzStairBlock.name=Сходи з істинного кварцу -tile.appliedenergistics2.SkyStoneBlockStairBlock.name=Сходи з небесного каменю -tile.appliedenergistics2.SkyStoneBrickStairBlock.name=Цегляні сходи з небесного каменю -tile.appliedenergistics2.SkyStoneSmallBrickStairBlock.name=Сходи з дрібної цегли з небесного каменю -tile.appliedenergistics2.SkyStoneStairBlock.name=Сходи з небесного каменю - -# Slabs -tile.appliedenergistics2.ChiseledQuartzSlabBlock.name=Плита з точеного істинного кварцу -tile.appliedenergistics2.FluixSlabBlock.name=Плита з мінливого кристалу -tile.appliedenergistics2.QuartzPillarSlabBlock.name=Плита з колони істинного кварцу -tile.appliedenergistics2.QuartzSlabBlock.name=Плита з істинного кварцу -tile.appliedenergistics2.SkyStoneBlockSlabBlock.name=Плита з небесного каменю -tile.appliedenergistics2.SkyStoneBrickSlabBlock.name=Цегляна плита з небесного каменя -tile.appliedenergistics2.SkyStoneSmallBrickSlabBlock.name=Плита з дрібної цегли небесного каменю -tile.appliedenergistics2.SkyStoneSlabBlock.name=Плита з небесного каменю - -# Chat Messages -chat.appliedenergistics2.ChestCannotReadStorageCell=ME скриня не може зчитати диск зберігання. -chat.appliedenergistics2.SettingCleared=Карта пам'яті очищена. -chat.appliedenergistics2.OutOfRange=Бездротова мережа поза зоною досяжності. -chat.appliedenergistics2.InvalidMachine=Неможливо відновити конфігурацію для цього пристрою. -chat.appliedenergistics2.LoadedSettings=Завантажено конфігурацію пристрою з карти пам'яті. -chat.appliedenergistics2.DeviceNotPowered=Недостатньо енергії для пристрою. -chat.appliedenergistics2.DeviceNotWirelessTerminal=Пристрій не є бездротовим терміналом. -chat.appliedenergistics2.DeviceNotLinked=Пристрій не прив'язано. -chat.appliedenergistics2.StationCanNotBeLocated=Станцію не вдається знайти. -chat.appliedenergistics2.MachineNotPowered=У механізму відсутнє живлення. -chat.appliedenergistics2.CommunicationError=Помилка з'єднання з мережею. -chat.appliedenergistics2.SavedSettings=Успішно збережено налаштування. -chat.appliedenergistics2.AmmoDepleted=Боєприпаси вичерпані. -chat.appliedenergistics2.isNowLocked=Монітор заблоковано. -chat.appliedenergistics2.isNowUnlocked=Монітор розблоковано. -chat.appliedenergistics2.TunnelNotConnected=Тунель не з'єднаний. -chat.appliedenergistics2.TunnelInputIsAt=Вхід до тунелю знаходиться за (%d, %d, %d) -chat.appliedenergistics2.TunnelHasNoOutputs=Тунель не має виходів. -chat.appliedenergistics2.TunnelOutputsAreAt=Виходи з тунелю знаходяться за: -chat.appliedenergistics2.InterfaceInOtherDim=Інтерфейс розташований у вимірі: %d і не може бути підсвідчений -chat.appliedenergistics2.InterfaceHighlighted=Інтерфейс тепер підсвідчуються за %d, %d, %d -chat.appliedenergistics2.CraftingItemsWentMissing=Не вдалося почати крафт, інгредієнт був пропущений: %d * %s -chat.appliedenergistics2.FBOUnsupported=OpenGL FBOs не підтримуються, не можна експортувати зображення -# Creative Tabs -itemGroup.appliedenergistics2=Applied Energistics 2 -itemGroup.appliedenergistics2.facades=Applied Energistics 2 - Фасади - -# GUI -gui.appliedenergistics2.CraftingTerminal=Термінал створення -gui.appliedenergistics2.METunnel=МЕ -gui.appliedenergistics2.ItemTunnel=Предмет -gui.appliedenergistics2.FluidTunnel=Рідина -gui.appliedenergistics2.RedstoneTunnel=Редстоун -gui.appliedenergistics2.EUTunnel=EU -gui.appliedenergistics2.RFTunnel=RF -gui.appliedenergistics2.LightTunnel=Світло -gui.appliedenergistics2.OCTunnel=OpenComputers -gui.appliedenergistics2.PressureTunnel=Тиск -gui.appliedenergistics2.GTTunnel=GT EU -gui.appliedenergistics2.IFACETunnel=ME Інтерфейс - -gui.appliedenergistics2.security.extract.name=Забирати -gui.appliedenergistics2.security.inject.name=Класти -gui.appliedenergistics2.security.craft.name=Створювати -gui.appliedenergistics2.security.build.name=Побудувати -gui.appliedenergistics2.security.security.name=Безпека - -gui.appliedenergistics2.security.extract.tip=Користувач може забирати предмети зі сховища. -gui.appliedenergistics2.security.inject.tip=Користувачеві дозволено класти нові предмети у сховище. -gui.appliedenergistics2.security.craft.tip=Користувач може розпочинати нові задачі на створення. -gui.appliedenergistics2.security.build.tip=Користувач може змінювати фізичну структуру мережі та вносити зміни до конфігурації. -gui.appliedenergistics2.security.security.tip=Користувач може отримати доступ до терміналу безпеки мережі та модифікувати його. - -gui.appliedenergistics2.Efficiency=Ефективність -gui.appliedenergistics2.RequiredPower=Необхідна енергія -gui.appliedenergistics2.StoredPower=Накопичена енергія -gui.appliedenergistics2.MaxPower=Максимальна енергія -gui.appliedenergistics2.QuartzCuttingKnife=Кварцовий ріжучий ніж -gui.appliedenergistics2.Inscriber=Штампувальний прес -gui.appliedenergistics2.Wireless=Бездротова точка доступу -gui.appliedenergistics2.WirelessTerminal=Бездротовий термінал -gui.appliedenergistics2.NoPermissions=Дозволи не вибрано -gui.appliedenergistics2.SecurityCardEditor=Редактор біометричних карток -gui.appliedenergistics2.Encoded=Закодований -gui.appliedenergistics2.Priority=Пріоритет -gui.appliedenergistics2.StorageBus=МЕ-шина зберігання -gui.appliedenergistics2.EnergyDrain=Пасивне споживання -gui.appliedenergistics2.Installed=Встановлено -gui.appliedenergistics2.NetworkTool=Діагностика мережі -gui.appliedenergistics2.PowerUsageRate=Використання енергії -gui.appliedenergistics2.PowerInputRate=Генерація енергії -gui.appliedenergistics2.PortableCell=Портативний диск -gui.appliedenergistics2.Security=Термінал безпеки -gui.appliedenergistics2.CellWorkbench=Верстак для роботи з дисками -gui.appliedenergistics2.QuantumLinkChamber=Камера квантового зв'язку -gui.appliedenergistics2.IOPort=ME-Порт вводу/виводу -gui.appliedenergistics2.Chest=ME-Скриня -gui.appliedenergistics2.Condenser=Конденсатор матерії -gui.appliedenergistics2.Config=Конфігурація -gui.appliedenergistics2.Drive=ME-Привід -gui.appliedenergistics2.ExportBus=ME-Шина експорту -gui.appliedenergistics2.GrindStone=Точильний камінь -gui.appliedenergistics2.ImportBus=МЕ-Шина імпорту -gui.appliedenergistics2.Interface=ME-Інтерфейс -gui.appliedenergistics2.LevelEmitter=ME Випромінювач рівня енергії -gui.appliedenergistics2.Of=з -gui.appliedenergistics2.Patterns=Шаблони -gui.appliedenergistics2.SpatialIOPort=Просторовий порт IO -gui.appliedenergistics2.StoredEnergy=Накопичена енергія -gui.appliedenergistics2.StoredItems=Накопичені предмети -gui.appliedenergistics2.StoredStacks=Накопічені стеки -gui.appliedenergistics2.Terminal=Термінал -gui.appliedenergistics2.InterfaceTerminal=Термінал Інтерфейсів -gui.appliedenergistics2.InterfaceTerminalHint=Показати або Приховати в терміналі інтерфейсів. -gui.appliedenergistics2.FormationPlane=Площина формування -gui.appliedenergistics2.VibrationChamber=Вібраційна камера -gui.appliedenergistics2.NetworkDetails=Деталі мережі -gui.appliedenergistics2.StorageCells=МЕ-Диск зберігання -gui.appliedenergistics2.IOBuses=МЕ-Шина імпорту/експорту -gui.appliedenergistics2.Stores=Зберігає -gui.appliedenergistics2.BytesUsed=Байтів використано -gui.appliedenergistics2.Types=Типів -gui.appliedenergistics2.Blank=Порожній. -gui.appliedenergistics2.Unlinked=Без зв'язку -gui.appliedenergistics2.Linked=Прив'язаний -gui.appliedenergistics2.StoredSize=Збережений розмір -gui.appliedenergistics2.SkyChest=Скриня з небесного каменю -gui.appliedenergistics2.PatternTerminal=Термінал шаблонів -gui.appliedenergistics2.PatternTerminalEx=Термінал обробки шаблонів -gui.appliedenergistics2.CraftingPattern=Створення шаблону -gui.appliedenergistics2.MolecularAssembler=Молекулярний збирач -gui.appliedenergistics2.ProcessingPattern=Шаблон обробки -gui.appliedenergistics2.Crafts=Створення -gui.appliedenergistics2.And=і -gui.appliedenergistics2.Creates=Створює -gui.appliedenergistics2.With=з -gui.appliedenergistics2.Substitute=Використовува заміщюванні: -gui.appliedenergistics2.BeSubstitute=Може бути заміщенно: -gui.appliedenergistics2.Yes=Так -gui.appliedenergistics2.No=Ні -gui.appliedenergistics2.InWorldCrafting=AE2 у світовому створенні -gui.appliedenergistics2.inWorldFluix=Киньте 1 заряджений істинний кварц + 1 Пекельний кварц + 1 редстоун в воду поруч один з одним і почекайте трохи, щоб отримати 2 мінливих кристали. -gui.appliedenergistics2.inWorldPurificationCertus=Киньте насіння істинного кварцу, зроблене з порошоку істинного кварцу та піску, у воду; Щоб пришвидшити процес, додайте прискорювач росту кристалів. -gui.appliedenergistics2.inWorldPurificationNether=Киньте насіння Пекельного кварцу, зроблене з порошоку пекельного кварцу та піску, у воду; Щоб пришвидшити процес, додайте прискорювач росту кристалів. -gui.appliedenergistics2.inWorldPurificationFluix=Киньте насіння мінливого кристалу, зроблене з порошоку мінливого кристалу та пісоку, у воду; Щоб пришвидшити процес, додайте прискорювач росту кристалів. -gui.appliedenergistics2.inWorldSingularity=Для створення киньте 1 сингулярність і 1 Порошок Енду та спричиніть вибух у межах досяжності цих предметів. -gui.appliedenergistics2.ChargedQuartz=Заряджений істинний кварц створюється шляхом повіщення незарядженого кристалу істинниго кварцу у зарядний пристрій та подачі живлення. -gui.appliedenergistics2.ChargedQuartzFind=Заряджений істинний кварц зустрічається у світі досить рідко, зовні він схожий на звичайний істинний кварц, за винятком того, що виблискує. -gui.appliedenergistics2.NoSecondOutput=Немає вторинної продукції -gui.appliedenergistics2.OfSecondOutput=%1$d%% шанс на вторинну продукцію. -gui.appliedenergistics2.MultipleOutputs=%1$d%% вторинної, %2$d%% третинної продукції. -gui.appliedenergistics2.SelectAmount=Виберіть кількість -gui.appliedenergistics2.CopyMode=Режим копіювання -gui.appliedenergistics2.CopyModeDesc=Визначає, чи буде очищено вміст панелі конфігурації при вийманні диска. -gui.appliedenergistics2.Next=Далі -gui.appliedenergistics2.Lumen=Сяючий -gui.appliedenergistics2.Empty=Порожній -gui.appliedenergistics2.Stored=Зберігається -gui.appliedenergistics2.Cancel=Скасувати -gui.appliedenergistics2.ETAFormat=HH:mm:ss -gui.appliedenergistics2.SwitchCraftingSimulationDisplayMode=Перемикання режиму відображення (Список/Дерево) -gui.appliedenergistics2.Crafting=Створення -gui.appliedenergistics2.Scheduled=Заплановано -gui.appliedenergistics2.CraftingStatus=Статус створення -gui.appliedenergistics2.RemainingOperations=Простоюючі процесори -gui.appliedenergistics2.FromStorage=Доступно -gui.appliedenergistics2.ToCraft=Потрібно створити -gui.appliedenergistics2.CraftingPlan=План створення -gui.appliedenergistics2.Automatic=Автоматично -gui.appliedenergistics2.Start=Почати -gui.appliedenergistics2.Missing=Пропущено -gui.appliedenergistics2.NoCraftingTreeReceived=Не отримано жодного дерева створення -gui.appliedenergistics2.CraftingStepLimitExceeded=Перевищено ліміт етапів створення -gui.appliedenergistics2.RequestedItem=Вимагається предмет -gui.appliedenergistics2.SimulationIncomplete=Моделювання незавершене -gui.appliedenergistics2.Bytes=Сховище -gui.appliedenergistics2.Set=Встановити -gui.appliedenergistics2.Simulation=Моделювання -gui.appliedenergistics2.CoProcessors=Співпроцесори -gui.appliedenergistics2.CraftingCPU=Створення процесора -gui.appliedenergistics2.NoCraftingCPUs=Процесори для створення не доступні -gui.appliedenergistics2.CalculatingWait=Обчислення, будь ласка зачекайте... -gui.appliedenergistics2.Clean=Очистити -gui.appliedenergistics2.InvalidPattern=Неправильний шаблон -gui.appliedenergistics2.UnknownItem=Невідомий предмет -gui.appliedenergistics2.Range=Діапазон -gui.appliedenergistics2.TransparentFacades=Прозорі фасади -gui.appliedenergistics2.TransparentFacadesHint=Керує видимістю фасадів, коли мережевий інструмент знаходиться на панелі інструментів. -gui.appliedenergistics2.CPUs=Процессор -gui.appliedenergistics2.NoCraftingJobs=Немає активного завдання на створення -gui.appliedenergistics2.FacadeCrafting=Виготовлення фасадів -gui.appliedenergistics2.inWorldCraftingPresses=Шаблони для створення знаходяться в центрі метеоритів, які можна знайти по всьому світу, їх можна знайти за допомогою метеоритного компасу. -gui.appliedenergistics2.Included=Включено -gui.appliedenergistics2.Excluded=Виключено -gui.appliedenergistics2.Partitioned=Розділений -gui.appliedenergistics2.PartitionedOre=Фільтр словника руд -gui.appliedenergistics2.Precise=Точно -gui.appliedenergistics2.Fuzzy=Нечіткий -gui.appliedenergistics2.Filter=Фільтр -gui.appliedenergistics2.SmallFontCraft=Створення -gui.appliedenergistics2.LargeFontCraft=+ -gui.appliedenergistics2.Renamer=Користувацьке ім'я: (Введіть, щоб встановити) -gui.appliedenergistics2.OreFilterLabel=Фільтр словника руд -gui.appliedenergistics2.HoldShiftForTooltip=Утримуйте клавішу Shift для розширеної підказки -gui.appliedenergistics2.HoldShiftClick_HIGHLIGHT_INTERFACE=Утримуйте клавішу Shift, щоб підсвітити інтерфейс -gui.appliedenergistics2.Nothing=Нічого -gui.appliedenergistics2.VoidCellTooltip=Видаляє §4все§7, що зберігається на ньому -gui.appliedenergistics2.Deprecated=Застаріле, буде видалене найближчим часом! - -# GUI Colors - ARGB -gui.color.appliedenergistics2.SearchboxFocused=6E000000 -gui.color.appliedenergistics2.SearchboxUnfocused=00000000 -gui.color.appliedenergistics2.SearchboxFocused=6E000000 -gui.color.appliedenergistics2.SearchboxUnfocused=00000000 -gui.color.appliedenergistics2.ItemSlotOverlayUnpowered=66111111 -gui.color.appliedenergistics2.ItemSlotOverlayInvalid=66ff6666 -gui.color.appliedenergistics2.CraftConfirmMissingItem=1AFF0000 -gui.color.appliedenergistics2.CraftingCPUActive=5A45A021 -gui.color.appliedenergistics2.CraftingCPUScheduled=FF787878 -gui.color.appliedenergistics2.InterfaceTerminalMatch=2A00FF00 - -# GUI Tooltips -gui.tooltips.appliedenergistics2.Stash=Зберегти предмети -gui.tooltips.appliedenergistics2.StashDesc=Повернути предмети на сітці створення до мережевого сховища. -gui.tooltips.appliedenergistics2.Substitutions=Заміни по рудному словнику -gui.tooltips.appliedenergistics2.SubstitutionsDescEnabled=Дозволяє замінювати вхідні компоненти. -gui.tooltips.appliedenergistics2.SubstitutionsDescDisabled=Запобігає заміні вхідних компонентів. -gui.tooltips.appliedenergistics2.BeSubstitutions=Використовувати як заміну -gui.tooltips.appliedenergistics2.BeSubstitutionsDescEnabled=Дозволяє створення заміни вхідних компонентів. -gui.tooltips.appliedenergistics2.BeSubstitutionsDescDisabled=Забороняє створення заміни вхідних компонентів. Якщо всі доступні для інгредієнта шаблони вимкнено для заміни, симулятор створення буде поводитися з ними так, як якщо б вони були ввімкнені для заміни. - -gui.tooltips.appliedenergistics2.PatternSlotConfigTitle=Перемкнути режим створення шаблону -gui.tooltips.appliedenergistics2.PatternSlotConfigInfo=Перемкнути режим створення шаблону між (16 -> 4) та (4 -> 16) -gui.tooltips.appliedenergistics2.Encode=Закодувати шаблон -gui.tooltips.appliedenergistics2.EncodeDescription=Запишіть введений шаблон до поточного закодованого шаблону або до доступного порожнього шаблону. Утримуйте клавішу Shift, щоб перенести шаблон безпосередньо в інвентар. Утримуйте Shift+Control, щоб закодувати весь стек. - -gui.tooltips.appliedenergistics2.FuzzyMode=Нечітке порівняння -gui.tooltips.appliedenergistics2.FZPercent_25=Розділити шкоду на 25% -gui.tooltips.appliedenergistics2.FZPercent_50=Розділити шкоду на 50% -gui.tooltips.appliedenergistics2.FZPercent_75=Розділити шкоду на 75% -gui.tooltips.appliedenergistics2.FZPercent_99=Розділити шкоду на 99% - -gui.tooltips.appliedenergistics2.SortOrder=Порядок сортування -gui.tooltips.appliedenergistics2.SortBy=Сортувати за -gui.tooltips.appliedenergistics2.FZIgnoreAll=Будь-який збіг -gui.tooltips.appliedenergistics2.TransferDirection=Напрямок передачі -gui.tooltips.appliedenergistics2.TransferToNetwork=Передати дані до мережі -gui.tooltips.appliedenergistics2.TransferToStorageCell=Передати дані до диску зберігання -gui.tooltips.appliedenergistics2.ToggleSortDirection=Переключити напрямок передачі - -gui.tooltips.appliedenergistics2.StoredItems=Збережені предмети -gui.tooltips.appliedenergistics2.StoredCraftable=Зберігається / Створюється -gui.tooltips.appliedenergistics2.View=Вигляд -gui.tooltips.appliedenergistics2.RedstoneMode=Редстоун режим -gui.tooltips.appliedenergistics2.OperationMode=Режим роботи -gui.tooltips.appliedenergistics2.NumberOfItems=Кількість предметів -gui.tooltips.appliedenergistics2.ItemName=Назва предмета -gui.tooltips.appliedenergistics2.PowerUnits=Одиниці енергії -gui.tooltips.appliedenergistics2.IOMode=Режим входу/виходу -gui.tooltips.appliedenergistics2.CondenserOutput=ME-Конденсатор - Вихід -gui.tooltips.appliedenergistics2.PartitionStorage=Розділ сховища -gui.tooltips.appliedenergistics2.Clear=Очистити -gui.tooltips.appliedenergistics2.TrashController=Видалення за допомогою Shift / Space. - -gui.tooltips.appliedenergistics2.InterfaceBlockingMode=Режим блокування -gui.tooltips.appliedenergistics2.InterfaceCraftingMode=Режим створення -gui.tooltips.appliedenergistics2.Trash=Знищити предмети -gui.tooltips.appliedenergistics2.MatterBalls=Конденсувати в кулі матерії\n%s за предмет -gui.tooltips.appliedenergistics2.Singularity=Конденсувати в сингулярність\n%s за предмет -gui.tooltips.appliedenergistics2.Read=Тільки забирати -gui.tooltips.appliedenergistics2.Write=Тільки вставляти -gui.tooltips.appliedenergistics2.ReadWrite=Двонаправлений - -gui.tooltips.appliedenergistics2.AlwaysActive=Завжди активний -gui.tooltips.appliedenergistics2.ActiveWithoutSignal=Активний без сигналу -gui.tooltips.appliedenergistics2.ActiveWithSignal=Активний з сигналом -gui.tooltips.appliedenergistics2.ActiveOnPulse=Активувати один раз за імпульс -gui.tooltips.appliedenergistics2.EmitLevelsBelow=Випромінювати сигнал, коли рівень нижче ліміту. -gui.tooltips.appliedenergistics2.EmitLevelAbove=Випромінювати сигнал, коли рівень вищий або дорівнює ліміту. - -gui.tooltips.appliedenergistics2.SearchMode_Auto=Авто пошук -gui.tooltips.appliedenergistics2.SearchMode_Standard=Стандартний пошук -gui.tooltips.appliedenergistics2.SearchMode_NEIAuto=Синхронізований авто пошук NEI -gui.tooltips.appliedenergistics2.SearchMode_NEIStandard=Синхронізований стандартний пошук NEI -gui.tooltips.appliedenergistics2.SearchMode=Режим поля пошуку - -gui.tooltips.appliedenergistics2.PartitionStorageHint=Конфігурує розділ на основі поточних збережених об'єктів. -gui.tooltips.appliedenergistics2.ClearSettings=Очистити конфігурацію/налаштування -gui.tooltips.appliedenergistics2.Craftable=Створювальні -gui.tooltips.appliedenergistics2.MoveWhenEmpty=Перемістити до виводу, коли порожній. -gui.tooltips.appliedenergistics2.MoveWhenWorkIsDone=Перемістити до виводу, коли робота виконана. -gui.tooltips.appliedenergistics2.MoveWhenFull=Перемістити до виводу, коли заповниться. -gui.tooltips.appliedenergistics2.Disabled=Вимкнений -gui.tooltips.appliedenergistics2.Enable=Увімкнений -gui.tooltips.appliedenergistics2.Blocking=Не штовхати предмети для створення, якщо в інвентарі є предмети. -gui.tooltips.appliedenergistics2.NonBlocking=Ігнорувати вміст цільового інвентарю. -gui.tooltips.appliedenergistics2.Craft=Поведінка створення -gui.tooltips.appliedenergistics2.CraftOnly=Не використовувати збережені предмети, створювати лише під час експорту. -gui.tooltips.appliedenergistics2.CraftEither=Використовувати збережені предмети або створити під час експорту. -gui.tooltips.appliedenergistics2.LevelType=Тип рівня -gui.tooltips.appliedenergistics2.LevelType_Energy=Енергія -gui.tooltips.appliedenergistics2.LevelType_Item=Предмет -gui.tooltips.appliedenergistics2.InventoryTweaks=Inventory Tweaks -gui.tooltips.appliedenergistics2.Mod=Мод -gui.tooltips.appliedenergistics2.TerminalStyle=Стиль терміналу -gui.tooltips.appliedenergistics2.TerminalStyle_Full=Повноекранний термінал -gui.tooltips.appliedenergistics2.TerminalStyle_Tall=Високий центрований термінал -gui.tooltips.appliedenergistics2.TerminalStyle_Small=Малий центрований термінал -gui.tooltips.appliedenergistics2.SaveAsImage=Зберегти як зображення - -gui.tooltips.appliedenergistics2.DoesntDespawn=Цей предмет не зникне. -gui.tooltips.appliedenergistics2.EmitterMode=Режим випромінювача створення -gui.tooltips.appliedenergistics2.CraftViaRedstone=Випромінювати сигнал редстоуну для виготовлення предмета. -gui.tooltips.appliedenergistics2.EmitWhenCrafting=Випромінювати сигнал редстоуну, коли предмет створюється. - -gui.tooltips.appliedenergistics2.ReportInaccessibleItems=Повідомити про недоступні предмети -gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=Так: предмети, які не можна витягнути будуть видимими. -gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=Ні: Видимі лише предмети, що можна витягнути. - -gui.tooltips.appliedenergistics2.TypeFilter=Тип фільтру -gui.tooltips.appliedenergistics2.TypeFilterShowAll=Показати все -gui.tooltips.appliedenergistics2.TypeFilterShowItemsOnly=Показати тільки предмети -gui.tooltips.appliedenergistics2.TypeFilterShowFluidsOnly=Показувати тільки краплі рідин - -gui.tooltips.appliedenergistics2.BlockPlacement=Розміщення блоків -gui.tooltips.appliedenergistics2.BlockPlacementYes=Блоки будуть розміщатись як блоки. -gui.tooltips.appliedenergistics2.BlockPlacementNo=Блоки будуть випадати як предмети. - -gui.tooltips.appliedenergistics2.SchedulingMode=Режим планування -gui.tooltips.appliedenergistics2.SchedulingModeDefault=Експортуйте перший предмет, доки мережа не спорожніє, а потім спробуйте експортувати наступні. -gui.tooltips.appliedenergistics2.SchedulingModeRoundRobin=Експорт з використанням циклічного режиму. -gui.tooltips.appliedenergistics2.SchedulingModeRandom=Експортувати предмети у випадковому режимі. - -gui.tooltips.appliedenergistics2.ItemsStored=Збережені предмети: %s -gui.tooltips.appliedenergistics2.ItemCount=Кількість предметів: %s -gui.tooltips.appliedenergistics2.ItemsRequestable=Необхідні предмети: %s -gui.tooltips.appliedenergistics2.P2PFrequency=Частота: %s -gui.tooltips.appliedenergistics2.OreFilterHint=Відфільтрувати предмети за назвами зі словника руд -gui.tooltips.appliedenergistics2.OreFilter=Фільтр словника руд -gui.tooltips.appliedenergistics2.SearchStringTooltip=Клацніть ПКМ, щоб очистити рядок пошуку -gui.tooltips.appliedenergistics2.SaveSearchString=Зберігати рядок пошуку -gui.tooltips.appliedenergistics2.SaveSearchStringYes=Так -gui.tooltips.appliedenergistics2.SaveSearchStringNo=Ні -gui.tooltips.appliedenergistics2.DoublePattern=Подвоїти шаблон -gui.tooltips.appliedenergistics2.DoublePatternHint=Подвоїти розмір стеку входів та виходів шаблону, якщо це можливо. x8, коли shift утримується. -gui.tooltips.appliedenergistics2.CraftingStatus=Статус створення -gui.tooltips.appliedenergistics2.CraftingStatusDesc=Відкриває вікно стану створення -gui.tooltips.appliedenergistics2.ToggleMolecularAssemblers=Перемкнути відображення тільки інтерфейсів створення -gui.tooltips.appliedenergistics2.ToggleMolecularAssemblersDescOff=Показати всі інтерфейси -gui.tooltips.appliedenergistics2.ToggleMolecularAssemblersDescOn=Показувати тільки інтерфейси на молекулярних асемблерах -gui.tooltips.appliedenergistics2.ToggleShowFullInterfaces=Перемкнути відображення інтерфейсів із заповненими слотами -gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOnDesc=Показати всі інтерфейси -gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOffDesc=Показувати тільки інтерфейси з вільними слотами -gui.tooltips.appliedenergistics2.ToggleShowOnlyInvalidInterface=Перемкнути відображення інтерфейсів з недійсними шаблонами -gui.tooltips.appliedenergistics2.ToggleShowOnlyInvalidInterfaceOnDesc=Показати всі інтерфейси -gui.tooltips.appliedenergistics2.ToggleShowOnlyInvalidInterfaceOffDesc=Показати лише інтерфейси з недійсними шаблонами -gui.tooltips.appliedenergistics2.HighlightInterface=Виділити інтерфейс -gui.tooltips.appliedenergistics2.SearchFieldInputs=Вхід рецепту -gui.tooltips.appliedenergistics2.SearchFieldOutputs=Вихід рецепту -gui.tooltips.appliedenergistics2.SearchFieldNames=Назви інтерфейсів - -gui.tooltips.appliedenergistics2.InsertionModeDefault=Режим вставки за замовчуванням -gui.tooltips.appliedenergistics2.InsertionModeDefaultDesc=Від першого до останнього, об'єднайте стаки за потреби -gui.tooltips.appliedenergistics2.InsertionModePreferEmpty=Вставка надає перевагу порожнім слотам -gui.tooltips.appliedenergistics2.InsertionModePreferEmptyDesc=Те саме, що й за замовчуванням, але спочатку спробуйте порожні слоти -gui.tooltips.appliedenergistics2.InsertionModeOnlyEmpty=Вставляти лише у порожні слоти -gui.tooltips.appliedenergistics2.InsertionModeOnlyEmptyDesc=Від першого до останнього, не об'єднує стеки - -gui.tooltips.appliedenergistics2.SidelessModeSided=Односторонній режим -gui.tooltips.appliedenergistics2.SidelessModeSidedDesc=Кожна рідина доступна тільки з одного певного боку -gui.tooltips.appliedenergistics2.SidelessModeSideless=Безбічний режим -gui.tooltips.appliedenergistics2.SidelessModeSidelessDesc=Всі рідини доступні з усіх боків - -gui.tooltips.appliedenergistics2.AdvancedBlockingModeDefault=Режим блокування за замовчуванням -gui.tooltips.appliedenergistics2.AdvancedBlockingModeDefaultDesc=Блокування інтерфейсів слідує звичайним правилам блокування (ігнорування мікросхем тощо.) -gui.tooltips.appliedenergistics2.AdvancedBlockingModeAll=Вільний режим -gui.tooltips.appliedenergistics2.AdvancedBlockingModeAllDesc=Блокування інтерфейсів заблокує будь-який предмет у цій системі ME. - -gui.tooltips.appliedenergistics2.CraftingModeStandard=Стандартний режим створення -gui.tooltips.appliedenergistics2.CraftingModeStandardDesc=Створення крафта починається лише тоді, коли всі інгредієнти доступні в системі ME. -gui.tooltips.appliedenergistics2.CraftingModeIgnoreMissing=Режим "Ігнорування наявності ігредієнтів" -gui.tooltips.appliedenergistics2.CraftingModeIgnoreMissingDesc=Починає створювення, навіть якщо інгредієнти відсутні в системі ME. - -# Units -gui.appliedenergistics2.units.appliedenergstics=AE -gui.appliedenergistics2.units.ic2=EU -gui.appliedenergistics2.units.mekanism=Джоулі -gui.appliedenergistics2.units.rotarycraft=Вати -gui.appliedenergistics2.units.thermalexpansion=RF - -# Colors -gui.appliedenergistics2.White=Білий -gui.appliedenergistics2.Orange=Помаранчевий -gui.appliedenergistics2.Magenta=Пурпурний -gui.appliedenergistics2.LightBlue=Блакитний -gui.appliedenergistics2.Yellow=Жовтий -gui.appliedenergistics2.Lime=Лаймовий -gui.appliedenergistics2.Pink=Рожевий -gui.appliedenergistics2.Gray=Сірий -gui.appliedenergistics2.LightGray=Світло-сірий -gui.appliedenergistics2.Cyan=Блакитний -gui.appliedenergistics2.Purple=Фіолетовий -gui.appliedenergistics2.Blue=Синій -gui.appliedenergistics2.Brown=Коричневий -gui.appliedenergistics2.Green=Зелений -gui.appliedenergistics2.Red=Червоний -gui.appliedenergistics2.Black=Чорний -gui.appliedenergistics2.Fluix=Мінливий - -# Waila -waila.appliedenergistics2.Crafting=Створення -waila.appliedenergistics2.DeviceOnline=Пристрій увімкнено -waila.appliedenergistics2.DeviceOffline=Пристрій вимкнено -waila.appliedenergistics2.DeviceMissingChannel=У пристрою відсутній канал -waila.appliedenergistics2.Locked=Заблоковано -waila.appliedenergistics2.Unlocked=Розблоковано -waila.appliedenergistics2.Showing=Показує -waila.appliedenergistics2.Contains=Містить -waila.appliedenergistics2.Channels=%1$d з %2$d каналів -waila.appliedenergistics2.P2PUnlinked=Не пов'язано -waila.appliedenergistics2.P2PInputOneOutput=Пов'язано (вхідна сторона) -waila.appliedenergistics2.P2PInputManyOutputs=Пов'язано (вхідна сторона) - %d виходів -waila.appliedenergistics2.P2POutput=Пов'язано (вихідна сторона) -waila.appliedenergistics2.Booting=Мережа завантажується - -# Items -item.appliedenergistics2.ItemBasicStorageCell.1k.name=1k ME диск зберігання -item.appliedenergistics2.ItemBasicStorageCell.4k.name=4k ME диск зберігання -item.appliedenergistics2.ItemBasicStorageCell.16k.name=16k ME диск зберігання -item.appliedenergistics2.ItemBasicStorageCell.64k.name=64k ME диск зберігання -item.appliedenergistics2.ItemAdvancedStorageCell.256k.name=256k ME диск зберігання -item.appliedenergistics2.ItemAdvancedStorageCell.1024k.name=1024k ME диск зберігання -item.appliedenergistics2.ItemAdvancedStorageCell.4096k.name=4096k ME диск зберігання -item.appliedenergistics2.ItemAdvancedStorageCell.16384k.name=16384k ME диск зберігання -item.appliedenergistics2.ItemExtremeStorageCell.Container.name=ME Диск для збереження блоків -item.appliedenergistics2.ItemExtremeStorageCell.Quantum.name=ME Квантовий диск зберігання -item.appliedenergistics2.ItemExtremeStorageCell.Singularity.name=ME Сингулярний диск зберігання -item.appliedenergistics2.ItemCreativeStorageCell.name=Творча ME диск зберігання -item.appliedenergistics2.ItemVoidStorageCell.name=Пустотний ME диск зберігання -item.appliedenergistics2.ItemEncodedPattern.name=Закодований шаблон -item.appliedenergistics2.ItemViewCell.name=Диск для відображення -item.appliedenergistics2.ItemFacade.name=Кабельний фасад - -item.appliedenergistics2.ItemCrystalSeed.Certus.name=Насіння істинного кварцу -item.appliedenergistics2.ItemCrystalSeed.Nether.name=Насіння пекельного кварцу -item.appliedenergistics2.ItemCrystalSeed.Fluix.name=Насіння мінливого кристалу - -item.appliedenergistics2.ItemPart.InvalidType.name=Вимкнений предмет -item.appliedenergistics2.ItemMaterial.InvalidType.name=Цей предмет вимкнено. - -item.appliedenergistics2.ItemMaterial.BlankPattern.name=Порожній шаблон -item.appliedenergistics2.ItemMaterial.FormationCore.name=Ядро формування -item.appliedenergistics2.ItemMaterial.AnnihilationCore.name=Ядро знищення -item.appliedenergistics2.ItemMaterial.BasicCard.name=Базова карта -item.appliedenergistics2.ItemMaterial.AdvCard.name=Просунута карта - - -item.appliedenergistics2.ItemMaterial.CardCapacity.name=Карта ємності -item.appliedenergistics2.ItemMaterial.CardPatternCapacity.name=Карта ємності шаблонів -item.appliedenergistics2.ItemMaterial.CardFuzzy.name=Нечітка карта -item.appliedenergistics2.ItemMaterial.CardInverter.name=Карта інвертування -item.appliedenergistics2.ItemMaterial.CardRedstone.name=Карта редстоуна -item.appliedenergistics2.ItemMaterial.CardSpeed.name=Карта прискорення -item.appliedenergistics2.ItemMaterial.CardSuperSpeed.name=Карта гіперприскорення -item.appliedenergistics2.ItemMaterial.CardOreFilter.name=Карта фільтрації по словнику руд -item.appliedenergistics2.ItemMaterial.CardPatternRefiller.name=Карта автозавантаження шаблону -item.appliedenergistics2.ItemMaterial.CardAdvancedBlocking.name=Карта просунутого блокування - -item.appliedenergistics2.ItemMaterial.Cell2SpatialPart.name=2³ Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell16SpatialPart.name=16³ Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell128SpatialPart.name=128³ Компонент зберігання - -item.appliedenergistics2.ItemMaterial.Cell1kPart.name=1k ME Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell4kPart.name=4k ME Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell16kPart.name=16k ME Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell64kPart.name=64k ME Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell256kPart.name=256k ME Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell1024kPart.name=1024k ME Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell4096kPart.name=4096k ME Компонент зберігання -item.appliedenergistics2.ItemMaterial.Cell16384kPart.name=16384k ME Компонент зберігання - -item.appliedenergistics2.ItemMaterial.CertusQuartzCrystal.name=Кристал істинного кварцу -item.appliedenergistics2.ItemMaterial.CertusQuartzCrystalCharged.name=Кристал зарядженого істиного кварцу -item.appliedenergistics2.ItemMaterial.CertusQuartzDust.name=Порошок істинного кварцу -item.appliedenergistics2.ItemMaterial.EmptyStorageCell.name=ME Основа диску -item.appliedenergistics2.ItemMaterial.EmptyAdvancedStorageCell.name=ME Просунута основа диску -item.appliedenergistics2.ItemMaterial.EnderDust.name=Порошок Енду - -item.appliedenergistics2.ItemMaterial.Flour.name=Борошно -item.appliedenergistics2.ItemMaterial.FluixCrystal.name=Мінливий кристал -item.appliedenergistics2.ItemMaterial.FluixDust.name=Порошок мінливого кристалу -item.appliedenergistics2.ItemMaterial.FluixPearl.name=Мінлива перлина - -item.appliedenergistics2.ItemMaterial.GoldDust.name=Золотий порошок -item.appliedenergistics2.ItemMaterial.IronDust.name=Залізний порошок -item.appliedenergistics2.ItemMaterial.IronNugget.name=Залізний самородок - - -item.appliedenergistics2.ItemMaterial.MatterBall.name=Куля з матерії -item.appliedenergistics2.ItemMaterial.NetherQuartzDust.name=Порошок пекельного кварцу -item.appliedenergistics2.ItemMaterial.PurifiedCertusQuartzCrystal.name=Чистий істинний кварц -item.appliedenergistics2.ItemMaterial.PurifiedFluixCrystal.name=Чистий мінливий кристал -item.appliedenergistics2.ItemMaterial.PurifiedNetherQuartzCrystal.name=Чистий пекельний кварц -item.appliedenergistics2.ItemMaterial.QESingularity.name=Квантова заплутана сингулярність -item.appliedenergistics2.ItemMaterial.Silicon.name=Кремній -item.appliedenergistics2.ItemMaterial.Singularity.name=Сингулярність -item.appliedenergistics2.ItemMaterial.Wireless.name=Бездротовий приймач -item.appliedenergistics2.ItemMaterial.WirelessBooster.name=Бездротовий підсилювач -item.appliedenergistics2.ItemMaterial.WoodenGear.name=Дерев'яна шестерня - -item.appliedenergistics2.ItemMaterial.NamePress.name=Схема штампа для викарбовування імені -item.appliedenergistics2.ItemMaterial.EngProcessorPress.name=Схема штампа для інженерних елементів -item.appliedenergistics2.ItemMaterial.CalcProcessorPress.name=Схема штампа для розрахункових елементів -item.appliedenergistics2.ItemMaterial.LogicProcessorPress.name=Схема штампа для логічних елементів -item.appliedenergistics2.ItemMaterial.SiliconPress.name=Схема штампа для кремнієвих елементів - -item.appliedenergistics2.ItemMaterial.EngProcessorPrint.name=Штампований інженерний процесор -item.appliedenergistics2.ItemMaterial.CalcProcessorPrint.name=Штампований обчислювальний процесор -item.appliedenergistics2.ItemMaterial.LogicProcessorPrint.name=Штампований логічний процесор -item.appliedenergistics2.ItemMaterial.SiliconPrint.name=Штампований кремній - -item.appliedenergistics2.ItemMaterial.EngProcessor.name=Інженерний процесор -item.appliedenergistics2.ItemMaterial.CalcProcessor.name=Обчислювальний процесор -item.appliedenergistics2.ItemMaterial.LogicProcessor.name=Логічний процесор -item.appliedenergistics2.ItemMaterial.LogicProcessorAsm.name=Незавершений логічний процесор - -item.appliedenergistics2.ItemMaterial.SkyDust.name=Порошок небесного каменю -item.appliedenergistics2.ItemMaterial.CardCrafting.name=Карта створення - -item.appliedenergistics2.ItemPart.FormationPlane.name=ME Площина формування -item.appliedenergistics2.ItemPart.AnnihilationPlane.name=ME Площина руйнування -item.appliedenergistics2.ItemPart.IdentityAnnihilationPlane.name=ME ідентифікуюча площина винищення -item.appliedenergistics2.ItemPart.CableAnchor.name=Кабельний анкер -item.appliedenergistics2.ItemPart.CableCovered.name=ME Покритий кабель -item.appliedenergistics2.ItemPart.CableGlass.name=ME Скляний кабель -item.appliedenergistics2.ItemPart.CableSmart.name=ME Розумний кабель -item.appliedenergistics2.ItemPart.CableDense.name=ME Щільний розумний кабель -item.appliedenergistics2.ItemPart.CableDenseCovered.name=ME Щільний покритий кабель -item.appliedenergistics2.ItemPart.CableUltraDenseCovered.name=ME покритий магістральний кабель -item.appliedenergistics2.ItemPart.CableUltraDenseSmart.name=ME розмуний магістральний кабель -item.appliedenergistics2.ItemPart.StorageMonitor.name=ME Монітор сховища -item.appliedenergistics2.ItemPart.ConversionMonitor.name=ME Монітор перетворення -item.appliedenergistics2.ItemPart.SemiDarkMonitor.name=Освітлювальна панель -item.appliedenergistics2.ItemPart.Monitor.name=Яскрава освітлювальна панель -item.appliedenergistics2.ItemPart.DarkMonitor.name=Темна освітлювальна панель - -item.appliedenergistics2.ItemPart.ExportBus.name=ME-Шина експорту -item.appliedenergistics2.ItemPart.ImportBus.name=МЕ-Шина імпорту -item.appliedenergistics2.ItemPart.Interface.name=ME Інтерфейс -item.appliedenergistics2.ItemPart.LevelEmitter.name=ME Випромінювач рівня енергії -item.appliedenergistics2.ItemPart.P2PTunnel.name=P2P тунель -item.appliedenergistics2.ItemPart.PatternTerminal.name=ME Термінал шаблонів -item.appliedenergistics2.ItemPart.PatternTerminalEx.name=ME Термінал обробки шаблонів -item.appliedenergistics2.ItemPart.QuartzFiber.name=Кварцове волокно -item.appliedenergistics2.ItemPart.StorageBus.name=ME Шина зберігання -item.appliedenergistics2.ItemPart.Terminal.name=ME Термінал -item.appliedenergistics2.ItemPart.CraftingTerminal.name=ME Термінал створення -item.appliedenergistics2.ItemPart.InterfaceTerminal.name=ME Термінал інтерфейсу -item.appliedenergistics2.ItemPart.InvertedToggleBus.name=МЕ інвертована шина перемикання -item.appliedenergistics2.ItemPart.ToggleBus.name=МЕ шина перемикання -item.appliedenergistics2.ItemPart.CraftingMonitor.name=ME Монітор створення - -item.appliedenergistics2.ItemSpatialStorageCell.128Cubed.name=128³ диск зберігання простору -item.appliedenergistics2.ItemSpatialStorageCell.16Cubed.name=16³ диск зберігання простору -item.appliedenergistics2.ItemSpatialStorageCell.2Cubed.name=2³ диск зберігання простору - -item.appliedenergistics2.ToolCertusQuartzAxe.name=Сокира істинного кварцу -item.appliedenergistics2.ToolCertusQuartzCuttingKnife.name=Ніж істинного кварцу -item.appliedenergistics2.ToolCertusQuartzHoe.name=Мотика істинного кварцу -item.appliedenergistics2.ToolCertusQuartzPickaxe.name=Кайло істинного кварцу -item.appliedenergistics2.ToolCertusQuartzSpade.name=Лопата істинного кварцу -item.appliedenergistics2.ToolCertusQuartzSword.name=Меч істинного кварцу -item.appliedenergistics2.ToolCertusQuartzWrench.name=Ключ істинного кварцу - -item.appliedenergistics2.ToolNetherQuartzAxe.name=Сокира пекельного кварцу -item.appliedenergistics2.ToolNetherQuartzCuttingKnife.name=Ніж пекельного кварцу -item.appliedenergistics2.ToolNetherQuartzHoe.name=Мотика пекельного кварцу -item.appliedenergistics2.ToolNetherQuartzPickaxe.name=Кайло пекельного кварцу -item.appliedenergistics2.ToolNetherQuartzSpade.name=Лопата пекельного кварцу -item.appliedenergistics2.ToolNetherQuartzSword.name=Меч пекельного кварцу -item.appliedenergistics2.ToolNetherQuartzWrench.name=Ключ пекельного кварцу - -item.appliedenergistics2.ItemPaintBall.name=Кулька з фарбою -item.appliedenergistics2.ToolPortableCell.name=Портативний диск -item.appliedenergistics2.ToolNetworkTool.name=Мережевий інструмент -item.appliedenergistics2.ToolChargedStaff.name=Жезл заряджання -item.appliedenergistics2.ToolEntropyManipulator.name=Маніпулятор ентропії -item.appliedenergistics2.ToolMassCannon.name=Матеріальна пушка -item.appliedenergistics2.ToolMemoryCard.name=Карта пам'яті -item.appliedenergistics2.ToolColorApplicator.name=Аплікатор кольорів -item.appliedenergistics2.ToolWirelessTerminal.name=Бездротовий термінал -item.appliedenergistics2.ToolBiometricCard.name=Біометрична карта - -item.appliedenergistics2.ToolDebugCard.name=Творча.Карта відлагодження -item.appliedenergistics2.ToolReplicatorCard.name=Творча.Карта реплікації - -# Commands -commands.ae2.usage=Команди надані Applied Energistics 2 - використовуйте /ae2 list для списку та /ae2 help _____ для допомоги. -commands.ae2.permissions=Ви не маєте прав для виконання цієї команди. -commands.ae2.ChunkLogger=Перемикає завантаження та вивантаження чанків у журнал сервера. (ОП) -commands.ae2.ChunkLoggerOn=Ведення журналу чанків увімкнено -commands.ae2.ChunkLoggerOff=Ведення журналу чанків вимкнено -commands.ae2.Supporters=Відображає список прибічників AE2 -commands.ae2.Profiler=Команда профілювання сітки, передайте якогось Tile в сітці, щоб почати/зупинити профілювання -commands.ae2.ProfilerStart=Профілювання почато -commands.ae2.ProfilerFailed=Немає AE Tile тут -commands.ae2.ProfilerGridDown=Ця мережа вимкнена -commands.ae2.ProfilerStop=Середня кількість наносекунд, які займає ця мережа за такт: -commands.ae2.ProfilerFailedDim=Нема такого виміру -commands.ae2.ToggleFullAccess=Перемкнути повний доступ ОП AE, ігноруючи налаштування терміналу безпеки -commands.ae2.ToggleDebugTiming=Перемкнути ведення журналу менджера відлагодження Tick -commands.ae2.ToggleDebugPathfinding=Перемкнути пошук шляху журналу відлагодження - -# Achievements -achievement.ae2.Compass=Мисливець за метеоритами -achievement.ae2.Compass.desc=Зробіть метеоритний компас -achievement.ae2.Presses=Невідома технологія -achievement.ae2.Presses.desc=Знайдіть прес процесора -achievement.ae2.SpatialIO=Просторова координація -achievement.ae2.SpatialIO.desc=Створіть просторовий порт вводу-виводу -achievement.ae2.SpatialIOExplorer=Щоб сміливо йти -achievement.ae2.SpatialIOExplorer.desc=Зберігаються в просторовій камері -achievement.ae2.StorageCell=Краще, ніж скрині -achievement.ae2.StorageCell.desc=Зробіть комірку для зберігання -achievement.ae2.IOPort=Перетасувати комірки зберігання -achievement.ae2.IOPort.desc=Створіть порт вводу-виводу -achievement.ae2.CraftingTerminal=Більший (Набагато) стіл -achievement.ae2.CraftingTerminal.desc=Створіть термінал створення -achievement.ae2.PatternTerminal=Маестро створення -achievement.ae2.PatternTerminal.desc=Створіть термінал шаблонів -achievement.ae2.ChargedQuartz=Розряд -achievement.ae2.ChargedQuartz.desc=Знайдіть заряджений кварц -achievement.ae2.Fluix=Неприродне -achievement.ae2.Fluix.desc=Створюйте мінливі кристали -achievement.ae2.Charger=Створення мінливого -achievement.ae2.Charger.desc=Зробіть зарядний пристрій -achievement.ae2.CrystalGrowthAccelerator=Прискорювач – це стриманність -achievement.ae2.CrystalGrowthAccelerator.desc=Створіть прискорювач росту кристалів -achievement.ae2.GlassCable=Мінливе енергетичне підключення -achievement.ae2.GlassCable.desc=Зробіть ME скляний кабель -achievement.ae2.Networking1=Мережевий початківець -achievement.ae2.Networking1.desc=Використайте 8 каналів за допомогою пристроїв у мережі. -achievement.ae2.Controller=Мережевий комутатор -achievement.ae2.Controller.desc=Зробіть контроллер -achievement.ae2.Networking2=Мережевий інженер -achievement.ae2.Networking2.desc=Використайте 128 каналів за допомогою пристроїв у мережі. -achievement.ae2.Networking3=Мережевий адміністратор -achievement.ae2.Networking3.desc=Використайте 2048 каналів за допомогою пристроїв у мережі. -achievement.ae2.P2P=Мережа точка-точка -achievement.ae2.P2P.desc=Створіть тунель P2P -achievement.ae2.Recursive=Рекурсивна мережа -achievement.ae2.Recursive.desc=Розмістіть на інтерфейс шину зберігання. -achievement.ae2.CraftingCPU=Крафт нового покоління -achievement.ae2.CraftingCPU.desc=Створіть блок створення -achievement.ae2.Facade=Мережева естетика -achievement.ae2.Facade.desc=Створіть кабельний фасад -achievement.ae2.NetworkTool=Діагностика мережі -achievement.ae2.NetworkTool.desc=Створіть мережевий інструмент -achievement.ae2.PortableCell=Кочовий диск -achievement.ae2.PortableCell.desc=Створіть портативний диск -achievement.ae2.StorageBus=Безмежний потенціал -achievement.ae2.StorageBus.desc=Зробіть шину зберіганн -achievement.ae2.QNB=Квантове тунелювання -achievement.ae2.QNB.desc=Зробіть квантовий зв'язок - -# Stats -stat.ae2.ItemsInserted=Збережено предметів в ME-Сховище -stat.ae2.ItemsExtracted=Витягнуто предметів з ME-Сховища -stat.ae2.TurnedCranks=Зламано рукояток - -# Keys -key.appliedenergistics2.category=Applied Energistics 2 -key.toggle_focus.desc=Перемкнути фокус вікна пошуку From de4eaea945cd1f75189b44711050b115f600cf08 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Fri, 3 Nov 2023 19:22:29 +0800 Subject: [PATCH 17/34] Revert "Revert "Merge branch 'GTNewHorizons:master' into master"" This reverts commit 864bbd494c9f9f46ef5f30648fe6663701da1be8. --- dependencies.gradle | 10 +- .../gui/implementations/GuiCraftingCPU.java | 48 +- .../implementations/GuiCraftingStatus.java | 80 +- .../appliedenergistics2/lang/uk_UA.lang | 737 ++++++++++++++++++ 4 files changed, 845 insertions(+), 30 deletions(-) create mode 100644 src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang diff --git a/dependencies.gradle b/dependencies.gradle index b84818a71a4..80ba0962c38 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,16 +1,16 @@ // Add your dependencies here dependencies { - implementation('com.github.GTNewHorizons:NotEnoughItems:2.4.5-GTNH:dev') + implementation('com.github.GTNewHorizons:NotEnoughItems:2.4.6-GTNH:dev') implementation('curse.maven:cofh-core-69162:2388751') compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.4.13-GTNH:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:AE2FluidCraft-Rework:1.1.42-gtnh:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.36:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.3.4:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.68:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.73:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:Jabba:1.3.0:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:inventory-tweaks:1.5.16:api') {transitive = false} - compileOnly('com.github.GTNewHorizons:OpenComputers:1.9.17-GTNH:api') {transitive = false} + compileOnly('com.github.GTNewHorizons:inventory-tweaks:1.6.0:api') {transitive = false} + compileOnly('com.github.GTNewHorizons:OpenComputers:1.9.19-GTNH:api') {transitive = false} compileOnly('com.github.GTNewHorizons:waila:1.6.2:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:Railcraft:9.15.0:api') {transitive = false} compileOnly('net.industrial-craft:industrialcraft-2:2.2.828-experimental:api') @@ -29,7 +29,7 @@ dependencies { functionalTestImplementation('org.junit.platform:junit-platform-engine') functionalTestImplementation('org.junit.platform:junit-platform-launcher') functionalTestImplementation('org.junit.platform:junit-platform-reporting') - functionalTestImplementation('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.68:dev') { + functionalTestImplementation('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.73:dev') { exclude module: "Applied-Energistics-2-Unofficial" } diff --git a/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java b/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java index cc9677d27b2..cec78750f33 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java +++ b/src/main/java/appeng/client/gui/implementations/GuiCraftingCPU.java @@ -58,16 +58,19 @@ public class GuiCraftingCPU extends AEBaseGui implements ISortSource, IGuiTooltipHandler { - private static final int GUI_HEIGHT = 184; - private static final int GUI_WIDTH = 238; + protected static final int GUI_HEIGHT = 184; + protected static final int GUI_WIDTH = 238; - private static final int DISPLAYED_ROWS = 6; + protected static final int TEXTURE_BELOW_TOP_ROW_Y = 41; + protected static final int TEXTURE_ABOVE_BOTTOM_ROW_Y = 51; + protected static final int DISPLAYED_ROWS = 6; - private static final int SECTION_LENGTH = 67; + protected static final int SECTION_LENGTH = 67; + protected static final int SECTION_HEIGHT = 23; - private static final int SCROLLBAR_TOP = 19; - private static final int SCROLLBAR_LEFT = 218; - private static final int SCROLLBAR_HEIGHT = 137; + protected static final int SCROLLBAR_TOP = 19; + protected static final int SCROLLBAR_LEFT = 218; + protected static final int SCROLLBAR_HEIGHT = 137; private static final int CANCEL_LEFT_OFFSET = 163; private static final int CANCEL_TOP_OFFSET = 25; @@ -79,12 +82,15 @@ public class GuiCraftingCPU extends AEBaseGui implements ISortSource, IGuiToolti private static final int ITEMSTACK_LEFT_OFFSET = 9; private static final int ITEMSTACK_TOP_OFFSET = 22; + private static final int ITEMS_PER_ROW = 3; private final ContainerCraftingCPU craftingCpu; - private IItemList storage = AEApi.instance().storage().createItemList(); - private IItemList active = AEApi.instance().storage().createItemList(); - private IItemList pending = AEApi.instance().storage().createItemList(); + protected IItemList storage = AEApi.instance().storage().createItemList(); + protected IItemList active = AEApi.instance().storage().createItemList(); + protected IItemList pending = AEApi.instance().storage().createItemList(); + + protected int rows = DISPLAYED_ROWS; private class RemainingOperations implements ITooltip { @@ -152,7 +158,7 @@ public int getStringWidth() { } } - private List visual = new ArrayList<>(); + protected List visual = new ArrayList<>(); private GuiButton cancel; private int tooltip = -1; private final RemainingOperations remainingOperations = new RemainingOperations(); @@ -237,7 +243,7 @@ private void setScrollBar() { final int size = this.visual.size(); this.getScrollBar().setTop(SCROLLBAR_TOP).setLeft(SCROLLBAR_LEFT).setHeight(SCROLLBAR_HEIGHT); - this.getScrollBar().setRange(0, (size + 2) / 3 - DISPLAYED_ROWS, 1); + this.getScrollBar().setRange(0, (size + 2) / ITEMS_PER_ROW - rows, 1); } @Override @@ -249,15 +255,15 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { this.tooltip = -1; - final int offY = 23; + final int offY = SECTION_HEIGHT; int y = 0; int x = 0; - for (int z = 0; z <= 4 * 5; z++) { - final int minX = gx + 9 + x * 67; - final int minY = gy + 22 + y * offY; + for (int z = 0; z <= ITEMS_PER_ROW * rows; z++) { + final int minX = gx + ITEMSTACK_LEFT_OFFSET + x * SECTION_LENGTH; + final int minY = gy + ITEMSTACK_TOP_OFFSET + y * offY; - if (minX < mouseX && minX + 67 > mouseX) { - if (minY < mouseY && minY + offY - 2 > mouseY) { + if (minX < mouseX && minX + SECTION_LENGTH > mouseX) { + if (minY < mouseY && minY + offY > mouseY) { this.tooltip = z; break; } @@ -265,7 +271,7 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { x++; - if (x > 2) { + if (x == ITEMS_PER_ROW) { y++; x = 0; } @@ -310,8 +316,8 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int x = 0; int y = 0; - final int viewStart = this.getScrollBar().getCurrentScroll() * 3; - final int viewEnd = viewStart + 3 * 6; + final int viewStart = this.getScrollBar().getCurrentScroll() * ITEMS_PER_ROW; + final int viewEnd = viewStart + ITEMS_PER_ROW * rows; String dspToolTip = ""; final List lineList = new LinkedList<>(); diff --git a/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java b/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java index 622c2077d3c..85aae6b93ef 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiCraftingStatus.java @@ -13,6 +13,8 @@ */ package appeng.client.gui.implementations; +import java.util.List; + import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; @@ -20,13 +22,18 @@ import org.lwjgl.input.Mouse; import appeng.api.AEApi; +import appeng.api.config.Settings; +import appeng.api.config.TerminalStyle; import appeng.api.definitions.IDefinitions; import appeng.api.definitions.IParts; import appeng.api.storage.ITerminalHost; +import appeng.api.storage.data.IAEItemStack; import appeng.client.gui.widgets.GuiCraftingCPUTable; +import appeng.client.gui.widgets.GuiImgButton; import appeng.client.gui.widgets.GuiTabButton; import appeng.client.gui.widgets.ICraftingCPUTableHolder; import appeng.container.implementations.ContainerCraftingStatus; +import appeng.core.AEConfig; import appeng.core.localization.GuiText; import appeng.core.sync.GuiBridge; import appeng.core.sync.network.NetworkHandler; @@ -46,11 +53,16 @@ public class GuiCraftingStatus extends GuiCraftingCPU implements ICraftingCPUTab private GuiTabButton originalGuiBtn; private GuiBridge originalGui; private ItemStack myIcon = null; + private boolean tallMode; + private GuiImgButton switchTallMode; public GuiCraftingStatus(final InventoryPlayer inventoryPlayer, final ITerminalHost te) { super(new ContainerCraftingStatus(inventoryPlayer, te)); this.status = (ContainerCraftingStatus) this.inventorySlots; + this.tallMode = AEConfig.instance.getConfigManager().getSetting(Settings.TERMINAL_STYLE) == TerminalStyle.TALL; + recalculateScreenSize(); + final Object target = this.status.getTarget(); final IDefinitions definitions = AEApi.instance().definitions(); final IParts parts = definitions.parts(); @@ -106,16 +118,21 @@ protected void actionPerformed(final GuiButton btn) { if (btn == this.selectCPU) { cpuTable.cycleCPU(backwards); - } - - if (btn == this.originalGuiBtn) { + } else if (btn == this.originalGuiBtn) { NetworkHandler.instance.sendToServer(new PacketSwitchGuis(this.originalGui)); + } else if (btn == this.switchTallMode) { + tallMode = !tallMode; + switchTallMode.set(tallMode ? TerminalStyle.TALL : TerminalStyle.SMALL); + recalculateScreenSize(); + this.setWorldAndResolution(mc, width, height); } } @Override public void initGui() { + recalculateScreenSize(); super.initGui(); + this.setScrollBar(); this.selectCPU = new GuiButton( 0, @@ -136,6 +153,12 @@ public void initGui() { itemRender)); this.originalGuiBtn.setHideEdge(13); } + this.switchTallMode = new GuiImgButton( + this.guiLeft - 18, + this.guiTop + 166, + Settings.TERMINAL_STYLE, + tallMode ? TerminalStyle.TALL : TerminalStyle.SMALL); + this.buttonList.add(switchTallMode); } @Override @@ -153,7 +176,31 @@ public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { @Override public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { - super.drawBG(offsetX, offsetY, mouseX, mouseY); + this.bindTexture("guis/craftingcpu.png"); + if (tallMode) { + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, TEXTURE_BELOW_TOP_ROW_Y); + int y = TEXTURE_BELOW_TOP_ROW_Y; + // first and last row are pre-baked + for (int row = 1; row < rows - 1; row++) { + this.drawTexturedModalRect( + offsetX, + offsetY + y, + 0, + TEXTURE_BELOW_TOP_ROW_Y, + this.xSize, + SECTION_HEIGHT); + y += SECTION_HEIGHT; + } + this.drawTexturedModalRect( + offsetX, + offsetY + y, + 0, + GUI_HEIGHT - TEXTURE_ABOVE_BOTTOM_ROW_Y, + this.xSize, + TEXTURE_ABOVE_BOTTOM_ROW_Y); + } else { + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + } this.cpuTable.drawBG(offsetX, offsetY); } @@ -206,4 +253,29 @@ private void updateCPUButtonText() { protected String getGuiDisplayName(final String in) { return in; // the cup name is on the button } + + protected void recalculateScreenSize() { + final int maxAvailableHeight = height - 64; + this.xSize = GUI_WIDTH; + if (tallMode) { + this.rows = (maxAvailableHeight - (SCROLLBAR_TOP + SECTION_HEIGHT)) / SECTION_HEIGHT; + this.ySize = SCROLLBAR_TOP + SECTION_HEIGHT + 5 + this.rows * SECTION_HEIGHT; + } else { + this.rows = DISPLAYED_ROWS; + this.ySize = GUI_HEIGHT; + } + } + + private void setScrollBar() { + final int size = this.visual.size(); + + this.getScrollBar().setTop(SCROLLBAR_TOP).setLeft(SCROLLBAR_LEFT).setHeight(ySize - 47); + this.getScrollBar().setRange(0, (size + 2) / 3 - this.rows, 1); + } + + @Override + public void postUpdate(List list, byte ref) { + super.postUpdate(list, ref); + setScrollBar(); + } } diff --git a/src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang b/src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang new file mode 100644 index 00000000000..2edbc7bb7cc --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/lang/uk_UA.lang @@ -0,0 +1,737 @@ +# Blocks +tile.appliedenergistics2.BlockCableBus.name=AE2 кабель та/або шина +tile.appliedenergistics2.BlockCellWorkbench.name=Верстак для роботи з дисками +tile.appliedenergistics2.BlockCharger.name=Зарядний пристрій +tile.appliedenergistics2.BlockChest.name=ME-Скриня +tile.appliedenergistics2.BlockCondenser.name=Конденсатор матерії +tile.appliedenergistics2.BlockController.name=МЕ-Контролер +tile.appliedenergistics2.BlockCrank.name=Дерев’яна ручка +tile.appliedenergistics2.BlockCreativeEnergyCell.name=Творчий накопичувач енергії +tile.appliedenergistics2.BlockDenseEnergyCell.name=Щільний накопичувач енергії +tile.appliedenergistics2.BlockEnergyCell.name=Накопичувач енергії +tile.appliedenergistics2.BlockDrive.name=ME-Привід +tile.appliedenergistics2.BlockEnergyAcceptor.name=Приймач енергії +tile.appliedenergistics2.BlockGrinder.name=Кварцовий точильний камінь +tile.appliedenergistics2.BlockMatrixFrame.name=Каркас матриці +tile.appliedenergistics2.BlockIOPort.name=ME-Порт вводу/виводу +tile.appliedenergistics2.BlockInscriber.name=Штампувальний прес +tile.appliedenergistics2.BlockInterface.name=Постачальник шаблонів +tile.appliedenergistics2.BlockQuantumLinkChamber.name=МЕ-Камера квантового зв'язку +tile.appliedenergistics2.BlockQuantumRing.name=МЕ-Квантове кільце +tile.appliedenergistics2.BlockFluix.name=Блок мінливого кристалу +tile.appliedenergistics2.BlockQuartz.name=Блок істинного кварцу +tile.appliedenergistics2.BlockQuartzChiseled.name=Точений блок істинного кварцу +tile.appliedenergistics2.BlockQuartzGlass.name=Кварцове скло +tile.appliedenergistics2.BlockQuartzLamp.name=Яскраве кварцове скло +tile.appliedenergistics2.BlockQuartzPillar.name=Колона з істинного кварцу +tile.appliedenergistics2.BlockQuartzTorch.name=Заряджений кварцовий світильник +tile.appliedenergistics2.BlockLightDetector.name=Детектор світла +tile.appliedenergistics2.BlockSpatialIOPort.name=Просторовий порт IO +tile.appliedenergistics2.BlockSpatialPylon.name=Просторовий пілон +tile.appliedenergistics2.BlockTinyTNT.name=Крихітний динаміт +tile.appliedenergistics2.BlockVibrationChamber.name=Вібраційна камера +tile.appliedenergistics2.BlockWireless.name=ME-Бездротова точка доступу +tile.appliedenergistics2.OreQuartz.name=Руда істинного кварцу +tile.appliedenergistics2.OreQuartzCharged.name=Руда зарядженного істиного кварцу +tile.appliedenergistics2.BlockSecurity.name=ME-Термінал безпеки +tile.appliedenergistics2.BlockQuartzGrowthAccelerator.name=Прискорювач росту кристалів +tile.appliedenergistics2.BlockSkyStone.name=Небесний камінь +tile.appliedenergistics2.BlockSkyStone.Block.name=Небесний камінь +tile.appliedenergistics2.BlockSkyStone.Brick.name=Цегла з небесного каменю +tile.appliedenergistics2.BlockSkyStone.SmallBrick.name=Дрібна цегла з небесного каменю +tile.appliedenergistics2.BlockSkyChest.name=Скриня з небесного каменю +tile.appliedenergistics2.BlockSkyChest.Block.name=Скриня з небесного каменю +tile.appliedenergistics2.BlockSkyCompass.name=Метеоритний компас +tile.appliedenergistics2.BlockCraftingMonitor.name=Монітор створення +tile.appliedenergistics2.BlockCraftingStorage.name=1К Сховище для створення +tile.appliedenergistics2.BlockCraftingStorage4k.name=4К Сховище для створення +tile.appliedenergistics2.BlockCraftingStorage16k.name=16К Сховище для створення +tile.appliedenergistics2.BlockCraftingStorage64k.name=64К Сховище для створення +tile.appliedenergistics2.BlockCraftingStorage256k.name=256К Сховище для створення +tile.appliedenergistics2.BlockCraftingStorage1024k.name=1024К Сховище для створення +tile.appliedenergistics2.BlockCraftingStorage4096k.name=4096К Сховище для створення +tile.appliedenergistics2.BlockCraftingStorage16384k.name=16384К Сховище для створення +tile.appliedenergistics2.BlockCraftingAccelerator.name=Блок сумісної обробки +tile.appliedenergistics2.BlockCraftingAccelerator4x.name=4-ох ядерний блок сумісної обробки +tile.appliedenergistics2.BlockCraftingAccelerator16x.name=16-ти ядерний блок сумісної обробки +tile.appliedenergistics2.BlockCraftingAccelerator64x.name=64-ох ядерний блок сумісної обробки +tile.appliedenergistics2.BlockCraftingAccelerator256x.name=256-и ядерний блок сумісної обробки +tile.appliedenergistics2.BlockCraftingAccelerator1024x.name=1024-ох ядерний блок сумісної обробки +tile.appliedenergistics2.BlockCraftingAccelerator4096x.name=4096-и ядерний блок сумісної обробки +tile.appliedenergistics2.BlockCraftingUnit.name=Блок створення +tile.appliedenergistics2.BlockMolecularAssembler.name=Молекулярний збирач + +# Stairs +tile.appliedenergistics2.ChiseledQuartzStairBlock.name=Виточені сходи з істинного кварцу +tile.appliedenergistics2.FluixStairBlock.name=Сходи з мінливого кристалу +tile.appliedenergistics2.QuartzPillarStairBlock.name=Сходи з колони істинного кварцу +tile.appliedenergistics2.QuartzStairBlock.name=Сходи з істинного кварцу +tile.appliedenergistics2.SkyStoneBlockStairBlock.name=Сходи з небесного каменю +tile.appliedenergistics2.SkyStoneBrickStairBlock.name=Цегляні сходи з небесного каменю +tile.appliedenergistics2.SkyStoneSmallBrickStairBlock.name=Сходи з дрібної цегли з небесного каменю +tile.appliedenergistics2.SkyStoneStairBlock.name=Сходи з небесного каменю + +# Slabs +tile.appliedenergistics2.ChiseledQuartzSlabBlock.name=Плита з точеного істинного кварцу +tile.appliedenergistics2.FluixSlabBlock.name=Плита з мінливого кристалу +tile.appliedenergistics2.QuartzPillarSlabBlock.name=Плита з колони істинного кварцу +tile.appliedenergistics2.QuartzSlabBlock.name=Плита з істинного кварцу +tile.appliedenergistics2.SkyStoneBlockSlabBlock.name=Плита з небесного каменю +tile.appliedenergistics2.SkyStoneBrickSlabBlock.name=Цегляна плита з небесного каменя +tile.appliedenergistics2.SkyStoneSmallBrickSlabBlock.name=Плита з дрібної цегли небесного каменю +tile.appliedenergistics2.SkyStoneSlabBlock.name=Плита з небесного каменю + +# Chat Messages +chat.appliedenergistics2.ChestCannotReadStorageCell=ME скриня не може зчитати диск зберігання. +chat.appliedenergistics2.SettingCleared=Карта пам'яті очищена. +chat.appliedenergistics2.OutOfRange=Бездротова мережа поза зоною досяжності. +chat.appliedenergistics2.InvalidMachine=Неможливо відновити конфігурацію для цього пристрою. +chat.appliedenergistics2.LoadedSettings=Завантажено конфігурацію пристрою з карти пам'яті. +chat.appliedenergistics2.DeviceNotPowered=Недостатньо енергії для пристрою. +chat.appliedenergistics2.DeviceNotWirelessTerminal=Пристрій не є бездротовим терміналом. +chat.appliedenergistics2.DeviceNotLinked=Пристрій не прив'язано. +chat.appliedenergistics2.StationCanNotBeLocated=Станцію не вдається знайти. +chat.appliedenergistics2.MachineNotPowered=У механізму відсутнє живлення. +chat.appliedenergistics2.CommunicationError=Помилка з'єднання з мережею. +chat.appliedenergistics2.SavedSettings=Успішно збережено налаштування. +chat.appliedenergistics2.AmmoDepleted=Боєприпаси вичерпані. +chat.appliedenergistics2.isNowLocked=Монітор заблоковано. +chat.appliedenergistics2.isNowUnlocked=Монітор розблоковано. +chat.appliedenergistics2.TunnelNotConnected=Тунель не з'єднаний. +chat.appliedenergistics2.TunnelInputIsAt=Вхід до тунелю знаходиться за (%d, %d, %d) +chat.appliedenergistics2.TunnelHasNoOutputs=Тунель не має виходів. +chat.appliedenergistics2.TunnelOutputsAreAt=Виходи з тунелю знаходяться за: +chat.appliedenergistics2.InterfaceInOtherDim=Інтерфейс розташований у вимірі: %d і не може бути підсвідчений +chat.appliedenergistics2.InterfaceHighlighted=Інтерфейс тепер підсвідчуються за %d, %d, %d +chat.appliedenergistics2.CraftingItemsWentMissing=Не вдалося почати крафт, інгредієнт був пропущений: %d * %s +chat.appliedenergistics2.FBOUnsupported=OpenGL FBOs не підтримуються, не можна експортувати зображення +# Creative Tabs +itemGroup.appliedenergistics2=Applied Energistics 2 +itemGroup.appliedenergistics2.facades=Applied Energistics 2 - Фасади + +# GUI +gui.appliedenergistics2.CraftingTerminal=Термінал створення +gui.appliedenergistics2.METunnel=МЕ +gui.appliedenergistics2.ItemTunnel=Предмет +gui.appliedenergistics2.FluidTunnel=Рідина +gui.appliedenergistics2.RedstoneTunnel=Редстоун +gui.appliedenergistics2.EUTunnel=EU +gui.appliedenergistics2.RFTunnel=RF +gui.appliedenergistics2.LightTunnel=Світло +gui.appliedenergistics2.OCTunnel=OpenComputers +gui.appliedenergistics2.PressureTunnel=Тиск +gui.appliedenergistics2.GTTunnel=GT EU +gui.appliedenergistics2.IFACETunnel=ME Інтерфейс + +gui.appliedenergistics2.security.extract.name=Забирати +gui.appliedenergistics2.security.inject.name=Класти +gui.appliedenergistics2.security.craft.name=Створювати +gui.appliedenergistics2.security.build.name=Побудувати +gui.appliedenergistics2.security.security.name=Безпека + +gui.appliedenergistics2.security.extract.tip=Користувач може забирати предмети зі сховища. +gui.appliedenergistics2.security.inject.tip=Користувачеві дозволено класти нові предмети у сховище. +gui.appliedenergistics2.security.craft.tip=Користувач може розпочинати нові задачі на створення. +gui.appliedenergistics2.security.build.tip=Користувач може змінювати фізичну структуру мережі та вносити зміни до конфігурації. +gui.appliedenergistics2.security.security.tip=Користувач може отримати доступ до терміналу безпеки мережі та модифікувати його. + +gui.appliedenergistics2.Efficiency=Ефективність +gui.appliedenergistics2.RequiredPower=Необхідна енергія +gui.appliedenergistics2.StoredPower=Накопичена енергія +gui.appliedenergistics2.MaxPower=Максимальна енергія +gui.appliedenergistics2.QuartzCuttingKnife=Кварцовий ріжучий ніж +gui.appliedenergistics2.Inscriber=Штампувальний прес +gui.appliedenergistics2.Wireless=Бездротова точка доступу +gui.appliedenergistics2.WirelessTerminal=Бездротовий термінал +gui.appliedenergistics2.NoPermissions=Дозволи не вибрано +gui.appliedenergistics2.SecurityCardEditor=Редактор біометричних карток +gui.appliedenergistics2.Encoded=Закодований +gui.appliedenergistics2.Priority=Пріоритет +gui.appliedenergistics2.StorageBus=МЕ-шина зберігання +gui.appliedenergistics2.EnergyDrain=Пасивне споживання +gui.appliedenergistics2.Installed=Встановлено +gui.appliedenergistics2.NetworkTool=Діагностика мережі +gui.appliedenergistics2.PowerUsageRate=Використання енергії +gui.appliedenergistics2.PowerInputRate=Генерація енергії +gui.appliedenergistics2.PortableCell=Портативний диск +gui.appliedenergistics2.Security=Термінал безпеки +gui.appliedenergistics2.CellWorkbench=Верстак для роботи з дисками +gui.appliedenergistics2.QuantumLinkChamber=Камера квантового зв'язку +gui.appliedenergistics2.IOPort=ME-Порт вводу/виводу +gui.appliedenergistics2.Chest=ME-Скриня +gui.appliedenergistics2.Condenser=Конденсатор матерії +gui.appliedenergistics2.Config=Конфігурація +gui.appliedenergistics2.Drive=ME-Привід +gui.appliedenergistics2.ExportBus=ME-Шина експорту +gui.appliedenergistics2.GrindStone=Точильний камінь +gui.appliedenergistics2.ImportBus=МЕ-Шина імпорту +gui.appliedenergistics2.Interface=ME-Інтерфейс +gui.appliedenergistics2.LevelEmitter=ME Випромінювач рівня енергії +gui.appliedenergistics2.Of=з +gui.appliedenergistics2.Patterns=Шаблони +gui.appliedenergistics2.SpatialIOPort=Просторовий порт IO +gui.appliedenergistics2.StoredEnergy=Накопичена енергія +gui.appliedenergistics2.StoredItems=Накопичені предмети +gui.appliedenergistics2.StoredStacks=Накопічені стеки +gui.appliedenergistics2.Terminal=Термінал +gui.appliedenergistics2.InterfaceTerminal=Термінал Інтерфейсів +gui.appliedenergistics2.InterfaceTerminalHint=Показати або Приховати в терміналі інтерфейсів. +gui.appliedenergistics2.FormationPlane=Площина формування +gui.appliedenergistics2.VibrationChamber=Вібраційна камера +gui.appliedenergistics2.NetworkDetails=Деталі мережі +gui.appliedenergistics2.StorageCells=МЕ-Диск зберігання +gui.appliedenergistics2.IOBuses=МЕ-Шина імпорту/експорту +gui.appliedenergistics2.Stores=Зберігає +gui.appliedenergistics2.BytesUsed=Байтів використано +gui.appliedenergistics2.Types=Типів +gui.appliedenergistics2.Blank=Порожній. +gui.appliedenergistics2.Unlinked=Без зв'язку +gui.appliedenergistics2.Linked=Прив'язаний +gui.appliedenergistics2.StoredSize=Збережений розмір +gui.appliedenergistics2.SkyChest=Скриня з небесного каменю +gui.appliedenergistics2.PatternTerminal=Термінал шаблонів +gui.appliedenergistics2.PatternTerminalEx=Термінал обробки шаблонів +gui.appliedenergistics2.CraftingPattern=Створення шаблону +gui.appliedenergistics2.MolecularAssembler=Молекулярний збирач +gui.appliedenergistics2.ProcessingPattern=Шаблон обробки +gui.appliedenergistics2.Crafts=Створення +gui.appliedenergistics2.And=і +gui.appliedenergistics2.Creates=Створює +gui.appliedenergistics2.With=з +gui.appliedenergistics2.Substitute=Використовува заміщюванні: +gui.appliedenergistics2.BeSubstitute=Може бути заміщенно: +gui.appliedenergistics2.Yes=Так +gui.appliedenergistics2.No=Ні +gui.appliedenergistics2.InWorldCrafting=AE2 у світовому створенні +gui.appliedenergistics2.inWorldFluix=Киньте 1 заряджений істинний кварц + 1 Пекельний кварц + 1 редстоун в воду поруч один з одним і почекайте трохи, щоб отримати 2 мінливих кристали. +gui.appliedenergistics2.inWorldPurificationCertus=Киньте насіння істинного кварцу, зроблене з порошоку істинного кварцу та піску, у воду; Щоб пришвидшити процес, додайте прискорювач росту кристалів. +gui.appliedenergistics2.inWorldPurificationNether=Киньте насіння Пекельного кварцу, зроблене з порошоку пекельного кварцу та піску, у воду; Щоб пришвидшити процес, додайте прискорювач росту кристалів. +gui.appliedenergistics2.inWorldPurificationFluix=Киньте насіння мінливого кристалу, зроблене з порошоку мінливого кристалу та пісоку, у воду; Щоб пришвидшити процес, додайте прискорювач росту кристалів. +gui.appliedenergistics2.inWorldSingularity=Для створення киньте 1 сингулярність і 1 Порошок Енду та спричиніть вибух у межах досяжності цих предметів. +gui.appliedenergistics2.ChargedQuartz=Заряджений істинний кварц створюється шляхом повіщення незарядженого кристалу істинниго кварцу у зарядний пристрій та подачі живлення. +gui.appliedenergistics2.ChargedQuartzFind=Заряджений істинний кварц зустрічається у світі досить рідко, зовні він схожий на звичайний істинний кварц, за винятком того, що виблискує. +gui.appliedenergistics2.NoSecondOutput=Немає вторинної продукції +gui.appliedenergistics2.OfSecondOutput=%1$d%% шанс на вторинну продукцію. +gui.appliedenergistics2.MultipleOutputs=%1$d%% вторинної, %2$d%% третинної продукції. +gui.appliedenergistics2.SelectAmount=Виберіть кількість +gui.appliedenergistics2.CopyMode=Режим копіювання +gui.appliedenergistics2.CopyModeDesc=Визначає, чи буде очищено вміст панелі конфігурації при вийманні диска. +gui.appliedenergistics2.Next=Далі +gui.appliedenergistics2.Lumen=Сяючий +gui.appliedenergistics2.Empty=Порожній +gui.appliedenergistics2.Stored=Зберігається +gui.appliedenergistics2.Cancel=Скасувати +gui.appliedenergistics2.ETAFormat=HH:mm:ss +gui.appliedenergistics2.SwitchCraftingSimulationDisplayMode=Перемикання режиму відображення (Список/Дерево) +gui.appliedenergistics2.Crafting=Створення +gui.appliedenergistics2.Scheduled=Заплановано +gui.appliedenergistics2.CraftingStatus=Статус створення +gui.appliedenergistics2.RemainingOperations=Простоюючі процесори +gui.appliedenergistics2.FromStorage=Доступно +gui.appliedenergistics2.ToCraft=Потрібно створити +gui.appliedenergistics2.CraftingPlan=План створення +gui.appliedenergistics2.Automatic=Автоматично +gui.appliedenergistics2.Start=Почати +gui.appliedenergistics2.Missing=Пропущено +gui.appliedenergistics2.NoCraftingTreeReceived=Не отримано жодного дерева створення +gui.appliedenergistics2.CraftingStepLimitExceeded=Перевищено ліміт етапів створення +gui.appliedenergistics2.RequestedItem=Вимагається предмет +gui.appliedenergistics2.SimulationIncomplete=Моделювання незавершене +gui.appliedenergistics2.Bytes=Сховище +gui.appliedenergistics2.Set=Встановити +gui.appliedenergistics2.Simulation=Моделювання +gui.appliedenergistics2.CoProcessors=Співпроцесори +gui.appliedenergistics2.CraftingCPU=Створення процесора +gui.appliedenergistics2.NoCraftingCPUs=Процесори для створення не доступні +gui.appliedenergistics2.CalculatingWait=Обчислення, будь ласка зачекайте... +gui.appliedenergistics2.Clean=Очистити +gui.appliedenergistics2.InvalidPattern=Неправильний шаблон +gui.appliedenergistics2.UnknownItem=Невідомий предмет +gui.appliedenergistics2.Range=Діапазон +gui.appliedenergistics2.TransparentFacades=Прозорі фасади +gui.appliedenergistics2.TransparentFacadesHint=Керує видимістю фасадів, коли мережевий інструмент знаходиться на панелі інструментів. +gui.appliedenergistics2.CPUs=Процессор +gui.appliedenergistics2.NoCraftingJobs=Немає активного завдання на створення +gui.appliedenergistics2.FacadeCrafting=Виготовлення фасадів +gui.appliedenergistics2.inWorldCraftingPresses=Шаблони для створення знаходяться в центрі метеоритів, які можна знайти по всьому світу, їх можна знайти за допомогою метеоритного компасу. +gui.appliedenergistics2.Included=Включено +gui.appliedenergistics2.Excluded=Виключено +gui.appliedenergistics2.Partitioned=Розділений +gui.appliedenergistics2.PartitionedOre=Фільтр словника руд +gui.appliedenergistics2.Precise=Точно +gui.appliedenergistics2.Fuzzy=Нечіткий +gui.appliedenergistics2.Filter=Фільтр +gui.appliedenergistics2.SmallFontCraft=Створення +gui.appliedenergistics2.LargeFontCraft=+ +gui.appliedenergistics2.Renamer=Користувацьке ім'я: (Введіть, щоб встановити) +gui.appliedenergistics2.OreFilterLabel=Фільтр словника руд +gui.appliedenergistics2.HoldShiftForTooltip=Утримуйте клавішу Shift для розширеної підказки +gui.appliedenergistics2.HoldShiftClick_HIGHLIGHT_INTERFACE=Утримуйте клавішу Shift, щоб підсвітити інтерфейс +gui.appliedenergistics2.Nothing=Нічого +gui.appliedenergistics2.VoidCellTooltip=Видаляє §4все§7, що зберігається на ньому +gui.appliedenergistics2.Deprecated=Застаріле, буде видалене найближчим часом! + +# GUI Colors - ARGB +gui.color.appliedenergistics2.SearchboxFocused=6E000000 +gui.color.appliedenergistics2.SearchboxUnfocused=00000000 +gui.color.appliedenergistics2.SearchboxFocused=6E000000 +gui.color.appliedenergistics2.SearchboxUnfocused=00000000 +gui.color.appliedenergistics2.ItemSlotOverlayUnpowered=66111111 +gui.color.appliedenergistics2.ItemSlotOverlayInvalid=66ff6666 +gui.color.appliedenergistics2.CraftConfirmMissingItem=1AFF0000 +gui.color.appliedenergistics2.CraftingCPUActive=5A45A021 +gui.color.appliedenergistics2.CraftingCPUScheduled=FF787878 +gui.color.appliedenergistics2.InterfaceTerminalMatch=2A00FF00 + +# GUI Tooltips +gui.tooltips.appliedenergistics2.Stash=Зберегти предмети +gui.tooltips.appliedenergistics2.StashDesc=Повернути предмети на сітці створення до мережевого сховища. +gui.tooltips.appliedenergistics2.Substitutions=Заміни по рудному словнику +gui.tooltips.appliedenergistics2.SubstitutionsDescEnabled=Дозволяє замінювати вхідні компоненти. +gui.tooltips.appliedenergistics2.SubstitutionsDescDisabled=Запобігає заміні вхідних компонентів. +gui.tooltips.appliedenergistics2.BeSubstitutions=Використовувати як заміну +gui.tooltips.appliedenergistics2.BeSubstitutionsDescEnabled=Дозволяє створення заміни вхідних компонентів. +gui.tooltips.appliedenergistics2.BeSubstitutionsDescDisabled=Забороняє створення заміни вхідних компонентів. Якщо всі доступні для інгредієнта шаблони вимкнено для заміни, симулятор створення буде поводитися з ними так, як якщо б вони були ввімкнені для заміни. + +gui.tooltips.appliedenergistics2.PatternSlotConfigTitle=Перемкнути режим створення шаблону +gui.tooltips.appliedenergistics2.PatternSlotConfigInfo=Перемкнути режим створення шаблону між (16 -> 4) та (4 -> 16) +gui.tooltips.appliedenergistics2.Encode=Закодувати шаблон +gui.tooltips.appliedenergistics2.EncodeDescription=Запишіть введений шаблон до поточного закодованого шаблону або до доступного порожнього шаблону. Утримуйте клавішу Shift, щоб перенести шаблон безпосередньо в інвентар. Утримуйте Shift+Control, щоб закодувати весь стек. + +gui.tooltips.appliedenergistics2.FuzzyMode=Нечітке порівняння +gui.tooltips.appliedenergistics2.FZPercent_25=Розділити шкоду на 25% +gui.tooltips.appliedenergistics2.FZPercent_50=Розділити шкоду на 50% +gui.tooltips.appliedenergistics2.FZPercent_75=Розділити шкоду на 75% +gui.tooltips.appliedenergistics2.FZPercent_99=Розділити шкоду на 99% + +gui.tooltips.appliedenergistics2.SortOrder=Порядок сортування +gui.tooltips.appliedenergistics2.SortBy=Сортувати за +gui.tooltips.appliedenergistics2.FZIgnoreAll=Будь-який збіг +gui.tooltips.appliedenergistics2.TransferDirection=Напрямок передачі +gui.tooltips.appliedenergistics2.TransferToNetwork=Передати дані до мережі +gui.tooltips.appliedenergistics2.TransferToStorageCell=Передати дані до диску зберігання +gui.tooltips.appliedenergistics2.ToggleSortDirection=Переключити напрямок передачі + +gui.tooltips.appliedenergistics2.StoredItems=Збережені предмети +gui.tooltips.appliedenergistics2.StoredCraftable=Зберігається / Створюється +gui.tooltips.appliedenergistics2.View=Вигляд +gui.tooltips.appliedenergistics2.RedstoneMode=Редстоун режим +gui.tooltips.appliedenergistics2.OperationMode=Режим роботи +gui.tooltips.appliedenergistics2.NumberOfItems=Кількість предметів +gui.tooltips.appliedenergistics2.ItemName=Назва предмета +gui.tooltips.appliedenergistics2.PowerUnits=Одиниці енергії +gui.tooltips.appliedenergistics2.IOMode=Режим входу/виходу +gui.tooltips.appliedenergistics2.CondenserOutput=ME-Конденсатор - Вихід +gui.tooltips.appliedenergistics2.PartitionStorage=Розділ сховища +gui.tooltips.appliedenergistics2.Clear=Очистити +gui.tooltips.appliedenergistics2.TrashController=Видалення за допомогою Shift / Space. + +gui.tooltips.appliedenergistics2.InterfaceBlockingMode=Режим блокування +gui.tooltips.appliedenergistics2.InterfaceCraftingMode=Режим створення +gui.tooltips.appliedenergistics2.Trash=Знищити предмети +gui.tooltips.appliedenergistics2.MatterBalls=Конденсувати в кулі матерії\n%s за предмет +gui.tooltips.appliedenergistics2.Singularity=Конденсувати в сингулярність\n%s за предмет +gui.tooltips.appliedenergistics2.Read=Тільки забирати +gui.tooltips.appliedenergistics2.Write=Тільки вставляти +gui.tooltips.appliedenergistics2.ReadWrite=Двонаправлений + +gui.tooltips.appliedenergistics2.AlwaysActive=Завжди активний +gui.tooltips.appliedenergistics2.ActiveWithoutSignal=Активний без сигналу +gui.tooltips.appliedenergistics2.ActiveWithSignal=Активний з сигналом +gui.tooltips.appliedenergistics2.ActiveOnPulse=Активувати один раз за імпульс +gui.tooltips.appliedenergistics2.EmitLevelsBelow=Випромінювати сигнал, коли рівень нижче ліміту. +gui.tooltips.appliedenergistics2.EmitLevelAbove=Випромінювати сигнал, коли рівень вищий або дорівнює ліміту. + +gui.tooltips.appliedenergistics2.SearchMode_Auto=Авто пошук +gui.tooltips.appliedenergistics2.SearchMode_Standard=Стандартний пошук +gui.tooltips.appliedenergistics2.SearchMode_NEIAuto=Синхронізований авто пошук NEI +gui.tooltips.appliedenergistics2.SearchMode_NEIStandard=Синхронізований стандартний пошук NEI +gui.tooltips.appliedenergistics2.SearchMode=Режим поля пошуку + +gui.tooltips.appliedenergistics2.PartitionStorageHint=Конфігурує розділ на основі поточних збережених об'єктів. +gui.tooltips.appliedenergistics2.ClearSettings=Очистити конфігурацію/налаштування +gui.tooltips.appliedenergistics2.Craftable=Створювальні +gui.tooltips.appliedenergistics2.MoveWhenEmpty=Перемістити до виводу, коли порожній. +gui.tooltips.appliedenergistics2.MoveWhenWorkIsDone=Перемістити до виводу, коли робота виконана. +gui.tooltips.appliedenergistics2.MoveWhenFull=Перемістити до виводу, коли заповниться. +gui.tooltips.appliedenergistics2.Disabled=Вимкнений +gui.tooltips.appliedenergistics2.Enable=Увімкнений +gui.tooltips.appliedenergistics2.Blocking=Не штовхати предмети для створення, якщо в інвентарі є предмети. +gui.tooltips.appliedenergistics2.NonBlocking=Ігнорувати вміст цільового інвентарю. +gui.tooltips.appliedenergistics2.Craft=Поведінка створення +gui.tooltips.appliedenergistics2.CraftOnly=Не використовувати збережені предмети, створювати лише під час експорту. +gui.tooltips.appliedenergistics2.CraftEither=Використовувати збережені предмети або створити під час експорту. +gui.tooltips.appliedenergistics2.LevelType=Тип рівня +gui.tooltips.appliedenergistics2.LevelType_Energy=Енергія +gui.tooltips.appliedenergistics2.LevelType_Item=Предмет +gui.tooltips.appliedenergistics2.InventoryTweaks=Inventory Tweaks +gui.tooltips.appliedenergistics2.Mod=Мод +gui.tooltips.appliedenergistics2.TerminalStyle=Стиль терміналу +gui.tooltips.appliedenergistics2.TerminalStyle_Full=Повноекранний термінал +gui.tooltips.appliedenergistics2.TerminalStyle_Tall=Високий центрований термінал +gui.tooltips.appliedenergistics2.TerminalStyle_Small=Малий центрований термінал +gui.tooltips.appliedenergistics2.SaveAsImage=Зберегти як зображення + +gui.tooltips.appliedenergistics2.DoesntDespawn=Цей предмет не зникне. +gui.tooltips.appliedenergistics2.EmitterMode=Режим випромінювача створення +gui.tooltips.appliedenergistics2.CraftViaRedstone=Випромінювати сигнал редстоуну для виготовлення предмета. +gui.tooltips.appliedenergistics2.EmitWhenCrafting=Випромінювати сигнал редстоуну, коли предмет створюється. + +gui.tooltips.appliedenergistics2.ReportInaccessibleItems=Повідомити про недоступні предмети +gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=Так: предмети, які не можна витягнути будуть видимими. +gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=Ні: Видимі лише предмети, що можна витягнути. + +gui.tooltips.appliedenergistics2.TypeFilter=Тип фільтру +gui.tooltips.appliedenergistics2.TypeFilterShowAll=Показати все +gui.tooltips.appliedenergistics2.TypeFilterShowItemsOnly=Показати тільки предмети +gui.tooltips.appliedenergistics2.TypeFilterShowFluidsOnly=Показувати тільки краплі рідин + +gui.tooltips.appliedenergistics2.BlockPlacement=Розміщення блоків +gui.tooltips.appliedenergistics2.BlockPlacementYes=Блоки будуть розміщатись як блоки. +gui.tooltips.appliedenergistics2.BlockPlacementNo=Блоки будуть випадати як предмети. + +gui.tooltips.appliedenergistics2.SchedulingMode=Режим планування +gui.tooltips.appliedenergistics2.SchedulingModeDefault=Експортуйте перший предмет, доки мережа не спорожніє, а потім спробуйте експортувати наступні. +gui.tooltips.appliedenergistics2.SchedulingModeRoundRobin=Експорт з використанням циклічного режиму. +gui.tooltips.appliedenergistics2.SchedulingModeRandom=Експортувати предмети у випадковому режимі. + +gui.tooltips.appliedenergistics2.ItemsStored=Збережені предмети: %s +gui.tooltips.appliedenergistics2.ItemCount=Кількість предметів: %s +gui.tooltips.appliedenergistics2.ItemsRequestable=Необхідні предмети: %s +gui.tooltips.appliedenergistics2.P2PFrequency=Частота: %s +gui.tooltips.appliedenergistics2.OreFilterHint=Відфільтрувати предмети за назвами зі словника руд +gui.tooltips.appliedenergistics2.OreFilter=Фільтр словника руд +gui.tooltips.appliedenergistics2.SearchStringTooltip=Клацніть ПКМ, щоб очистити рядок пошуку +gui.tooltips.appliedenergistics2.SaveSearchString=Зберігати рядок пошуку +gui.tooltips.appliedenergistics2.SaveSearchStringYes=Так +gui.tooltips.appliedenergistics2.SaveSearchStringNo=Ні +gui.tooltips.appliedenergistics2.DoublePattern=Подвоїти шаблон +gui.tooltips.appliedenergistics2.DoublePatternHint=Подвоїти розмір стеку входів та виходів шаблону, якщо це можливо. x8, коли shift утримується. +gui.tooltips.appliedenergistics2.CraftingStatus=Статус створення +gui.tooltips.appliedenergistics2.CraftingStatusDesc=Відкриває вікно стану створення +gui.tooltips.appliedenergistics2.ToggleMolecularAssemblers=Перемкнути відображення тільки інтерфейсів створення +gui.tooltips.appliedenergistics2.ToggleMolecularAssemblersDescOff=Показати всі інтерфейси +gui.tooltips.appliedenergistics2.ToggleMolecularAssemblersDescOn=Показувати тільки інтерфейси на молекулярних асемблерах +gui.tooltips.appliedenergistics2.ToggleShowFullInterfaces=Перемкнути відображення інтерфейсів із заповненими слотами +gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOnDesc=Показати всі інтерфейси +gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOffDesc=Показувати тільки інтерфейси з вільними слотами +gui.tooltips.appliedenergistics2.ToggleShowOnlyInvalidInterface=Перемкнути відображення інтерфейсів з недійсними шаблонами +gui.tooltips.appliedenergistics2.ToggleShowOnlyInvalidInterfaceOnDesc=Показати всі інтерфейси +gui.tooltips.appliedenergistics2.ToggleShowOnlyInvalidInterfaceOffDesc=Показати лише інтерфейси з недійсними шаблонами +gui.tooltips.appliedenergistics2.HighlightInterface=Виділити інтерфейс +gui.tooltips.appliedenergistics2.SearchFieldInputs=Вхід рецепту +gui.tooltips.appliedenergistics2.SearchFieldOutputs=Вихід рецепту +gui.tooltips.appliedenergistics2.SearchFieldNames=Назви інтерфейсів + +gui.tooltips.appliedenergistics2.InsertionModeDefault=Режим вставки за замовчуванням +gui.tooltips.appliedenergistics2.InsertionModeDefaultDesc=Від першого до останнього, об'єднайте стаки за потреби +gui.tooltips.appliedenergistics2.InsertionModePreferEmpty=Вставка надає перевагу порожнім слотам +gui.tooltips.appliedenergistics2.InsertionModePreferEmptyDesc=Те саме, що й за замовчуванням, але спочатку спробуйте порожні слоти +gui.tooltips.appliedenergistics2.InsertionModeOnlyEmpty=Вставляти лише у порожні слоти +gui.tooltips.appliedenergistics2.InsertionModeOnlyEmptyDesc=Від першого до останнього, не об'єднує стеки + +gui.tooltips.appliedenergistics2.SidelessModeSided=Односторонній режим +gui.tooltips.appliedenergistics2.SidelessModeSidedDesc=Кожна рідина доступна тільки з одного певного боку +gui.tooltips.appliedenergistics2.SidelessModeSideless=Безбічний режим +gui.tooltips.appliedenergistics2.SidelessModeSidelessDesc=Всі рідини доступні з усіх боків + +gui.tooltips.appliedenergistics2.AdvancedBlockingModeDefault=Режим блокування за замовчуванням +gui.tooltips.appliedenergistics2.AdvancedBlockingModeDefaultDesc=Блокування інтерфейсів слідує звичайним правилам блокування (ігнорування мікросхем тощо.) +gui.tooltips.appliedenergistics2.AdvancedBlockingModeAll=Вільний режим +gui.tooltips.appliedenergistics2.AdvancedBlockingModeAllDesc=Блокування інтерфейсів заблокує будь-який предмет у цій системі ME. + +gui.tooltips.appliedenergistics2.CraftingModeStandard=Стандартний режим створення +gui.tooltips.appliedenergistics2.CraftingModeStandardDesc=Створення крафта починається лише тоді, коли всі інгредієнти доступні в системі ME. +gui.tooltips.appliedenergistics2.CraftingModeIgnoreMissing=Режим "Ігнорування наявності ігредієнтів" +gui.tooltips.appliedenergistics2.CraftingModeIgnoreMissingDesc=Починає створювення, навіть якщо інгредієнти відсутні в системі ME. + +# Units +gui.appliedenergistics2.units.appliedenergstics=AE +gui.appliedenergistics2.units.ic2=EU +gui.appliedenergistics2.units.mekanism=Джоулі +gui.appliedenergistics2.units.rotarycraft=Вати +gui.appliedenergistics2.units.thermalexpansion=RF + +# Colors +gui.appliedenergistics2.White=Білий +gui.appliedenergistics2.Orange=Помаранчевий +gui.appliedenergistics2.Magenta=Пурпурний +gui.appliedenergistics2.LightBlue=Блакитний +gui.appliedenergistics2.Yellow=Жовтий +gui.appliedenergistics2.Lime=Лаймовий +gui.appliedenergistics2.Pink=Рожевий +gui.appliedenergistics2.Gray=Сірий +gui.appliedenergistics2.LightGray=Світло-сірий +gui.appliedenergistics2.Cyan=Блакитний +gui.appliedenergistics2.Purple=Фіолетовий +gui.appliedenergistics2.Blue=Синій +gui.appliedenergistics2.Brown=Коричневий +gui.appliedenergistics2.Green=Зелений +gui.appliedenergistics2.Red=Червоний +gui.appliedenergistics2.Black=Чорний +gui.appliedenergistics2.Fluix=Мінливий + +# Waila +waila.appliedenergistics2.Crafting=Створення +waila.appliedenergistics2.DeviceOnline=Пристрій увімкнено +waila.appliedenergistics2.DeviceOffline=Пристрій вимкнено +waila.appliedenergistics2.DeviceMissingChannel=У пристрою відсутній канал +waila.appliedenergistics2.Locked=Заблоковано +waila.appliedenergistics2.Unlocked=Розблоковано +waila.appliedenergistics2.Showing=Показує +waila.appliedenergistics2.Contains=Містить +waila.appliedenergistics2.Channels=%1$d з %2$d каналів +waila.appliedenergistics2.P2PUnlinked=Не пов'язано +waila.appliedenergistics2.P2PInputOneOutput=Пов'язано (вхідна сторона) +waila.appliedenergistics2.P2PInputManyOutputs=Пов'язано (вхідна сторона) - %d виходів +waila.appliedenergistics2.P2POutput=Пов'язано (вихідна сторона) +waila.appliedenergistics2.Booting=Мережа завантажується + +# Items +item.appliedenergistics2.ItemBasicStorageCell.1k.name=1k ME диск зберігання +item.appliedenergistics2.ItemBasicStorageCell.4k.name=4k ME диск зберігання +item.appliedenergistics2.ItemBasicStorageCell.16k.name=16k ME диск зберігання +item.appliedenergistics2.ItemBasicStorageCell.64k.name=64k ME диск зберігання +item.appliedenergistics2.ItemAdvancedStorageCell.256k.name=256k ME диск зберігання +item.appliedenergistics2.ItemAdvancedStorageCell.1024k.name=1024k ME диск зберігання +item.appliedenergistics2.ItemAdvancedStorageCell.4096k.name=4096k ME диск зберігання +item.appliedenergistics2.ItemAdvancedStorageCell.16384k.name=16384k ME диск зберігання +item.appliedenergistics2.ItemExtremeStorageCell.Container.name=ME Диск для збереження блоків +item.appliedenergistics2.ItemExtremeStorageCell.Quantum.name=ME Квантовий диск зберігання +item.appliedenergistics2.ItemExtremeStorageCell.Singularity.name=ME Сингулярний диск зберігання +item.appliedenergistics2.ItemCreativeStorageCell.name=Творча ME диск зберігання +item.appliedenergistics2.ItemVoidStorageCell.name=Пустотний ME диск зберігання +item.appliedenergistics2.ItemEncodedPattern.name=Закодований шаблон +item.appliedenergistics2.ItemViewCell.name=Диск для відображення +item.appliedenergistics2.ItemFacade.name=Кабельний фасад + +item.appliedenergistics2.ItemCrystalSeed.Certus.name=Насіння істинного кварцу +item.appliedenergistics2.ItemCrystalSeed.Nether.name=Насіння пекельного кварцу +item.appliedenergistics2.ItemCrystalSeed.Fluix.name=Насіння мінливого кристалу + +item.appliedenergistics2.ItemPart.InvalidType.name=Вимкнений предмет +item.appliedenergistics2.ItemMaterial.InvalidType.name=Цей предмет вимкнено. + +item.appliedenergistics2.ItemMaterial.BlankPattern.name=Порожній шаблон +item.appliedenergistics2.ItemMaterial.FormationCore.name=Ядро формування +item.appliedenergistics2.ItemMaterial.AnnihilationCore.name=Ядро знищення +item.appliedenergistics2.ItemMaterial.BasicCard.name=Базова карта +item.appliedenergistics2.ItemMaterial.AdvCard.name=Просунута карта + + +item.appliedenergistics2.ItemMaterial.CardCapacity.name=Карта ємності +item.appliedenergistics2.ItemMaterial.CardPatternCapacity.name=Карта ємності шаблонів +item.appliedenergistics2.ItemMaterial.CardFuzzy.name=Нечітка карта +item.appliedenergistics2.ItemMaterial.CardInverter.name=Карта інвертування +item.appliedenergistics2.ItemMaterial.CardRedstone.name=Карта редстоуна +item.appliedenergistics2.ItemMaterial.CardSpeed.name=Карта прискорення +item.appliedenergistics2.ItemMaterial.CardSuperSpeed.name=Карта гіперприскорення +item.appliedenergistics2.ItemMaterial.CardOreFilter.name=Карта фільтрації по словнику руд +item.appliedenergistics2.ItemMaterial.CardPatternRefiller.name=Карта автозавантаження шаблону +item.appliedenergistics2.ItemMaterial.CardAdvancedBlocking.name=Карта просунутого блокування + +item.appliedenergistics2.ItemMaterial.Cell2SpatialPart.name=2³ Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell16SpatialPart.name=16³ Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell128SpatialPart.name=128³ Компонент зберігання + +item.appliedenergistics2.ItemMaterial.Cell1kPart.name=1k ME Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell4kPart.name=4k ME Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell16kPart.name=16k ME Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell64kPart.name=64k ME Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell256kPart.name=256k ME Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell1024kPart.name=1024k ME Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell4096kPart.name=4096k ME Компонент зберігання +item.appliedenergistics2.ItemMaterial.Cell16384kPart.name=16384k ME Компонент зберігання + +item.appliedenergistics2.ItemMaterial.CertusQuartzCrystal.name=Кристал істинного кварцу +item.appliedenergistics2.ItemMaterial.CertusQuartzCrystalCharged.name=Кристал зарядженого істиного кварцу +item.appliedenergistics2.ItemMaterial.CertusQuartzDust.name=Порошок істинного кварцу +item.appliedenergistics2.ItemMaterial.EmptyStorageCell.name=ME Основа диску +item.appliedenergistics2.ItemMaterial.EmptyAdvancedStorageCell.name=ME Просунута основа диску +item.appliedenergistics2.ItemMaterial.EnderDust.name=Порошок Енду + +item.appliedenergistics2.ItemMaterial.Flour.name=Борошно +item.appliedenergistics2.ItemMaterial.FluixCrystal.name=Мінливий кристал +item.appliedenergistics2.ItemMaterial.FluixDust.name=Порошок мінливого кристалу +item.appliedenergistics2.ItemMaterial.FluixPearl.name=Мінлива перлина + +item.appliedenergistics2.ItemMaterial.GoldDust.name=Золотий порошок +item.appliedenergistics2.ItemMaterial.IronDust.name=Залізний порошок +item.appliedenergistics2.ItemMaterial.IronNugget.name=Залізний самородок + + +item.appliedenergistics2.ItemMaterial.MatterBall.name=Куля з матерії +item.appliedenergistics2.ItemMaterial.NetherQuartzDust.name=Порошок пекельного кварцу +item.appliedenergistics2.ItemMaterial.PurifiedCertusQuartzCrystal.name=Чистий істинний кварц +item.appliedenergistics2.ItemMaterial.PurifiedFluixCrystal.name=Чистий мінливий кристал +item.appliedenergistics2.ItemMaterial.PurifiedNetherQuartzCrystal.name=Чистий пекельний кварц +item.appliedenergistics2.ItemMaterial.QESingularity.name=Квантова заплутана сингулярність +item.appliedenergistics2.ItemMaterial.Silicon.name=Кремній +item.appliedenergistics2.ItemMaterial.Singularity.name=Сингулярність +item.appliedenergistics2.ItemMaterial.Wireless.name=Бездротовий приймач +item.appliedenergistics2.ItemMaterial.WirelessBooster.name=Бездротовий підсилювач +item.appliedenergistics2.ItemMaterial.WoodenGear.name=Дерев'яна шестерня + +item.appliedenergistics2.ItemMaterial.NamePress.name=Схема штампа для викарбовування імені +item.appliedenergistics2.ItemMaterial.EngProcessorPress.name=Схема штампа для інженерних елементів +item.appliedenergistics2.ItemMaterial.CalcProcessorPress.name=Схема штампа для розрахункових елементів +item.appliedenergistics2.ItemMaterial.LogicProcessorPress.name=Схема штампа для логічних елементів +item.appliedenergistics2.ItemMaterial.SiliconPress.name=Схема штампа для кремнієвих елементів + +item.appliedenergistics2.ItemMaterial.EngProcessorPrint.name=Штампований інженерний процесор +item.appliedenergistics2.ItemMaterial.CalcProcessorPrint.name=Штампований обчислювальний процесор +item.appliedenergistics2.ItemMaterial.LogicProcessorPrint.name=Штампований логічний процесор +item.appliedenergistics2.ItemMaterial.SiliconPrint.name=Штампований кремній + +item.appliedenergistics2.ItemMaterial.EngProcessor.name=Інженерний процесор +item.appliedenergistics2.ItemMaterial.CalcProcessor.name=Обчислювальний процесор +item.appliedenergistics2.ItemMaterial.LogicProcessor.name=Логічний процесор +item.appliedenergistics2.ItemMaterial.LogicProcessorAsm.name=Незавершений логічний процесор + +item.appliedenergistics2.ItemMaterial.SkyDust.name=Порошок небесного каменю +item.appliedenergistics2.ItemMaterial.CardCrafting.name=Карта створення + +item.appliedenergistics2.ItemPart.FormationPlane.name=ME Площина формування +item.appliedenergistics2.ItemPart.AnnihilationPlane.name=ME Площина руйнування +item.appliedenergistics2.ItemPart.IdentityAnnihilationPlane.name=ME ідентифікуюча площина винищення +item.appliedenergistics2.ItemPart.CableAnchor.name=Кабельний анкер +item.appliedenergistics2.ItemPart.CableCovered.name=ME Покритий кабель +item.appliedenergistics2.ItemPart.CableGlass.name=ME Скляний кабель +item.appliedenergistics2.ItemPart.CableSmart.name=ME Розумний кабель +item.appliedenergistics2.ItemPart.CableDense.name=ME Щільний розумний кабель +item.appliedenergistics2.ItemPart.CableDenseCovered.name=ME Щільний покритий кабель +item.appliedenergistics2.ItemPart.CableUltraDenseCovered.name=ME покритий магістральний кабель +item.appliedenergistics2.ItemPart.CableUltraDenseSmart.name=ME розмуний магістральний кабель +item.appliedenergistics2.ItemPart.StorageMonitor.name=ME Монітор сховища +item.appliedenergistics2.ItemPart.ConversionMonitor.name=ME Монітор перетворення +item.appliedenergistics2.ItemPart.SemiDarkMonitor.name=Освітлювальна панель +item.appliedenergistics2.ItemPart.Monitor.name=Яскрава освітлювальна панель +item.appliedenergistics2.ItemPart.DarkMonitor.name=Темна освітлювальна панель + +item.appliedenergistics2.ItemPart.ExportBus.name=ME-Шина експорту +item.appliedenergistics2.ItemPart.ImportBus.name=МЕ-Шина імпорту +item.appliedenergistics2.ItemPart.Interface.name=ME Інтерфейс +item.appliedenergistics2.ItemPart.LevelEmitter.name=ME Випромінювач рівня енергії +item.appliedenergistics2.ItemPart.P2PTunnel.name=P2P тунель +item.appliedenergistics2.ItemPart.PatternTerminal.name=ME Термінал шаблонів +item.appliedenergistics2.ItemPart.PatternTerminalEx.name=ME Термінал обробки шаблонів +item.appliedenergistics2.ItemPart.QuartzFiber.name=Кварцове волокно +item.appliedenergistics2.ItemPart.StorageBus.name=ME Шина зберігання +item.appliedenergistics2.ItemPart.Terminal.name=ME Термінал +item.appliedenergistics2.ItemPart.CraftingTerminal.name=ME Термінал створення +item.appliedenergistics2.ItemPart.InterfaceTerminal.name=ME Термінал інтерфейсу +item.appliedenergistics2.ItemPart.InvertedToggleBus.name=МЕ інвертована шина перемикання +item.appliedenergistics2.ItemPart.ToggleBus.name=МЕ шина перемикання +item.appliedenergistics2.ItemPart.CraftingMonitor.name=ME Монітор створення + +item.appliedenergistics2.ItemSpatialStorageCell.128Cubed.name=128³ диск зберігання простору +item.appliedenergistics2.ItemSpatialStorageCell.16Cubed.name=16³ диск зберігання простору +item.appliedenergistics2.ItemSpatialStorageCell.2Cubed.name=2³ диск зберігання простору + +item.appliedenergistics2.ToolCertusQuartzAxe.name=Сокира істинного кварцу +item.appliedenergistics2.ToolCertusQuartzCuttingKnife.name=Ніж істинного кварцу +item.appliedenergistics2.ToolCertusQuartzHoe.name=Мотика істинного кварцу +item.appliedenergistics2.ToolCertusQuartzPickaxe.name=Кайло істинного кварцу +item.appliedenergistics2.ToolCertusQuartzSpade.name=Лопата істинного кварцу +item.appliedenergistics2.ToolCertusQuartzSword.name=Меч істинного кварцу +item.appliedenergistics2.ToolCertusQuartzWrench.name=Ключ істинного кварцу + +item.appliedenergistics2.ToolNetherQuartzAxe.name=Сокира пекельного кварцу +item.appliedenergistics2.ToolNetherQuartzCuttingKnife.name=Ніж пекельного кварцу +item.appliedenergistics2.ToolNetherQuartzHoe.name=Мотика пекельного кварцу +item.appliedenergistics2.ToolNetherQuartzPickaxe.name=Кайло пекельного кварцу +item.appliedenergistics2.ToolNetherQuartzSpade.name=Лопата пекельного кварцу +item.appliedenergistics2.ToolNetherQuartzSword.name=Меч пекельного кварцу +item.appliedenergistics2.ToolNetherQuartzWrench.name=Ключ пекельного кварцу + +item.appliedenergistics2.ItemPaintBall.name=Кулька з фарбою +item.appliedenergistics2.ToolPortableCell.name=Портативний диск +item.appliedenergistics2.ToolNetworkTool.name=Мережевий інструмент +item.appliedenergistics2.ToolChargedStaff.name=Жезл заряджання +item.appliedenergistics2.ToolEntropyManipulator.name=Маніпулятор ентропії +item.appliedenergistics2.ToolMassCannon.name=Матеріальна пушка +item.appliedenergistics2.ToolMemoryCard.name=Карта пам'яті +item.appliedenergistics2.ToolColorApplicator.name=Аплікатор кольорів +item.appliedenergistics2.ToolWirelessTerminal.name=Бездротовий термінал +item.appliedenergistics2.ToolBiometricCard.name=Біометрична карта + +item.appliedenergistics2.ToolDebugCard.name=Творча.Карта відлагодження +item.appliedenergistics2.ToolReplicatorCard.name=Творча.Карта реплікації + +# Commands +commands.ae2.usage=Команди надані Applied Energistics 2 - використовуйте /ae2 list для списку та /ae2 help _____ для допомоги. +commands.ae2.permissions=Ви не маєте прав для виконання цієї команди. +commands.ae2.ChunkLogger=Перемикає завантаження та вивантаження чанків у журнал сервера. (ОП) +commands.ae2.ChunkLoggerOn=Ведення журналу чанків увімкнено +commands.ae2.ChunkLoggerOff=Ведення журналу чанків вимкнено +commands.ae2.Supporters=Відображає список прибічників AE2 +commands.ae2.Profiler=Команда профілювання сітки, передайте якогось Tile в сітці, щоб почати/зупинити профілювання +commands.ae2.ProfilerStart=Профілювання почато +commands.ae2.ProfilerFailed=Немає AE Tile тут +commands.ae2.ProfilerGridDown=Ця мережа вимкнена +commands.ae2.ProfilerStop=Середня кількість наносекунд, які займає ця мережа за такт: +commands.ae2.ProfilerFailedDim=Нема такого виміру +commands.ae2.ToggleFullAccess=Перемкнути повний доступ ОП AE, ігноруючи налаштування терміналу безпеки +commands.ae2.ToggleDebugTiming=Перемкнути ведення журналу менджера відлагодження Tick +commands.ae2.ToggleDebugPathfinding=Перемкнути пошук шляху журналу відлагодження + +# Achievements +achievement.ae2.Compass=Мисливець за метеоритами +achievement.ae2.Compass.desc=Зробіть метеоритний компас +achievement.ae2.Presses=Невідома технологія +achievement.ae2.Presses.desc=Знайдіть прес процесора +achievement.ae2.SpatialIO=Просторова координація +achievement.ae2.SpatialIO.desc=Створіть просторовий порт вводу-виводу +achievement.ae2.SpatialIOExplorer=Щоб сміливо йти +achievement.ae2.SpatialIOExplorer.desc=Зберігаються в просторовій камері +achievement.ae2.StorageCell=Краще, ніж скрині +achievement.ae2.StorageCell.desc=Зробіть комірку для зберігання +achievement.ae2.IOPort=Перетасувати комірки зберігання +achievement.ae2.IOPort.desc=Створіть порт вводу-виводу +achievement.ae2.CraftingTerminal=Більший (Набагато) стіл +achievement.ae2.CraftingTerminal.desc=Створіть термінал створення +achievement.ae2.PatternTerminal=Маестро створення +achievement.ae2.PatternTerminal.desc=Створіть термінал шаблонів +achievement.ae2.ChargedQuartz=Розряд +achievement.ae2.ChargedQuartz.desc=Знайдіть заряджений кварц +achievement.ae2.Fluix=Неприродне +achievement.ae2.Fluix.desc=Створюйте мінливі кристали +achievement.ae2.Charger=Створення мінливого +achievement.ae2.Charger.desc=Зробіть зарядний пристрій +achievement.ae2.CrystalGrowthAccelerator=Прискорювач – це стриманність +achievement.ae2.CrystalGrowthAccelerator.desc=Створіть прискорювач росту кристалів +achievement.ae2.GlassCable=Мінливе енергетичне підключення +achievement.ae2.GlassCable.desc=Зробіть ME скляний кабель +achievement.ae2.Networking1=Мережевий початківець +achievement.ae2.Networking1.desc=Використайте 8 каналів за допомогою пристроїв у мережі. +achievement.ae2.Controller=Мережевий комутатор +achievement.ae2.Controller.desc=Зробіть контроллер +achievement.ae2.Networking2=Мережевий інженер +achievement.ae2.Networking2.desc=Використайте 128 каналів за допомогою пристроїв у мережі. +achievement.ae2.Networking3=Мережевий адміністратор +achievement.ae2.Networking3.desc=Використайте 2048 каналів за допомогою пристроїв у мережі. +achievement.ae2.P2P=Мережа точка-точка +achievement.ae2.P2P.desc=Створіть тунель P2P +achievement.ae2.Recursive=Рекурсивна мережа +achievement.ae2.Recursive.desc=Розмістіть на інтерфейс шину зберігання. +achievement.ae2.CraftingCPU=Крафт нового покоління +achievement.ae2.CraftingCPU.desc=Створіть блок створення +achievement.ae2.Facade=Мережева естетика +achievement.ae2.Facade.desc=Створіть кабельний фасад +achievement.ae2.NetworkTool=Діагностика мережі +achievement.ae2.NetworkTool.desc=Створіть мережевий інструмент +achievement.ae2.PortableCell=Кочовий диск +achievement.ae2.PortableCell.desc=Створіть портативний диск +achievement.ae2.StorageBus=Безмежний потенціал +achievement.ae2.StorageBus.desc=Зробіть шину зберіганн +achievement.ae2.QNB=Квантове тунелювання +achievement.ae2.QNB.desc=Зробіть квантовий зв'язок + +# Stats +stat.ae2.ItemsInserted=Збережено предметів в ME-Сховище +stat.ae2.ItemsExtracted=Витягнуто предметів з ME-Сховища +stat.ae2.TurnedCranks=Зламано рукояток + +# Keys +key.appliedenergistics2.category=Applied Energistics 2 +key.toggle_focus.desc=Перемкнути фокус вікна пошуку From 597a078fac9a260d9e5edf129616f66f4c600b77 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Fri, 3 Nov 2023 20:04:58 +0800 Subject: [PATCH 18/34] back roll some commits --- .../api/networking/ICellCacheHandler.java | 21 +++++++ .../gui/implementations/GuiNetworkStatus.java | 29 +++++++--- .../ContainerNetworkStatus.java | 52 +++++++++++++++--- .../appeng/core/localization/GuiText.java | 8 +-- .../appeng/me/cache/GridStorageCache.java | 37 +++++++++++-- .../me/storage/CellInventoryHandler.java | 38 ++++++++++++- .../appliedenergistics2/lang/en_US.lang | 6 +- .../appliedenergistics2/lang/zh_CN.lang | 6 +- .../appliedenergistics2/lang/zh_TW.lang | 4 ++ .../textures/guis/networkstatus.png | Bin 2721 -> 2929 bytes 10 files changed, 170 insertions(+), 31 deletions(-) create mode 100644 src/main/java/appeng/api/networking/ICellCacheHandler.java diff --git a/src/main/java/appeng/api/networking/ICellCacheHandler.java b/src/main/java/appeng/api/networking/ICellCacheHandler.java new file mode 100644 index 00000000000..b6946f78843 --- /dev/null +++ b/src/main/java/appeng/api/networking/ICellCacheHandler.java @@ -0,0 +1,21 @@ +package appeng.api.networking; + +import appeng.api.storage.StorageChannel; + +public interface ICellCacheHandler { + + long getTotalBytes(); + + long getFreeBytes(); + + long getUsedBytes(); + + long getTotalTypes(); + + long getFreeTypes(); + + long getUsedTypes(); + + StorageChannel getCellType(); + +} diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index c0475eab8e8..fe508d65f89 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -141,25 +141,40 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final 13, 143 - 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); + // Item byte status this.fontRendererObj.drawString( - GuiText.ByteTotal.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesTotal()), + GuiText.Items.getLocal() + ": " + + Platform.formatByteLong(ns.getItemBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getItemBytesTotal()) + + " (" + + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + + "%)", 13, 143, GuiColors.NetworkStatusPowerUsageRate.getColor()); + + // Fluid byte status this.fontRendererObj.drawString( - GuiText.ByteUsage.getLocal() + ": " - + Platform.formatByteLong(ns.getItemBytesUsed()) + GuiText.Fluids.getLocal() + ": " + + Platform.formatByteLong(ns.getFluidBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getFluidBytesTotal()) + " (" - + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) + "%)", 13, 143 + 10, GuiColors.NetworkStatusPowerUsageRate.getColor()); + + // Essential byte status this.fontRendererObj.drawString( - GuiText.ByteFree.getLocal() + ": " - + Platform.formatByteLong(ns.getItemBytesFree()) + GuiText.Essentias.getLocal() + ": " + + Platform.formatByteLong(ns.getEssentiaBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getEssentiaBytesTotal()) + " (" - + df.format(ns.getItemBytesFree() * 100d / ns.getItemBytesTotal()) + + df.format(ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal()) + "%)", 13, 143 + 20, diff --git a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java index 2ae47f02954..22f44225f63 100644 --- a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java +++ b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java @@ -58,7 +58,16 @@ public class ContainerNetworkStatus extends AEBaseContainer { public long itemBytesUsed; @GuiSync(6) - public long itemBytesFree; + public long fluidBytesTotal; + + @GuiSync(7) + public long fluidBytesUsed; + + @GuiSync(8) + public long essentiaBytesTotal; + + @GuiSync(9) + public long essentiaBytesUsed; private IGrid network; private int delay = 40; @@ -136,7 +145,10 @@ public void detectAndSendChanges() { if (sg != null) { this.setItemBytesTotal(sg.getItemBytesTotal()); this.setItemBytesUsed(sg.getItemBytesUsed()); - this.setItemBytesFree(this.getItemBytesTotal() - this.getItemBytesUsed()); + this.setFluidBytesTotal(sg.getFluidBytesTotal()); + this.setFluidBytesUsed(sg.getFluidBytesUsed()); + this.setEssentiaBytesTotal(sg.getEssentiaBytesTotal()); + this.setEssentiaBytesUsed(sg.getEssentiaBytesUsed()); } } super.detectAndSendChanges(); @@ -182,10 +194,6 @@ public long getItemBytesUsed() { return this.itemBytesUsed; } - public long getItemBytesFree() { - return this.itemBytesFree; - } - public void setItemBytesTotal(final long itemBytesTotal) { this.itemBytesTotal = itemBytesTotal; } @@ -194,7 +202,35 @@ public void setItemBytesUsed(final long itemBytesUsed) { this.itemBytesUsed = itemBytesUsed; } - public void setItemBytesFree(final long itemBytesFree) { - this.itemBytesFree = itemBytesFree; + public long getFluidBytesTotal() { + return this.fluidBytesTotal; + } + + public long getFluidBytesUsed() { + return this.fluidBytesUsed; + } + + public void setFluidBytesTotal(final long fluidBytesTotal) { + this.fluidBytesTotal = fluidBytesTotal; + } + + public void setFluidBytesUsed(final long fluidBytesUsed) { + this.fluidBytesUsed = fluidBytesUsed; + } + + public long getEssentiaBytesTotal() { + return essentiaBytesTotal; + } + + public long getEssentiaBytesUsed() { + return essentiaBytesUsed; + } + + public void setEssentiaBytesTotal(long essentiaBytesTotal) { + this.essentiaBytesTotal = essentiaBytesTotal; + } + + public void setEssentiaBytesUsed(long essentiaBytesUsed) { + this.essentiaBytesUsed = essentiaBytesUsed; } } diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index abe2b8f0f66..bac6ba14825 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -207,10 +207,10 @@ public enum GuiText { // If a thing is deprecated Deprecated, - // mine - ByteTotal, - ByteUsage, - ByteFree; + // Network bytes status + Items, + Fluids, + Essentias; private final String root; diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index ce44ecf94c5..996bc8f87cc 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -64,6 +64,10 @@ public class GridStorageCache implements IStorageGrid { private NetworkInventoryHandler myFluidNetwork; private long itemBytesTotal; private long itemBytesUsed; + private long fluidBytesTotal; + private long fluidBytesUsed; + private long essentiaBytesTotal; + private long essentiaBytesUsed; private int ticksCount; private int networkBytesUpdateFrequency; @@ -353,6 +357,10 @@ public void applyChanges() { private void updateBytesInfo() { this.itemBytesTotal = 0; this.itemBytesUsed = 0; + this.fluidBytesTotal = 0; + this.fluidBytesUsed = 0; + this.essentiaBytesTotal = 0; + this.essentiaBytesUsed = 0; try { for (ICellProvider icp : this.activeCellProviders) { if (icp instanceof TileDrive) { @@ -365,24 +373,43 @@ private void updateBytesInfo() { // exclude creative cell if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { if (handler.getCellInv() != null) { - itemBytesTotal += handler.getCellInv().getTotalBytes(); - itemBytesUsed += handler.getCellInv().getUsedBytes(); + itemBytesTotal += handler.getTotalBytes(); + itemBytesUsed += handler.getUsedBytes(); } } } + //TODO + for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { + + } } } } catch (Exception e) { // XD Normally won't be here, just normally.. } } - public long getItemBytesTotal() { - return this.itemBytesTotal; + return itemBytesTotal; } public long getItemBytesUsed() { - return this.itemBytesUsed; + return itemBytesUsed; + } + + public long getFluidBytesTotal() { + return fluidBytesTotal; + } + + public long getFluidBytesUsed() { + return fluidBytesUsed; + } + + public long getEssentiaBytesTotal() { + return essentiaBytesTotal; + } + + public long getEssentiaBytesUsed() { + return essentiaBytesUsed; } } diff --git a/src/main/java/appeng/me/storage/CellInventoryHandler.java b/src/main/java/appeng/me/storage/CellInventoryHandler.java index 77e4d29243a..8f98d4cbbfd 100644 --- a/src/main/java/appeng/me/storage/CellInventoryHandler.java +++ b/src/main/java/appeng/me/storage/CellInventoryHandler.java @@ -18,6 +18,7 @@ import appeng.api.config.IncludeExclude; import appeng.api.config.Upgrades; import appeng.api.implementations.items.IUpgradeModule; +import appeng.api.networking.ICellCacheHandler; import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.IMEInventory; @@ -29,7 +30,7 @@ import appeng.util.prioitylist.OreFilteredList; import appeng.util.prioitylist.PrecisePriorityList; -public class CellInventoryHandler extends MEInventoryHandler implements ICellInventoryHandler { +public class CellInventoryHandler extends MEInventoryHandler implements ICellInventoryHandler, ICellCacheHandler{ CellInventoryHandler(final IMEInventory c) { super(c, StorageChannel.ITEMS); @@ -116,4 +117,39 @@ public int getStatusForCell() { return val; } + + @Override + public long getTotalBytes() { + return this.getCellInv().getTotalBytes(); + } + + @Override + public long getFreeBytes() { + return this.getCellInv().getFreeBytes(); + } + + @Override + public long getUsedBytes() { + return this.getCellInv().getUsedBytes(); + } + + @Override + public long getTotalTypes() { + return this.getCellInv().getTotalItemTypes(); + } + + @Override + public long getFreeTypes() { + return this.getCellInv().getRemainingItemTypes(); + } + + @Override + public long getUsedTypes() { + return this.getCellInv().getStoredItemTypes(); + } + + @Override + public StorageChannel getCellType() { + return StorageChannel.ITEMS; + } } diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index feb44c80672..1163c5ac9c0 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -272,9 +272,9 @@ gui.appliedenergistics2.Nothing=Nothing gui.appliedenergistics2.VoidCellTooltip=Deletes §4everything§7 stored on it gui.appliedenergistics2.Deprecated=Deprecated, will be removed soon! -gui.appliedenergistics2.ByteTotal=Bytes Total -gui.appliedenergistics2.ByteUsage=Bytes Used -gui.appliedenergistics2.ByteFree=Bytes Free +gui.appliedenergistics2.Items=Items +gui.appliedenergistics2.Fluids=Fluids +gui.appliedenergistics2.Essentias=Essen # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 156fedaada6..9350785b116 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -265,9 +265,9 @@ gui.appliedenergistics2.HoldShiftClick_HIGHLIGHT_INTERFACE=shift点击,高亮ME gui.appliedenergistics2.VoidCellTooltip=删除§任何§7存储在里面的物品 gui.appliedenergistics2.Nothing=无 -gui.appliedenergistics2.ByteTotal=所有字节 -gui.appliedenergistics2.ByteUsage=已用字节 -gui.appliedenergistics2.ByteFree=剩余字节 +gui.appliedenergistics2.Items=物品 +gui.appliedenergistics2.Fluids=流体 +gui.appliedenergistics2.Essentias=源质 # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang index 63fb6a97a3f..224551adfa5 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang @@ -184,6 +184,10 @@ gui.appliedenergistics2.CalculatingWait=正在計算,請等待... gui.appliedenergistics2.Clean=清空 gui.appliedenergistics2.InvalidPattern=無效樣板 +gui.appliedenergistics2.Items=物品 +gui.appliedenergistics2.Fluids=流體 +gui.appliedenergistics2.Essentias=源質 + gui.tooltips.appliedenergistics2.Stash=存儲物品 gui.tooltips.appliedenergistics2.StashDesc=將合成槽的物品返回網絡 gui.tooltips.appliedenergistics2.Substitutions=礦物詞典替換 diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png b/src/main/resources/assets/appliedenergistics2/textures/guis/networkstatus.png index b1f38e0c21798ed6a8940ad7893f5109e8b21cf5..185bdc36f77e87a2dac3e599afa0c757cbff858e 100644 GIT binary patch delta 183 zcmZ1|`cZ6x1rxjSMyoC+UPE02;}An5D-&}oQ{%}OnH11O{xJop7+R#5Stg~L>6%%X zn(7)Eni%UQ85s% FECAmf5kmj~ From ce9efceba55bcd757dc7be042a392a4be5351a62 Mon Sep 17 00:00:00 2001 From: MCTBL <30978504+MCTBL@users.noreply.github.com> Date: Fri, 3 Nov 2023 23:03:18 +0800 Subject: [PATCH 19/34] delete incorrect import and depends delete non compliant depends --- dependencies.gradle | 2 -- src/main/java/appeng/me/cache/GridStorageCache.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 80ba0962c38..f0f0f9dfdb0 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,8 +3,6 @@ dependencies { implementation('com.github.GTNewHorizons:NotEnoughItems:2.4.6-GTNH:dev') implementation('curse.maven:cofh-core-69162:2388751') - compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.4.13-GTNH:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:AE2FluidCraft-Rework:1.1.42-gtnh:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.36:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:ForgeMultipart:1.3.4:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.73:dev') {transitive = false} diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 8974145df9d..26845f0f907 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -15,7 +15,6 @@ import java.util.LinkedList; import java.util.List; -import com.glodblock.github.common.storage.FluidCellInventoryHandler; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; @@ -51,7 +50,6 @@ import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.VoidCellInventory; import appeng.tile.storage.TileDrive; -import thaumicenergistics.common.inventory.HandlerItemEssentiaCell; public class GridStorageCache implements IStorageGrid { From bb1f4ec439006427f1d243f65ac6314ec005cfd9 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Sat, 4 Nov 2023 02:09:40 +0800 Subject: [PATCH 20/34] Change interface's name --- .../api/networking/ICellCacheHandler.java | 21 ------ .../api/storage/ICellCacheRegistry.java | 29 ++++++++ .../appeng/me/cache/GridStorageCache.java | 6 +- .../me/storage/CellInventoryHandler.java | 73 ++++++++++--------- 4 files changed, 69 insertions(+), 60 deletions(-) delete mode 100644 src/main/java/appeng/api/networking/ICellCacheHandler.java create mode 100644 src/main/java/appeng/api/storage/ICellCacheRegistry.java diff --git a/src/main/java/appeng/api/networking/ICellCacheHandler.java b/src/main/java/appeng/api/networking/ICellCacheHandler.java deleted file mode 100644 index b6946f78843..00000000000 --- a/src/main/java/appeng/api/networking/ICellCacheHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package appeng.api.networking; - -import appeng.api.storage.StorageChannel; - -public interface ICellCacheHandler { - - long getTotalBytes(); - - long getFreeBytes(); - - long getUsedBytes(); - - long getTotalTypes(); - - long getFreeTypes(); - - long getUsedTypes(); - - StorageChannel getCellType(); - -} diff --git a/src/main/java/appeng/api/storage/ICellCacheRegistry.java b/src/main/java/appeng/api/storage/ICellCacheRegistry.java new file mode 100644 index 00000000000..4cead30561a --- /dev/null +++ b/src/main/java/appeng/api/storage/ICellCacheRegistry.java @@ -0,0 +1,29 @@ +package appeng.api.storage; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public interface ICellCacheRegistry { + + @SideOnly(Side.CLIENT) + long getTotalBytes(); + + @SideOnly(Side.CLIENT) + long getFreeBytes(); + + @SideOnly(Side.CLIENT) + long getUsedBytes(); + + @SideOnly(Side.CLIENT) + long getTotalTypes(); + + @SideOnly(Side.CLIENT) + long getFreeTypes(); + + @SideOnly(Side.CLIENT) + long getUsedTypes(); + + @SideOnly(Side.CLIENT) + StorageChannel getCellType(); + +} diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 26845f0f907..31a592dd30b 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -46,7 +46,6 @@ import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.DriveWatcher; import appeng.me.storage.ItemWatcher; -import appeng.me.storage.MEInventoryHandler; import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.VoidCellInventory; import appeng.tile.storage.TileDrive; @@ -379,9 +378,9 @@ private void updateBytesInfo() { } } } - //TODO + // TODO for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { - + } } } @@ -389,6 +388,7 @@ private void updateBytesInfo() { // XD Normally won't be here, just normally.. } } + public long getItemBytesTotal() { return itemBytesTotal; } diff --git a/src/main/java/appeng/me/storage/CellInventoryHandler.java b/src/main/java/appeng/me/storage/CellInventoryHandler.java index 8f98d4cbbfd..3df1976fb21 100644 --- a/src/main/java/appeng/me/storage/CellInventoryHandler.java +++ b/src/main/java/appeng/me/storage/CellInventoryHandler.java @@ -18,7 +18,7 @@ import appeng.api.config.IncludeExclude; import appeng.api.config.Upgrades; import appeng.api.implementations.items.IUpgradeModule; -import appeng.api.networking.ICellCacheHandler; +import appeng.api.storage.ICellCacheRegistry; import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.IMEInventory; @@ -30,7 +30,8 @@ import appeng.util.prioitylist.OreFilteredList; import appeng.util.prioitylist.PrecisePriorityList; -public class CellInventoryHandler extends MEInventoryHandler implements ICellInventoryHandler, ICellCacheHandler{ +public class CellInventoryHandler extends MEInventoryHandler + implements ICellInventoryHandler, ICellCacheRegistry { CellInventoryHandler(final IMEInventory c) { super(c, StorageChannel.ITEMS); @@ -118,38 +119,38 @@ public int getStatusForCell() { return val; } - @Override - public long getTotalBytes() { - return this.getCellInv().getTotalBytes(); - } - - @Override - public long getFreeBytes() { - return this.getCellInv().getFreeBytes(); - } - - @Override - public long getUsedBytes() { - return this.getCellInv().getUsedBytes(); - } - - @Override - public long getTotalTypes() { - return this.getCellInv().getTotalItemTypes(); - } - - @Override - public long getFreeTypes() { - return this.getCellInv().getRemainingItemTypes(); - } - - @Override - public long getUsedTypes() { - return this.getCellInv().getStoredItemTypes(); - } - - @Override - public StorageChannel getCellType() { - return StorageChannel.ITEMS; - } + @Override + public long getTotalBytes() { + return this.getCellInv().getTotalBytes(); + } + + @Override + public long getFreeBytes() { + return this.getCellInv().getFreeBytes(); + } + + @Override + public long getUsedBytes() { + return this.getCellInv().getUsedBytes(); + } + + @Override + public long getTotalTypes() { + return this.getCellInv().getTotalItemTypes(); + } + + @Override + public long getFreeTypes() { + return this.getCellInv().getRemainingItemTypes(); + } + + @Override + public long getUsedTypes() { + return this.getCellInv().getStoredItemTypes(); + } + + @Override + public StorageChannel getCellType() { + return StorageChannel.ITEMS; + } } From a8334bafac84d4818ecb780992e4946d19b9a1f4 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Sat, 4 Nov 2023 22:59:05 +0800 Subject: [PATCH 21/34] Remove wrong annotations --- .../appeng/api/storage/ICellCacheRegistry.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/appeng/api/storage/ICellCacheRegistry.java b/src/main/java/appeng/api/storage/ICellCacheRegistry.java index 4cead30561a..75c57585282 100644 --- a/src/main/java/appeng/api/storage/ICellCacheRegistry.java +++ b/src/main/java/appeng/api/storage/ICellCacheRegistry.java @@ -1,29 +1,23 @@ package appeng.api.storage; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - +/** + * For {@link appeng.me.storage.CellInventoryHandler}(or FluidCellInventoryHandler in AE2FC) to easily get bytes + * informations + */ public interface ICellCacheRegistry { - @SideOnly(Side.CLIENT) long getTotalBytes(); - @SideOnly(Side.CLIENT) long getFreeBytes(); - @SideOnly(Side.CLIENT) long getUsedBytes(); - @SideOnly(Side.CLIENT) long getTotalTypes(); - @SideOnly(Side.CLIENT) long getFreeTypes(); - @SideOnly(Side.CLIENT) long getUsedTypes(); - @SideOnly(Side.CLIENT) StorageChannel getCellType(); } From df8b2b38d7f6ef05e04b14b2143e006fbe17eb52 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Mon, 6 Nov 2023 03:30:07 +0800 Subject: [PATCH 22/34] Add new AdvancedNetworkTool only text and texture, wait to implement the actual functions. --- .../java/appeng/api/definitions/IItems.java | 2 + .../appeng/core/api/definitions/ApiItems.java | 8 ++ .../java/appeng/core/features/AEFeature.java | 2 + .../appeng/core/localization/GuiText.java | 1 + .../items/tools/ToolAdvancedNetworkTool.java | 108 ++++++++++++++++++ .../appliedenergistics2/lang/en_US.lang | 1 + .../appliedenergistics2/lang/zh_CN.lang | 1 + .../appliedenergistics2/lang/zh_TW.lang | 1 + .../items/ToolAdvancedNetworkTool.png | Bin 0 -> 1854 bytes 9 files changed, 124 insertions(+) create mode 100644 src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java create mode 100644 src/main/resources/assets/appliedenergistics2/textures/items/ToolAdvancedNetworkTool.png diff --git a/src/main/java/appeng/api/definitions/IItems.java b/src/main/java/appeng/api/definitions/IItems.java index d71b8595ebc..087ba560e1a 100644 --- a/src/main/java/appeng/api/definitions/IItems.java +++ b/src/main/java/appeng/api/definitions/IItems.java @@ -62,6 +62,8 @@ public interface IItems { IItemDefinition networkTool(); + IItemDefinition advancedNetworkTool(); + IItemDefinition portableCell(); IItemDefinition cellCreative(); diff --git a/src/main/java/appeng/core/api/definitions/ApiItems.java b/src/main/java/appeng/core/api/definitions/ApiItems.java index 4c1140fdc80..8ba7c8958e9 100644 --- a/src/main/java/appeng/core/api/definitions/ApiItems.java +++ b/src/main/java/appeng/core/api/definitions/ApiItems.java @@ -30,6 +30,7 @@ import appeng.items.storage.ItemSpatialStorageCell; import appeng.items.storage.ItemViewCell; import appeng.items.storage.ItemVoidStorageCell; +import appeng.items.tools.ToolAdvancedNetworkTool; import appeng.items.tools.ToolBiometricCard; import appeng.items.tools.ToolMemoryCard; import appeng.items.tools.ToolNetworkTool; @@ -75,6 +76,7 @@ public final class ApiItems implements IItems { private final IItemDefinition massCannon; private final IItemDefinition memoryCard; private final IItemDefinition networkTool; + private final IItemDefinition advancedNetworkTool; private final IItemDefinition portableCell; private final IItemDefinition cellCreative; @@ -140,6 +142,7 @@ public ApiItems(final DefinitionConstructor constructor) { this.massCannon = constructor.registerItemDefinition(new ToolMassCannon()); this.memoryCard = constructor.registerItemDefinition(new ToolMemoryCard()); this.networkTool = constructor.registerItemDefinition(new ToolNetworkTool()); + this.advancedNetworkTool = constructor.registerItemDefinition(new ToolAdvancedNetworkTool()); this.portableCell = constructor.registerItemDefinition(new ToolPortableCell()); this.cellCreative = constructor.registerItemDefinition(new ItemCreativeStorageCell()); @@ -291,6 +294,11 @@ public IItemDefinition networkTool() { return this.networkTool; } + @Override + public IItemDefinition advancedNetworkTool() { + return this.advancedNetworkTool; + } + @Override public IItemDefinition portableCell() { return this.portableCell; diff --git a/src/main/java/appeng/core/features/AEFeature.java b/src/main/java/appeng/core/features/AEFeature.java index d289a990ee1..03a27807f16 100644 --- a/src/main/java/appeng/core/features/AEFeature.java +++ b/src/main/java/appeng/core/features/AEFeature.java @@ -82,6 +82,7 @@ public boolean isVisible() { IOPort(Constants.CATEGORY_STORAGE), NetworkTool(Constants.CATEGORY_NETWORK_TOOL), + AdvancedNetworkTool(Constants.CATEGORY_ADVANCED_NETWORK_TOOL), DenseEnergyCells(Constants.CATEGORY_HIGHER_CAPACITY), DenseCables(Constants.CATEGORY_HIGHER_CAPACITY), @@ -174,6 +175,7 @@ private enum Constants { private static final String CATEGORY_RENDERING = "Rendering"; private static final String CATEGORY_FACADES = "Facades"; private static final String CATEGORY_NETWORK_TOOL = "NetworkTool"; + private static final String CATEGORY_ADVANCED_NETWORK_TOOL = "AdvancedNetworkTool"; private static final String CATEGORY_PORTABLE_CELL = "PortableCell"; } } diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index bac6ba14825..ca55278d253 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -49,6 +49,7 @@ public enum GuiText { PortableCell, NetworkTool, + AdvancedNetworkTool, PowerUsageRate, PowerInputRate, Installed, diff --git a/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java new file mode 100644 index 00000000000..650d74a61b9 --- /dev/null +++ b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java @@ -0,0 +1,108 @@ +package appeng.items.tools; + +import java.util.EnumSet; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; + +import com.google.common.base.Optional; + +import appeng.api.implementations.guiobjects.IGuiItem; +import appeng.api.implementations.guiobjects.IGuiItemObject; +import appeng.api.implementations.items.IAEWrench; +import appeng.api.networking.IGridHost; +import appeng.client.ClientHelper; +import appeng.core.features.AEFeature; +import appeng.integration.IntegrationType; +import appeng.items.AEBaseItem; +import appeng.items.contents.NetworkToolViewer; +import appeng.transformer.annotations.Integration.Interface; +import appeng.transformer.annotations.Integration.InterfaceList; +import appeng.util.Platform; +import buildcraft.api.tools.IToolWrench; +import cofh.api.item.IToolHammer; + +@InterfaceList( + value = { @Interface(iface = "cofh.api.item.IToolHammer", iname = IntegrationType.CoFHWrench), + @Interface(iface = "buildcraft.api.tools.IToolWrench", iname = IntegrationType.BuildCraftCore) }) +public class ToolAdvancedNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench, IToolWrench, IToolHammer { + + public ToolAdvancedNetworkTool() { + super(Optional.absent()); + + this.setFeature(EnumSet.of(AEFeature.AdvancedNetworkTool)); + this.setMaxStackSize(1); + this.setHarvestLevel("wrench", 0); + } + + @Override + public ItemStack onItemRightClick(final ItemStack it, final World w, final EntityPlayer p) { + if (Platform.isClient()) { + final MovingObjectPosition mop = ClientHelper.proxy.getMOP(); + + if (mop == null) { + this.onItemUseFirst(it, p, w, 0, 0, 0, -1, 0, 0, 0); + } else { + final int i = mop.blockX; + final int j = mop.blockY; + final int k = mop.blockZ; + + if (w.getBlock(i, j, k).isAir(w, i, j, k)) { + this.onItemUseFirst(it, p, w, 0, 0, 0, -1, 0, 0, 0); + } + } + } + + return it; + } + + @Override + public boolean onItemUseFirst(final ItemStack is, final EntityPlayer player, final World world, final int x, + final int y, final int z, final int side, final float hitX, final float hitY, final float hitZ) { + // TODO + + return true; + } + + @Override + public boolean doesSneakBypassUse(final World world, final int x, final int y, final int z, + final EntityPlayer player) { + return true; + } + + @Override + public boolean canWrench(final ItemStack is, final EntityPlayer player, final int x, final int y, final int z) { + return true; + } + + @Override + public boolean canWrench(final EntityPlayer player, final int x, final int y, final int z) { + return true; + } + + @Override + public void wrenchUsed(final EntityPlayer player, final int x, final int y, final int z) { + player.swingItem(); + } + + @Override + public boolean isUsable(ItemStack itemStack, EntityLivingBase entityLivingBase, int x, int y, int z) { + return true; + } + + @Override + public void toolUsed(ItemStack itemStack, EntityLivingBase entity, int x, int y, int z) { + entity.swingItem(); + } + + @Override + public IGuiItemObject getGuiObject(final ItemStack is, final World world, final int x, final int y, final int z) { + final TileEntity te = world.getTileEntity(x, y, z); + return new NetworkToolViewer(is, (IGridHost) (te instanceof IGridHost ? te : null)); + } + +} diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 1163c5ac9c0..975bbfa2c78 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -654,6 +654,7 @@ item.appliedenergistics2.ToolNetherQuartzWrench.name=Nether Quartz Wrench item.appliedenergistics2.ItemPaintBall.name=Paint Ball item.appliedenergistics2.ToolPortableCell.name=Portable Cell item.appliedenergistics2.ToolNetworkTool.name=Network Tool +item.appliedenergistics2.ToolAdvancedNetworkTool.name=Advanced Network Tool item.appliedenergistics2.ToolChargedStaff.name=Charged Staff item.appliedenergistics2.ToolEntropyManipulator.name=Entropy Manipulator item.appliedenergistics2.ToolMassCannon.name=Matter Cannon diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 9350785b116..8ce27292d69 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -618,6 +618,7 @@ item.appliedenergistics2.ToolNetherQuartzWrench.name=下界石英扳手 item.appliedenergistics2.ItemPaintBall.name=染色球 item.appliedenergistics2.ToolPortableCell.name=便携元件 item.appliedenergistics2.ToolNetworkTool.name=网络工具 +item.appliedenergistics2.ToolAdvancedNetworkTool.name=高级网络工具 item.appliedenergistics2.ToolChargedStaff.name=充能手杖 item.appliedenergistics2.ToolEntropyManipulator.name=熵变机械臂 item.appliedenergistics2.ToolMassCannon.name=物质炮 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang index 03e3aa72c7c..825693c772e 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang @@ -418,6 +418,7 @@ item.appliedenergistics2.ToolNetherQuartzWrench.name=下界石英扳手 item.appliedenergistics2.ItemPaintBall.name=染色球 item.appliedenergistics2.ToolPortableCell.name=便攜元件 item.appliedenergistics2.ToolNetworkTool.name=網絡工具 +item.appliedenergistics2.ToolAdvancedNetworkTool.name=高級網絡工具 item.appliedenergistics2.ToolChargedStaff.name=充能手杖 item.appliedenergistics2.ToolEntropyManipulator.name=熵變機械臂 item.appliedenergistics2.ToolMassCannon.name=物質炮 diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/ToolAdvancedNetworkTool.png b/src/main/resources/assets/appliedenergistics2/textures/items/ToolAdvancedNetworkTool.png new file mode 100644 index 0000000000000000000000000000000000000000..9bc0b08d88b58d36b6b5db0a43ceea76a6a8f2e9 GIT binary patch literal 1854 zcmbVNeP|nH7{5v_uCBGVRcx8;c9~4sF8A3qcWu_SNxDXQHMYS>t!LO;+f!Z<(&iC>~CtWQIT<+`l z{+{3S{GRu@kzmixs>;Sn1VO3-UA|s;uCb51D&YUdKW~Wev`+7O(nOHE>+GWpnV5V4 zLGJui35Bh&(9KI)$|=fP1UNG(9ikDWwJoEIQUX|L1jH28gZ=UThZw5J9<0AfAO+nE z;!4-B0s4k}Leg+T;$*CCJKCDzAwddQBAQ7hRg=$nupBQBukFVKhUOqv!h^Nj0nxA! zM7^2;&?ct~mngOgZRVVmi(xr#8%mRun;_i;#o&~SXGxx>(ZUad(F{4t_xd^uvEZEt zi(8h?6GS?lcBUDpX2b}J<2Zt(37Wm(o3|eStt`M7?BZmf^w2}N;#k`m2mo?k<0~`B?2Tt3aFL|u~Z4G$2ChcVW74rZ#9uz&`|KI_zw8-fIBS(u|O% zC5uJ{i;_{V*EWVjAMRIFSxcLbEL#J7q6It{P14XZ3MXA5lIBSl&oEm_H&2pzsG!M8 zG`k|S8QOdk6n2d)TH^nLWr>e!MoNS^D=9Gs2wja~XsMFCS4(OJ3=GvVITeDy2UOD% zRS5)q9t@`KR1}$~*k-O7xLDjB;i5Pzvk~0wY8G)R+QdXy8MY=(71#STY0x&exL$_q zX^P=QNdmYCWEQ6-mc=6xhQeteGH#LtOw^sP0*wEdp}@^0CU2X^-g0(V@Lh@t{mK?L zMIRU_TqPAW*9g2Q*$wW&B->daV}-}c3Kdve26@_a96-`l?9RhXEo!Aj1GL9rwbs&6 z#I5w3;?U~q*XG|U>X&!mZK^L6SBi^j48WO5V0J!)JzetF5dU>8_iouFD#GD-voA|? z72cF4Gf*M50q5@6q?tgFvP}VBd&oU@Y@AX**-_)a+-Xf$-xr&@W|SYk-!V}4^tl5Q zlbh?=nQoy`^ZHL;d|~wD^Oeck+LnW#z50Y>{^ftpTz_iI$c>+;uNnuBPaM1YY{fh5 z1?()z2;<*7?^t|$S6%j=bISRp?F~8-{hGVJcWSmmjy6{BJJfJu?&RD@fj26<_iuB2 zX@0T3VXY&{lpRW33b#~UslB+n{8YnNjn7>EHn{f+ dUv>Jgbq`J*f9TTw`fB?N7x4G^W;*t~_%B Date: Mon, 6 Nov 2023 19:04:00 +0800 Subject: [PATCH 23/34] Add the Advanced Network Tool gui --- build.gradle | 45 ++++---- .../GuiAdvancedNetworkTool.java | 78 +++++++++++++ .../ContainerAdvancedNetworkTool.java | 80 +++++++++++++ .../appeng/core/localization/GuiColors.java | 2 + src/main/java/appeng/core/sync/GuiBridge.java | 3 + .../appeng/core/sync/packets/PacketClick.java | 13 +++ .../contents/AdvancedNetworkToolViewer.java | 104 +++++++++++++++++ .../items/tools/ToolAdvancedNetworkTool.java | 107 +++++++++++++++++- .../appliedenergistics2/lang/en_US.lang | 1 + .../appliedenergistics2/lang/zh_CN.lang | 1 + .../appliedenergistics2/lang/zh_TW.lang | 1 + .../textures/guis/advancedtoolbox.png | Bin 0 -> 2598 bytes .../items/ToolAdvancedNetworkTool.png | Bin 1854 -> 4337 bytes .../items/ToolAdvancedNetworkTool.png.mcmeta | 19 ++++ 14 files changed, 429 insertions(+), 25 deletions(-) create mode 100644 src/main/java/appeng/client/gui/implementations/GuiAdvancedNetworkTool.java create mode 100644 src/main/java/appeng/container/implementations/ContainerAdvancedNetworkTool.java create mode 100644 src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java create mode 100644 src/main/resources/assets/appliedenergistics2/textures/guis/advancedtoolbox.png create mode 100644 src/main/resources/assets/appliedenergistics2/textures/items/ToolAdvancedNetworkTool.png.mcmeta diff --git a/build.gradle b/build.gradle index 068308e3e73..f2cf06c15b9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1698936026 +//version: 1699231026 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -906,7 +906,6 @@ runClient17Task.configure { mainClass = "GradleStart" username = minecraft.username userUUID = minecraft.userUUID -// jvmArgs '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' } def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") @@ -1173,30 +1172,32 @@ tasks.named("ideVirtualMainClasses").configure { // workaround variable hiding in pom processing def projectConfigs = project.configurations -publishing { - publications { - create("maven", MavenPublication) { - from components.java +if (System.getenv("MAVEN_USER") != null) { + publishing { + publications { + create("maven", MavenPublication) { + from components.java - if (apiPackage) { - artifact apiJar - } + if (apiPackage) { + artifact apiJar + } - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group - artifactId = System.getenv("ARTIFACT_ID") ?: project.name - // Using the identified version, not project.version as it has the prepended 1.7.10 - version = System.getenv("RELEASE_VERSION") ?: identifiedVersion + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group + artifactId = System.getenv("ARTIFACT_ID") ?: project.name + // Using the identified version, not project.version as it has the prepended 1.7.10 + version = System.getenv("RELEASE_VERSION") ?: identifiedVersion + } } - } - repositories { - if (usesMavenPublishing.toBoolean()) { - maven { - url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + repositories { + if (usesMavenPublishing.toBoolean()) { + maven { + url = mavenPublishUrl + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + credentials { + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + } } } } diff --git a/src/main/java/appeng/client/gui/implementations/GuiAdvancedNetworkTool.java b/src/main/java/appeng/client/gui/implementations/GuiAdvancedNetworkTool.java new file mode 100644 index 00000000000..81a0b6ee164 --- /dev/null +++ b/src/main/java/appeng/client/gui/implementations/GuiAdvancedNetworkTool.java @@ -0,0 +1,78 @@ +package appeng.client.gui.implementations; + +import java.io.IOException; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; + +import appeng.api.implementations.guiobjects.INetworkTool; +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiToggleButton; +import appeng.container.implementations.ContainerAdvancedNetworkTool; +import appeng.core.AELog; +import appeng.core.localization.GuiColors; +import appeng.core.localization.GuiText; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketValueConfig; + +public class GuiAdvancedNetworkTool extends AEBaseGui { + + private GuiToggleButton tFacades; + + public GuiAdvancedNetworkTool(final InventoryPlayer inventoryPlayer, final INetworkTool te) { + super(new ContainerAdvancedNetworkTool(inventoryPlayer, te)); + this.ySize = 202; + } + + @Override + protected void actionPerformed(final GuiButton btn) { + super.actionPerformed(btn); + + try { + if (btn == this.tFacades) { + NetworkHandler.instance.sendToServer(new PacketValueConfig("AdvancedNetworkTool", "Toggle")); + } + } catch (final IOException e) { + AELog.debug(e); + } + } + + @Override + public void initGui() { + super.initGui(); + + this.tFacades = new GuiToggleButton( + this.guiLeft - 18, + this.guiTop + 8, + 23, + 22, + GuiText.TransparentFacades.getLocal(), + GuiText.TransparentFacadesHint.getLocal()); + + this.buttonList.add(this.tFacades); + } + + @Override + public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + if (this.tFacades != null) { + this.tFacades.setState(((ContainerAdvancedNetworkTool) this.inventorySlots).isFacadeMode()); + } + + this.fontRendererObj.drawString( + this.getGuiDisplayName(GuiText.AdvancedNetworkTool.getLocal()), + 8, + 6, + GuiColors.AdvancedNetworkToolTitle.getColor()); + this.fontRendererObj.drawString( + GuiText.inventory.getLocal(), + 8, + this.ySize - 96 + 3, + GuiColors.AdvancedNetworkToolInventory.getColor()); + } + + @Override + public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + this.bindTexture("guis/advancedtoolbox.png"); + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + } +} diff --git a/src/main/java/appeng/container/implementations/ContainerAdvancedNetworkTool.java b/src/main/java/appeng/container/implementations/ContainerAdvancedNetworkTool.java new file mode 100644 index 00000000000..289b6f0cf45 --- /dev/null +++ b/src/main/java/appeng/container/implementations/ContainerAdvancedNetworkTool.java @@ -0,0 +1,80 @@ +package appeng.container.implementations; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import appeng.api.implementations.guiobjects.INetworkTool; +import appeng.container.AEBaseContainer; +import appeng.container.guisync.GuiSync; +import appeng.container.slot.SlotRestrictedInput; +import appeng.util.Platform; + +public class ContainerAdvancedNetworkTool extends AEBaseContainer { + + private final INetworkTool toolInv; + + @GuiSync(1) + public boolean facadeMode; + + public ContainerAdvancedNetworkTool(final InventoryPlayer ip, final INetworkTool te) { + super(ip, null, null); + this.toolInv = te; + + this.lockPlayerInventorySlot(ip.currentItem); + + for (int y = 0; y < 5; y++) { + for (int x = 0; x < 5; x++) { + this.addSlotToContainer( + (new SlotRestrictedInput( + SlotRestrictedInput.PlacableItemType.UPGRADES, + te, + y * 5 + x, + 62 - 18 + x * 18, + 37 - 18 + y * 18, + this.getInventoryPlayer()))); + } + } + + this.bindPlayerInventory(ip, 0, 120); + } + + public void toggleFacadeMode() { + final NBTTagCompound data = Platform.openNbtData(this.toolInv.getItemStack()); + data.setBoolean("hideFacades", !data.getBoolean("hideFacades")); + this.detectAndSendChanges(); + } + + @Override + public void detectAndSendChanges() { + final ItemStack currentItem = this.getPlayerInv().getCurrentItem(); + + if (currentItem != this.toolInv.getItemStack()) { + if (currentItem != null) { + if (Platform.isSameItem(this.toolInv.getItemStack(), currentItem)) { + this.getPlayerInv() + .setInventorySlotContents(this.getPlayerInv().currentItem, this.toolInv.getItemStack()); + } else { + this.setValidContainer(false); + } + } else { + this.setValidContainer(false); + } + } + + if (this.isValidContainer()) { + final NBTTagCompound data = Platform.openNbtData(currentItem); + this.setFacadeMode(data.getBoolean("hideFacades")); + } + + super.detectAndSendChanges(); + } + + public boolean isFacadeMode() { + return this.facadeMode; + } + + private void setFacadeMode(final boolean facadeMode) { + this.facadeMode = facadeMode; + } +} diff --git a/src/main/java/appeng/core/localization/GuiColors.java b/src/main/java/appeng/core/localization/GuiColors.java index 31e1bdb5d97..9d7e3ae8f84 100644 --- a/src/main/java/appeng/core/localization/GuiColors.java +++ b/src/main/java/appeng/core/localization/GuiColors.java @@ -93,7 +93,9 @@ public enum GuiColors { NetworkStatusItemCount(0x404040), NetworkToolTitle(0x404040), + AdvancedNetworkToolTitle(0x404040), NetworkToolInventory(0x404040), + AdvancedNetworkToolInventory(0x404040), OreFilterLabel(0x404040), diff --git a/src/main/java/appeng/core/sync/GuiBridge.java b/src/main/java/appeng/core/sync/GuiBridge.java index 0f7c20d7786..d0018adecea 100644 --- a/src/main/java/appeng/core/sync/GuiBridge.java +++ b/src/main/java/appeng/core/sync/GuiBridge.java @@ -46,6 +46,7 @@ import appeng.container.AEBaseContainer; import appeng.container.ContainerNull; import appeng.container.ContainerOpenContext; +import appeng.container.implementations.ContainerAdvancedNetworkTool; import appeng.container.implementations.ContainerCellWorkbench; import appeng.container.implementations.ContainerChest; import appeng.container.implementations.ContainerCondenser; @@ -142,6 +143,8 @@ public enum GuiBridge implements IGuiHandler { GUI_NETWORK_TOOL(ContainerNetworkTool.class, INetworkTool.class, GuiHostType.ITEM, null), + GUI_ADVANCED_NETWORK_TOOL(ContainerAdvancedNetworkTool.class, INetworkTool.class, GuiHostType.ITEM, null), + GUI_QUARTZ_KNIFE(ContainerQuartzKnife.class, QuartzKnifeObj.class, GuiHostType.ITEM, null), GUI_DRIVE(ContainerDrive.class, TileDrive.class, GuiHostType.WORLD, SecurityPermissions.BUILD), diff --git a/src/main/java/appeng/core/sync/packets/PacketClick.java b/src/main/java/appeng/core/sync/packets/PacketClick.java index 67287987986..378b0809b1a 100644 --- a/src/main/java/appeng/core/sync/packets/PacketClick.java +++ b/src/main/java/appeng/core/sync/packets/PacketClick.java @@ -20,6 +20,7 @@ import appeng.api.implementations.items.MemoryCardMessages; import appeng.core.sync.AppEngPacket; import appeng.core.sync.network.INetworkInfo; +import appeng.items.tools.ToolAdvancedNetworkTool; import appeng.items.tools.ToolNetworkTool; import appeng.items.tools.powered.ToolColorApplicator; import io.netty.buffer.ByteBuf; @@ -84,6 +85,18 @@ public void serverPacketData(final INetworkInfo manager, final AppEngPacket pack this.hitX, this.hitY, this.hitZ); + } else if (is.getItem() instanceof ToolAdvancedNetworkTool atnt) { + atnt.serverSideToolLogic( + is, + player, + player.worldObj, + this.x, + this.y, + this.z, + this.side, + this.hitX, + this.hitY, + this.hitZ); } else if (maybeMemoryCard.isSameAs(is)) { final IMemoryCard mem = (IMemoryCard) is.getItem(); mem.notifyUser(player, MemoryCardMessages.SETTINGS_CLEARED); diff --git a/src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java b/src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java new file mode 100644 index 00000000000..ed2b2cf7c03 --- /dev/null +++ b/src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java @@ -0,0 +1,104 @@ +package appeng.items.contents; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +import appeng.api.implementations.guiobjects.INetworkTool; +import appeng.api.implementations.items.IUpgradeModule; +import appeng.api.networking.IGridHost; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.util.Platform; + +public class AdvancedNetworkToolViewer implements INetworkTool { + + private final AppEngInternalInventory inv; + private final ItemStack is; + private final IGridHost gh; + + public AdvancedNetworkToolViewer(final ItemStack is, final IGridHost gHost) { + this.is = is; + this.gh = gHost; + this.inv = new AppEngInternalInventory(null, 25); + if (is.hasTagCompound()) // prevent crash when opening network status screen. + { + this.inv.readFromNBT(Platform.openNbtData(is), "inv"); + } + } + + @Override + public int getSizeInventory() { + return this.inv.getSizeInventory(); + } + + @Override + public ItemStack getStackInSlot(final int i) { + return this.inv.getStackInSlot(i); + } + + @Override + public ItemStack decrStackSize(final int i, final int j) { + return this.inv.decrStackSize(i, j); + } + + @Override + public ItemStack getStackInSlotOnClosing(final int i) { + return this.inv.getStackInSlotOnClosing(i); + } + + @Override + public void setInventorySlotContents(final int i, final ItemStack itemstack) { + this.inv.setInventorySlotContents(i, itemstack); + } + + @Override + public String getInventoryName() { + return this.inv.getInventoryName(); + } + + @Override + public boolean hasCustomInventoryName() { + return this.inv.hasCustomInventoryName(); + } + + @Override + public int getInventoryStackLimit() { + return this.inv.getInventoryStackLimit(); + } + + @Override + public void markDirty() { + this.inv.markDirty(); + this.inv.writeToNBT(Platform.openNbtData(this.is), "inv"); + } + + @Override + public boolean isUseableByPlayer(final EntityPlayer entityplayer) { + return this.inv.isUseableByPlayer(entityplayer); + } + + @Override + public void openInventory() { + this.inv.openInventory(); + } + + @Override + public void closeInventory() { + this.inv.closeInventory(); + } + + @Override + public boolean isItemValidForSlot(final int i, final ItemStack itemstack) { + return this.inv.isItemValidForSlot(i, itemstack) && itemstack.getItem() instanceof IUpgradeModule + && ((IUpgradeModule) itemstack.getItem()).getType(itemstack) != null; + } + + @Override + public ItemStack getItemStack() { + return this.is; + } + + @Override + public IGridHost getGridHost() { + return this.gh; + } +} diff --git a/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java index 650d74a61b9..ad0de9fdeb9 100644 --- a/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java +++ b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java @@ -2,12 +2,17 @@ import java.util.EnumSet; +import net.minecraft.block.Block; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; import com.google.common.base.Optional; @@ -15,11 +20,19 @@ import appeng.api.implementations.guiobjects.IGuiItemObject; import appeng.api.implementations.items.IAEWrench; import appeng.api.networking.IGridHost; +import appeng.api.parts.IPartHost; +import appeng.api.parts.SelectedPart; +import appeng.api.util.DimensionalCoord; +import appeng.api.util.INetworkToolAgent; import appeng.client.ClientHelper; +import appeng.container.AEBaseContainer; import appeng.core.features.AEFeature; +import appeng.core.sync.GuiBridge; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketClick; import appeng.integration.IntegrationType; import appeng.items.AEBaseItem; -import appeng.items.contents.NetworkToolViewer; +import appeng.items.contents.AdvancedNetworkToolViewer; import appeng.transformer.annotations.Integration.Interface; import appeng.transformer.annotations.Integration.InterfaceList; import appeng.util.Platform; @@ -63,11 +76,99 @@ public ItemStack onItemRightClick(final ItemStack it, final World w, final Entit @Override public boolean onItemUseFirst(final ItemStack is, final EntityPlayer player, final World world, final int x, final int y, final int z, final int side, final float hitX, final float hitY, final float hitZ) { - // TODO + if (ForgeEventFactory.onItemUseStart(player, is, 1) <= 0) return true; + + Block blk = world.getBlock(x, y, z); + if (blk != null) if (ForgeEventFactory.onPlayerInteract( + player, + blk.isAir(world, x, y, z) ? PlayerInteractEvent.Action.RIGHT_CLICK_AIR + : PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK, + x, + y, + z, + side, + world).isCanceled()) + return true; + + final MovingObjectPosition mop = new MovingObjectPosition( + x, + y, + z, + side, + Vec3.createVectorHelper(hitX, hitY, hitZ)); + final TileEntity te = world.getTileEntity(x, y, z); + if (te instanceof IPartHost) { + final SelectedPart part = ((IPartHost) te).selectPart(mop.hitVec); + + if (part.part != null || part.facade != null) { + if (part.part instanceof INetworkToolAgent && !((INetworkToolAgent) part.part).showNetworkInfo(mop)) { + return false; + } + } + } else if (te instanceof INetworkToolAgent && !((INetworkToolAgent) te).showNetworkInfo(mop)) { + return false; + } + if (Platform.isClient()) { + NetworkHandler.instance.sendToServer(new PacketClick(x, y, z, side, hitX, hitY, hitZ)); + } return true; } + public boolean serverSideToolLogic(final ItemStack is, final EntityPlayer p, final World w, final int x, + final int y, final int z, final int side, final float hitX, final float hitY, final float hitZ) { + if (side >= 0) { + if (!Platform.hasPermissions(new DimensionalCoord(w, x, y, z), p)) { + return false; + } + + final Block b = w.getBlock(x, y, z); + + if (b != null) if (ForgeEventFactory.onPlayerInteract( + p, + b.isAir(w, x, y, z) ? PlayerInteractEvent.Action.RIGHT_CLICK_AIR + : PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK, + x, + y, + z, + side, + w).isCanceled()) + return false; + + if (b != null && !p.isSneaking()) { + final TileEntity te = w.getTileEntity(x, y, z); + if (!(te instanceof IGridHost)) { + if (b.rotateBlock(w, x, y, z, ForgeDirection.getOrientation(side))) { + b.onNeighborBlockChange(w, x, y, z, Platform.AIR_BLOCK); + p.swingItem(); + return !w.isRemote; + } + } + } + + if (!p.isSneaking()) { + if (p.openContainer instanceof AEBaseContainer) { + return true; + } + + final TileEntity te = w.getTileEntity(x, y, z); + + if (te instanceof IGridHost) { + Platform.openGUI(p, te, ForgeDirection.getOrientation(side), GuiBridge.GUI_NETWORK_STATUS); + } else { + Platform.openGUI(p, null, ForgeDirection.UNKNOWN, GuiBridge.GUI_ADVANCED_NETWORK_TOOL); + } + + return true; + } else { + b.onBlockActivated(w, x, y, z, p, side, hitX, hitY, hitZ); + } + } else { + Platform.openGUI(p, null, ForgeDirection.UNKNOWN, GuiBridge.GUI_ADVANCED_NETWORK_TOOL); + } + return false; + } + @Override public boolean doesSneakBypassUse(final World world, final int x, final int y, final int z, final EntityPlayer player) { @@ -102,7 +203,7 @@ public void toolUsed(ItemStack itemStack, EntityLivingBase entity, int x, int y, @Override public IGuiItemObject getGuiObject(final ItemStack is, final World world, final int x, final int y, final int z) { final TileEntity te = world.getTileEntity(x, y, z); - return new NetworkToolViewer(is, (IGridHost) (te instanceof IGridHost ? te : null)); + return new AdvancedNetworkToolViewer(is, (IGridHost) (te instanceof IGridHost ? te : null)); } } diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 975bbfa2c78..15fcf70e7c1 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -151,6 +151,7 @@ gui.appliedenergistics2.StorageBus=Storage Bus gui.appliedenergistics2.EnergyDrain=Passive Drain gui.appliedenergistics2.Installed=Installed gui.appliedenergistics2.NetworkTool=Network Tool +gui.appliedenergistics2.AdvancedNetworkTool=Advanced Network Tool gui.appliedenergistics2.PowerUsageRate=Energy Usage gui.appliedenergistics2.PowerInputRate=Energy Generation gui.appliedenergistics2.PortableCell=Portable Cell diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 8ce27292d69..524875d4f8f 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -151,6 +151,7 @@ gui.appliedenergistics2.StorageBus=存储总线 gui.appliedenergistics2.EnergyDrain=被动流失 gui.appliedenergistics2.Installed=已安装 gui.appliedenergistics2.NetworkTool=网络工具 +gui.appliedenergistics2.AdvancedNetworkTool=高级网络工具 gui.appliedenergistics2.PowerUsageRate=耗能 gui.appliedenergistics2.PowerInputRate=产能 gui.appliedenergistics2.PortableCell=便携元件 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang index 825693c772e..5e14defcabe 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang @@ -109,6 +109,7 @@ gui.appliedenergistics2.StorageBus=存儲總線 gui.appliedenergistics2.EnergyDrain=被動流失 gui.appliedenergistics2.Installed=已安裝 gui.appliedenergistics2.NetworkTool=網絡工具 +gui.appliedenergistics2.AdvancedNetworkTool=高級網絡工具 gui.appliedenergistics2.PowerUsageRate=耗能 gui.appliedenergistics2.PowerInputRate=產能 gui.appliedenergistics2.PortableCell=便攜元件 diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/advancedtoolbox.png b/src/main/resources/assets/appliedenergistics2/textures/guis/advancedtoolbox.png new file mode 100644 index 0000000000000000000000000000000000000000..6c6d6e590947ab145ddd13e626ba704b84a4e031 GIT binary patch literal 2598 zcmd^BZEO>D7{84H8woQc5L7_Us~^D8-t~38OUpJ|=4R-4n=k^2Uhl5$xnA$MyU})I zxbc!ohy!EBV5{MSQHhavgWzN?%s5H9IfG`r4KT$H0|R8kfn$sR>)HwiWbnZ+HcxZ^ zyZb%A=l#iTT~hMe6s?jVDEnLGpH`of zJp+O=`q|Plxy-SMpmEOf<0oFv?MJ%%y zCTxK_E8>x5fk08e->>oOHN5CXwK$HWm=4wH)BvHDfI*6s=E6qzNPp4Uht=)nH0UaUe~la6*OXjT@&al<_hgP_4*+LAhixh%Elvo;kc9uNnW@Pgpo+dBhgZ6P+-tyjKo)n6ti$0a8sp3 zBM>%`A!S}H<#}(iP)m|7!#0~z7#yCnlJ(KNUz+=X4r3=}#){}L9VnSrjhRZdxrAOv zXbm}-nZU47sDr0jSMX6#BTneBhoGQqXi_Gh2&O5*#fuyXVrDtg&7gwMjlii)5;oq; zi@-4OP9OKe;UJ2Al1%z2rr2&pK-e0Vr3q)Q+2G90HL4Ai&Zssq2AA6GG%#w0F_>|) zR!ccCV^ZJFQx!^allt^i>Ms^qFkGbfnR%3vQ@VmEVkJ+^(BHm)t@c=0@mNzVtYYpAl%opwB)>JYR!-3KfO`U9en@w z>zlT0u4p}Md2W_rTK&l{Ub)qDGdw+i!OEpmTh0_7zZlCKYSnttOV^tl`l{9s4PLvk z^~#*1-1**y%v*!L?`G#s>>n5~MBlxG91TvZ>Fw?Pp~`S8&tkDeB9Y(Z#_CJ6vc7KX zIFNTY8rs?Pb7t3o5$B+X=9axw!U%4nwy)3hN`6fmQWq%`lI@i+qLt}3{utA z9$8hb>S}9ii$uaDpPn789=Z~eJRu@|*P$s_Rk6=U3R{0YHUT2j$1I_96Azw?g%1#+ z>>0I@dtBXn`Lq5Xe04T1W8(`mYBi_kLYuQ5FCPxit7%%>c;saGXMRN`&2M<#^KsLP z#?#@b{?+d2)G>5Ss--$_j4SK=q&{Zo6|8PP`)$<@JSP%7G3EP?0<^slmUix;R9$zT zu7IZW-AC@v-2b=wnM}I#w&czD>ZNW7UNmNj#O=4;3HM}XOY)wVw9$|4m}3!50u5F8itsXWGsK$ zAru!81qJF16oj&cFu@g|kVwqt3i$%D*c;*@T#SQY94;T`3MB$W!s9{K4-0rRkP1n3 z&_b&(@Jq&0nM`^Khm)S3&Q9mEbp|DeD;A462#>?#!2kgpGqfh$3~P-uM=S(UM#7-h zo76fjL|eq=x>S>l1(;g4pwZjRYK_(~fq-$$xSqphBlMPrfqIqBq%*2?kAT~zf3=7t zY{vDehU8(!B*CGQDGjAH83C4Sa{xjc5n+Qrl#51VLmN%OX6u>zfHJEe0i|bbP`xD3K;b5xAy%hL z9??$JNW`JQKw2weXzp^gmei#i=h54+uAzc(6D4Eu5FStw7e<7!Tp%P=!V}F$FbRTK zpb<+y-=#iR&<5sV;k6cv&< zhK;Nb(h;e&bm;Y#(j#>QurbO7=ZQ%!!WF;>f}t>>5C~xmrQ|S*$^|$fRLFUJ!HBgb z1~sUDJbA2DniUBw3Q<&mi$O_|d{hB*X$7rD<96J*~c1Fyj`@?9|Mk3%3a$^KKG+O&l0IsyYC98c#Lc`9~RNSAwKJO|5bs#ovghJ)S)w z5|W4*!(fz)C}4yy5WyHGSAaqxD9{i@3K0U5|0wpum5rbymHh|VTg?+HT&twO0m)(g z@%_lc)6QC>=6pY~l6c%H05=L+_0aSxy3Xv_Fzt6^RI@SMwKZH)3Mj6H^OphCI zaL!W(ql~36=rj>TdKz`BU>W+*K?sf%DsLVfh_o3FbmNJ;SHGWo^a;y1(=YJ zDa0@$5RouO32+!A5EN7_O3HCcfC?$lye({W|Ld7U%V;h6VY@sfk?HvQ=8)AMA4{G+V6xhrP5WJWpfpFDX{ z{6v!|+U3AJd8oJf%E$T6)V|t%X2hlD_|eQLr@2=u^UrRoy{i52z-`ucCs{?sp3MQJ zRpB`&X2rGnF!{O~{<%~2XHD#u8Mz!z@zCXBQSZ<_Wg7aoaZ92P+6|so|I+)G=EBQ0 zqWG=PHkPQXcQsvOZ94VL+~6d#^heJ*Yp3OIJkc}Aw=dFM@S5}Q&80qj^Nz^R?#-v- zYs)JtsKxfMNF3%_JX`Db+4T!=A3Cr|sZ_R8XA*PnG@ad6z%L1}*rO?KX^GTcY=ESODR3y>esNdq4R~IuvZ=SYGzI?xL^0+#+(9z z5#i)tSd(15>~t!kEGnw3et-R;rKuh6>+Q_RJsn5a4=&7^vokmSL*MtOOmh2B(YhmY zUASgtfs&g0af|ln1gk8HO2HYzk9`_dH*Hmjm zn>{@+Zpa@MU#oiH#mMXz-TvmntIj!I9sY;cXl}GW@3r0ayfG%0H`5eeQl{*_8OWn--sPFuecYTmz2JoDmR$14NL^TIvaW-v;Jt`>y&Z*k=O-LBM7-Tt+oy*{ITF?7tuomsi* zy_N;P%)HX)HQ2pz)Y7?BucT+s-~G$d`1!3H+)BIhzFadH0)5~Z$!31GV8Vp5>dQR= z%X_!%X1wu1SX-=z$E>y=_NN~&U*R6QDW9*MRp72-u$iv|s`cx$-M3Qlx2M}>oSJrZ zvpdtHPKqRWxGlRab7hjjQm1u}Gg>|=-!dWZu*=JJS?3ls#-?u@%074Py3Yo;n{(&h zY~0^{!*BjnDX`dbcwq8z?wjAvcs(K2?6R9q{jU1*5NW~leUP_Dz4Tzq%DTpId0vwt z+jz+SzN;6rrS72a=nwh)3qLj;V>2BR{xVTp==fk@X}k9N1eGA=`|{Fe`>vluz}$KV_pHur5m1d; zY95E}n4fh^92j=7d@EGN@(7Yfbv51d9ys#+LgwC$iLc=I@M$LpwEbOc2ZGZ@2Qs@G zc{eXfP!DOc{mR=bcZKW|6nNfzx8M06!01W)#An30d(3;54Nds$)beW`teU^l|C9&| Mjtu%FU}esK0UVxASO5S3 delta 670 zcmeyUxQ}mwxUv8T8v_G_{OA9PK#H@#BeIx*fm;}a85w5Hkzin8J-pG%mvQnQMxDv+ zjHZ)cFlJ7E!sN?gU}R-rW@T(VIgMEv%rUnzF_>)0tjY(H0dceqEUXL+Ca-6fs4vLK zFUc>?$S<&R&drO-0%6hIGAtCE&C#HufzwP_C=Vz39=l>TAUlvVUHf!n2 zTDHw5SCvj182e6oqQ~@oQ=D)m|Aov;zwIOo7}Bm;{%l)tj4dTiim$$XhUD_gD=#1L zT*T$mt)qOt_zaKrd`1fyK8AHX3+FNa{%h;Ob|We7^>& zc*e8Xn|_a*P>gWZ#Rh=6xV^C!S@k nbP0l+XkK2m$a( diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/ToolAdvancedNetworkTool.png.mcmeta b/src/main/resources/assets/appliedenergistics2/textures/items/ToolAdvancedNetworkTool.png.mcmeta new file mode 100644 index 00000000000..9f04d7ff868 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/textures/items/ToolAdvancedNetworkTool.png.mcmeta @@ -0,0 +1,19 @@ +{ + "animation": { + "frametime": 3, + "frames": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 0 + ] + } +} From 4a8bb6fea92723662cee9667e831c2250878e03e Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Tue, 7 Nov 2023 22:04:11 +0800 Subject: [PATCH 24/34] Add the advanced toolbox for other Gui --- .../guiobjects/INetworkTool.java | 2 ++ .../gui/implementations/GuiCellWorkbench.java | 13 ++++++- .../gui/implementations/GuiUpgradeable.java | 32 ++++++++++++++++-- .../implementations/ContainerUpgradeable.java | 27 ++++++++++----- .../contents/AdvancedNetworkToolViewer.java | 8 +++++ .../items/contents/NetworkToolViewer.java | 11 ++++-- .../items/tools/ToolAdvancedNetworkTool.java | 4 +-- .../appeng/items/tools/ToolNetworkTool.java | 2 +- .../textures/guis/advanced_toolbox.png | Bin 0 -> 2804 bytes 9 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 src/main/resources/assets/appliedenergistics2/textures/guis/advanced_toolbox.png diff --git a/src/main/java/appeng/api/implementations/guiobjects/INetworkTool.java b/src/main/java/appeng/api/implementations/guiobjects/INetworkTool.java index c3c82b074b7..6a1d5543ea3 100644 --- a/src/main/java/appeng/api/implementations/guiobjects/INetworkTool.java +++ b/src/main/java/appeng/api/implementations/guiobjects/INetworkTool.java @@ -22,5 +22,7 @@ */ public interface INetworkTool extends IInventory, IGuiItemObject { + int getSize(); + IGridHost getGridHost(); // null for most purposes. } diff --git a/src/main/java/appeng/client/gui/implementations/GuiCellWorkbench.java b/src/main/java/appeng/client/gui/implementations/GuiCellWorkbench.java index b9e22e78da4..624f6d34e5d 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiCellWorkbench.java +++ b/src/main/java/appeng/client/gui/implementations/GuiCellWorkbench.java @@ -139,7 +139,18 @@ public void drawBG(final int offsetX, final int offsetY, final int mouseX, final } } if (this.hasToolbox()) { - this.drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, 161, 68, 68); + // this.drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, 161, 68, 68); + switch (this.getToolboxSize()) { + case 3 -> this + .drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, this.ySize - 90, 68, 68); + case 5 -> { + this.bindTexture(this.getAdvancedBackground()); + // It's too big, so move it up a little bit + this.drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90 - 7, 0, 0, 104, 104); + } + default -> this + .drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, this.ySize - 90, 68, 68); + } } } diff --git a/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java b/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java index 03451f355f5..b527b06e404 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java +++ b/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java @@ -70,7 +70,15 @@ public GuiUpgradeable(final ContainerUpgradeable te) { this.cvb = te; this.bc = (IUpgradeableHost) te.getTarget(); - this.xSize = this.hasToolbox() ? 246 : 211; + if (this.hasToolbox()) { + this.xSize = switch (this.getToolboxSize()) { + case 3 -> 246; + case 5 -> 290; + default -> 246; + }; + } else { + this.xSize = 211; + } this.ySize = 184; } @@ -78,6 +86,10 @@ protected boolean hasToolbox() { return ((ContainerUpgradeable) this.inventorySlots).hasToolbox(); } + protected int getToolboxSize() { + return ((ContainerUpgradeable) this.inventorySlots).getToolboxSize(); + } + @Override public void initGui() { super.initGui(); @@ -150,12 +162,24 @@ public void drawBG(final int offsetX, final int offsetY, final int mouseX, final this.handleButtonVisibility(); this.bindTexture(this.getBackground()); + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, 211 - 34, this.ySize); if (this.drawUpgrades()) { this.drawTexturedModalRect(offsetX + 177, offsetY, 177, 0, 35, 14 + this.cvb.availableUpgrades() * 18); } if (this.hasToolbox()) { - this.drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, this.ySize - 90, 68, 68); + switch (this.getToolboxSize()) { + case 3 -> this + .drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, this.ySize - 90, 68, 68); + case 5 -> { + this.bindTexture(this.getAdvancedBackground()); + // It's too big, so move it up a little bit + // Why Storage Bus will use this to draw all the slot????? + this.drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90 - 7, 0, 0, 104, 104); + } + default -> this + .drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, this.ySize - 90, 68, 68); + } } } @@ -184,6 +208,10 @@ protected String getBackground() { return "guis/bus.png"; } + protected String getAdvancedBackground() { + return "guis/advanced_toolbox.png"; + } + protected boolean drawUpgrades() { return true; } diff --git a/src/main/java/appeng/container/implementations/ContainerUpgradeable.java b/src/main/java/appeng/container/implementations/ContainerUpgradeable.java index 20f1bfef7ea..4d81cf415c9 100644 --- a/src/main/java/appeng/container/implementations/ContainerUpgradeable.java +++ b/src/main/java/appeng/container/implementations/ContainerUpgradeable.java @@ -25,6 +25,7 @@ import appeng.api.config.YesNo; import appeng.api.implementations.IUpgradeableHost; import appeng.api.implementations.guiobjects.IGuiItem; +import appeng.api.implementations.guiobjects.INetworkTool; import appeng.api.parts.IPart; import appeng.api.util.IConfigManager; import appeng.container.AEBaseContainer; @@ -33,7 +34,7 @@ import appeng.container.slot.OptionalSlotFake; import appeng.container.slot.OptionalSlotFakeTypeOnly; import appeng.container.slot.SlotRestrictedInput; -import appeng.items.contents.NetworkToolViewer; +import appeng.items.tools.ToolAdvancedNetworkTool; import appeng.items.tools.ToolNetworkTool; import appeng.parts.automation.PartExportBus; import appeng.util.Platform; @@ -55,7 +56,8 @@ public class ContainerUpgradeable extends AEBaseContainer implements IOptionalSl public SchedulingMode schedulingMode = SchedulingMode.DEFAULT; private int tbSlot; - private NetworkToolViewer tbInventory; + // change to interface + private INetworkTool tbInventory; public ContainerUpgradeable(final InventoryPlayer ip, final IUpgradeableHost te) { super(ip, (TileEntity) (te instanceof TileEntity ? te : null), (IPart) (te instanceof IPart ? te : null)); @@ -84,25 +86,30 @@ public ContainerUpgradeable(final InventoryPlayer ip, final IUpgradeableHost te) final IInventory pi = this.getPlayerInv(); for (int x = 0; x < pi.getSizeInventory(); x++) { final ItemStack pii = pi.getStackInSlot(x); - if (pii != null && pii.getItem() instanceof ToolNetworkTool) { + // Add ToolAdvancedNetworkTool recognition + if (pii != null + && (pii.getItem() instanceof ToolNetworkTool || pii.getItem() instanceof ToolAdvancedNetworkTool)) { this.lockPlayerInventorySlot(x); this.tbSlot = x; - this.tbInventory = (NetworkToolViewer) ((IGuiItem) pii.getItem()) + this.tbInventory = (INetworkTool) ((IGuiItem) pii.getItem()) .getGuiObject(pii, w, xCoord, yCoord, zCoord); break; } } if (this.hasToolbox()) { - for (int v = 0; v < 3; v++) { - for (int u = 0; u < 3; u++) { + int size = this.tbInventory.getSize(); + // For advanced toolbox to move down a little bit + int yBias = size == 3 ? 0 : 7; + for (int v = 0; v < size; v++) { + for (int u = 0; u < size; u++) { this.addSlotToContainer( (new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, this.tbInventory, - u + v * 3, + u + v * size, 186 + u * 18, - this.getHeight() - 82 + v * 18, + this.getHeight() - 82 - yBias + v * 18, this.getInventoryPlayer())).setPlayerSide()); } } @@ -117,6 +124,10 @@ public boolean hasToolbox() { return this.tbInventory != null; } + public int getToolboxSize() { + return this.tbInventory.getSize(); + } + protected int getHeight() { return 184; } diff --git a/src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java b/src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java index ed2b2cf7c03..575d50ab867 100644 --- a/src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java +++ b/src/main/java/appeng/items/contents/AdvancedNetworkToolViewer.java @@ -9,22 +9,30 @@ import appeng.tile.inventory.AppEngInternalInventory; import appeng.util.Platform; +@Deprecated public class AdvancedNetworkToolViewer implements INetworkTool { private final AppEngInternalInventory inv; private final ItemStack is; private final IGridHost gh; + private final int size; public AdvancedNetworkToolViewer(final ItemStack is, final IGridHost gHost) { this.is = is; this.gh = gHost; this.inv = new AppEngInternalInventory(null, 25); + this.size = 5; if (is.hasTagCompound()) // prevent crash when opening network status screen. { this.inv.readFromNBT(Platform.openNbtData(is), "inv"); } } + @Override + public int getSize() { + return this.size; + } + @Override public int getSizeInventory() { return this.inv.getSizeInventory(); diff --git a/src/main/java/appeng/items/contents/NetworkToolViewer.java b/src/main/java/appeng/items/contents/NetworkToolViewer.java index e696dedf1d1..d3d28627886 100644 --- a/src/main/java/appeng/items/contents/NetworkToolViewer.java +++ b/src/main/java/appeng/items/contents/NetworkToolViewer.java @@ -24,17 +24,24 @@ public class NetworkToolViewer implements INetworkTool { private final AppEngInternalInventory inv; private final ItemStack is; private final IGridHost gh; + private final int size; - public NetworkToolViewer(final ItemStack is, final IGridHost gHost) { + public NetworkToolViewer(final ItemStack is, final IGridHost gHost, final int size) { this.is = is; this.gh = gHost; - this.inv = new AppEngInternalInventory(null, 9); + this.size = size; + this.inv = new AppEngInternalInventory(null, (int) Math.pow(size, size)); if (is.hasTagCompound()) // prevent crash when opening network status screen. { this.inv.readFromNBT(Platform.openNbtData(is), "inv"); } } + @Override + public int getSize() { + return this.size; + } + @Override public int getSizeInventory() { return this.inv.getSizeInventory(); diff --git a/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java index ad0de9fdeb9..67282c5ec73 100644 --- a/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java +++ b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java @@ -32,7 +32,7 @@ import appeng.core.sync.packets.PacketClick; import appeng.integration.IntegrationType; import appeng.items.AEBaseItem; -import appeng.items.contents.AdvancedNetworkToolViewer; +import appeng.items.contents.NetworkToolViewer; import appeng.transformer.annotations.Integration.Interface; import appeng.transformer.annotations.Integration.InterfaceList; import appeng.util.Platform; @@ -203,7 +203,7 @@ public void toolUsed(ItemStack itemStack, EntityLivingBase entity, int x, int y, @Override public IGuiItemObject getGuiObject(final ItemStack is, final World world, final int x, final int y, final int z) { final TileEntity te = world.getTileEntity(x, y, z); - return new AdvancedNetworkToolViewer(is, (IGridHost) (te instanceof IGridHost ? te : null)); + return new NetworkToolViewer(is, (IGridHost) (te instanceof IGridHost ? te : null), 5); } } diff --git a/src/main/java/appeng/items/tools/ToolNetworkTool.java b/src/main/java/appeng/items/tools/ToolNetworkTool.java index e1df102cd1c..ea68b0856cc 100644 --- a/src/main/java/appeng/items/tools/ToolNetworkTool.java +++ b/src/main/java/appeng/items/tools/ToolNetworkTool.java @@ -65,7 +65,7 @@ public ToolNetworkTool() { @Override public IGuiItemObject getGuiObject(final ItemStack is, final World world, final int x, final int y, final int z) { final TileEntity te = world.getTileEntity(x, y, z); - return new NetworkToolViewer(is, (IGridHost) (te instanceof IGridHost ? te : null)); + return new NetworkToolViewer(is, (IGridHost) (te instanceof IGridHost ? te : null), 3); } @Override diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/advanced_toolbox.png b/src/main/resources/assets/appliedenergistics2/textures/guis/advanced_toolbox.png new file mode 100644 index 0000000000000000000000000000000000000000..9e57b815e592862dd01a4e33c34cadc9c701a739 GIT binary patch literal 2804 zcmeHJU2GIp6rQf76ci|iG+?ovOcSH2v-7t*J2SG-(goV+LIX{p3Zb)i?(R;y^V6AW zcUweK^Z`-82Mi68pl?12s3{N|{*)3;1Na04N`uX|AR!13QV2xv>>p^LSs(Pt&E1_l zch33FcfNDx-ufr%i_5YfudPTR9YQc zo{NRQc?~N@F`_6^G)u88i7ZIFM|b2DsoS-Agb=iWrJ9av=(vk0 zM~p5fNFb)!6g0B{tJ^u5kYH3wHYvtSyD8-j!{Mn-HLYN6JIlIJlpNou0^6-UCZtwF z+vu_YT-FVBr#2tVj2n(&$Bk!jD?I)SLj@E9nq5{RBaZ?on1C9>wvjE9;b%&X7L*;s zYBh{RzECashcoNlRr65F(rFq3qBUU^|laN6;Vn7f{F5m|N!3Q|BMBtC(HW~@T z3L6Simm_cmNKwPmWYj{cCdVLU>M^&W5jx7ENwrb+dUCJG8rYeeB~(1qcajX;b`KK3 ztusW~XP4Eds8<}%tbZ~N5$F`f&zjjr)Je(~Y=|MHi|H@wS^RCedusN@)&AdQpA#3v zWjzMb4oVSjK9sxHWJ^Q+y=srEp6{Fn)YEQF?VJ)z~2S%m^kIc9yZ-3BMF>foeV&>Pe-J8yq zRb0RH;^^8@a6=p0v-#lmTVtPXzGqzPuHN$A$cFgMivwECegZpummZwlV;@~VWUd%` zIWhJocJ=Dj@nF@^d@y+I*iL3h*nbX;CX=2k!{1NT3{HNLzIJ{RuEM|acd z^yN9GuyE*x!%qCPZ(?G?IM=tO(~p6{jh~NpE~-A0d9W}>4gW%7AIvCvY#5pD!rnCr=T<9#CUVLsYX z|NQWwx!c- hh5z63zf@oeb~4?uenI-iM)!Yd^Rktpua>rN{S!y(I->vp literal 0 HcmV?d00001 From 469769470b6f912b861c0ab3dd1b997255e4b1e7 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Tue, 7 Nov 2023 23:29:14 +0800 Subject: [PATCH 25/34] Update Build Script --- build.gradle | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index f2cf06c15b9..f3a7fa27881 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1699231026 +//version: 1699290261 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -1172,32 +1172,29 @@ tasks.named("ideVirtualMainClasses").configure { // workaround variable hiding in pom processing def projectConfigs = project.configurations -if (System.getenv("MAVEN_USER") != null) { - publishing { - publications { - create("maven", MavenPublication) { - from components.java +publishing { + publications { + create("maven", MavenPublication) { + from components.java - if (apiPackage) { - artifact apiJar - } - - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group - artifactId = System.getenv("ARTIFACT_ID") ?: project.name - // Using the identified version, not project.version as it has the prepended 1.7.10 - version = System.getenv("RELEASE_VERSION") ?: identifiedVersion + if (apiPackage) { + artifact apiJar } - } - repositories { - if (usesMavenPublishing.toBoolean()) { - maven { - url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" - } + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group + artifactId = System.getenv("ARTIFACT_ID") ?: project.name + // Using the identified version, not project.version as it has the prepended 1.7.10 + version = System.getenv("RELEASE_VERSION") ?: identifiedVersion + } + } + repositories { + if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { + maven { + url = mavenPublishUrl + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + credentials { + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" } } } From 025d595993c2bd61aab027810ab1320ab1c25a78 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Thu, 9 Nov 2023 23:53:08 +0800 Subject: [PATCH 26/34] Add recipe into AE and fix some issue --- .../gui/implementations/GuiNetworkStatus.java | 19 ++++++++++--------- .../gui/implementations/GuiUpgradeable.java | 2 +- .../core/sync/packets/PacketValueConfig.java | 5 +++++ .../appeng/me/cache/GridStorageCache.java | 17 +++++++++++++++++ src/main/java/appeng/server/ServerHelper.java | 4 +++- .../java/appeng/tile/storage/TileChest.java | 6 +++++- .../recipes/tools/network.recipe | 4 ++++ 7 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index 325c66e29bc..d0e74157194 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -118,6 +118,7 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { @Override public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; + String tempStr; this.fontRendererObj .drawString(GuiText.NetworkDetails.getLocal(), 8, 6, GuiColors.NetworkStatusDetails.getColor()); @@ -144,40 +145,40 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final GuiColors.NetworkStatusPowerUsageRate.getColor()); // Item byte status + tempStr = ns.getItemBytesTotal() == 0 ? "" + : " (" + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) + "%)"; this.fontRendererObj.drawString( GuiText.Items.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesUsed()) + " / " + Platform.formatByteLong(ns.getItemBytesTotal()) - + " (" - + df.format(ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal()) - + "%)", + + tempStr, 13, 143, GuiColors.NetworkStatusPowerUsageRate.getColor()); + tempStr = ns.getFluidBytesTotal() == 0 ? "" + : " (" + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) + "%)"; // Fluid byte status this.fontRendererObj.drawString( GuiText.Fluids.getLocal() + ": " + Platform.formatByteLong(ns.getFluidBytesUsed()) + " / " + Platform.formatByteLong(ns.getFluidBytesTotal()) - + " (" - + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) - + "%)", + + tempStr, 13, 143 + 10, GuiColors.NetworkStatusPowerUsageRate.getColor()); + tempStr = ns.getEssentiaBytesTotal() == 0 ? "" + : " (" + df.format(ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal()) + "%)"; // Essential byte status this.fontRendererObj.drawString( GuiText.Essentias.getLocal() + ": " + Platform.formatByteLong(ns.getEssentiaBytesUsed()) + " / " + Platform.formatByteLong(ns.getEssentiaBytesTotal()) - + " (" - + df.format(ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal()) - + "%)", + + tempStr, 13, 143 + 20, GuiColors.NetworkStatusPowerUsageRate.getColor()); diff --git a/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java b/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java index b527b06e404..a487b46de3d 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java +++ b/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java @@ -174,8 +174,8 @@ public void drawBG(final int offsetX, final int offsetY, final int mouseX, final case 5 -> { this.bindTexture(this.getAdvancedBackground()); // It's too big, so move it up a little bit - // Why Storage Bus will use this to draw all the slot????? this.drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90 - 7, 0, 0, 104, 104); + this.bindTexture(this.getBackground()); } default -> this .drawTexturedModalRect(offsetX + 178, offsetY + this.ySize - 90, 178, this.ySize - 90, 68, 68); diff --git a/src/main/java/appeng/core/sync/packets/PacketValueConfig.java b/src/main/java/appeng/core/sync/packets/PacketValueConfig.java index be48157ff33..0f53bb9d203 100644 --- a/src/main/java/appeng/core/sync/packets/PacketValueConfig.java +++ b/src/main/java/appeng/core/sync/packets/PacketValueConfig.java @@ -28,6 +28,7 @@ import appeng.api.util.IConfigurableObject; import appeng.client.gui.implementations.GuiCraftingCPU; import appeng.container.AEBaseContainer; +import appeng.container.implementations.ContainerAdvancedNetworkTool; import appeng.container.implementations.ContainerCellWorkbench; import appeng.container.implementations.ContainerCraftConfirm; import appeng.container.implementations.ContainerCraftingCPU; @@ -169,6 +170,10 @@ public void serverPacketData(final INetworkInfo manager, final AppEngPacket pack if (this.Name.equals("NetworkTool") && this.Value.equals("Toggle")) { ((ContainerNetworkTool) c).toggleFacadeMode(); } + } else if (c instanceof ContainerAdvancedNetworkTool) { + if (this.Name.equals("AdvancedNetworkTool") && this.Value.equals("Toggle")) { + ((ContainerAdvancedNetworkTool) c).toggleFacadeMode(); + } } else if (c instanceof IConfigurableObject) { final IConfigManager cm = ((IConfigurableObject) c).getConfigManager(); diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 31a592dd30b..1d162d9852d 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -15,6 +15,8 @@ import java.util.LinkedList; import java.util.List; +import net.minecraft.item.ItemStack; + import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; @@ -48,6 +50,8 @@ import appeng.me.storage.ItemWatcher; import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.VoidCellInventory; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.storage.TileChest; import appeng.tile.storage.TileDrive; public class GridStorageCache implements IStorageGrid { @@ -382,6 +386,19 @@ private void updateBytesInfo() { for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { } + } else if (icp instanceof TileChest tc) { + // If there has any better way to get this handler... + ItemStack cell = ((AppEngInternalInventory) (tc.getInternalInventory())).getStackInSlot(1); + CellInventoryHandler handler = (CellInventoryHandler) AEApi.instance().registries().cell() + .getCellInventory(cell, tc, StorageChannel.ITEMS); + if (handler != null) { + itemBytesTotal += handler.getTotalBytes(); + itemBytesUsed += handler.getUsedBytes(); + } else { + // TODO + handler = (CellInventoryHandler) AEApi.instance().registries().cell() + .getCellInventory(cell, tc, StorageChannel.FLUIDS); + } } } } catch (Exception e) { diff --git a/src/main/java/appeng/server/ServerHelper.java b/src/main/java/appeng/server/ServerHelper.java index b545b840fbc..44e90ebcb58 100644 --- a/src/main/java/appeng/server/ServerHelper.java +++ b/src/main/java/appeng/server/ServerHelper.java @@ -30,6 +30,7 @@ import appeng.core.CommonHelper; import appeng.core.sync.AppEngPacket; import appeng.core.sync.network.NetworkHandler; +import appeng.items.tools.ToolAdvancedNetworkTool; import appeng.items.tools.ToolNetworkTool; import appeng.util.Platform; import cpw.mods.fml.common.FMLCommonHandler; @@ -125,7 +126,8 @@ protected CableRenderMode renderModeForPlayer(final EntityPlayer player) { for (int x = 0; x < InventoryPlayer.getHotbarSize(); x++) { final ItemStack is = player.inventory.getStackInSlot(x); - if (is != null && is.getItem() instanceof ToolNetworkTool) { + if (is != null && (is.getItem() instanceof ToolNetworkTool + || is.getItem() instanceof ToolAdvancedNetworkTool)) { final NBTTagCompound c = is.getTagCompound(); if (c != null && c.getBoolean("hideFacades")) { return CableRenderMode.CableView; diff --git a/src/main/java/appeng/tile/storage/TileChest.java b/src/main/java/appeng/tile/storage/TileChest.java index 8336fd253df..6714d4a7ee2 100644 --- a/src/main/java/appeng/tile/storage/TileChest.java +++ b/src/main/java/appeng/tile/storage/TileChest.java @@ -114,6 +114,10 @@ public TileChest() { this.setInternalPowerFlow(AccessRestriction.WRITE); } + public IMEInventory getInternal(final StorageChannel channel) throws ChestNoHandler { + return (IMEInventory) this.getHandler(channel); + } + @Override protected void PowerEvent(final PowerEventType x) { if (x == PowerEventType.REQUEST_POWER) { @@ -160,7 +164,7 @@ public int getCellCount() { return 1; } - private IMEInventoryHandler getHandler(final StorageChannel channel) throws ChestNoHandler { + public IMEInventoryHandler getHandler(final StorageChannel channel) throws ChestNoHandler { if (!this.isCached) { this.itemCell = null; this.fluidCell = null; diff --git a/src/main/resources/assets/appliedenergistics2/recipes/tools/network.recipe b/src/main/resources/assets/appliedenergistics2/recipes/tools/network.recipe index 432f8241dff..2c5c845eed5 100644 --- a/src/main/resources/assets/appliedenergistics2/recipes/tools/network.recipe +++ b/src/main/resources/assets/appliedenergistics2/recipes/tools/network.recipe @@ -6,6 +6,10 @@ shapeless= wrench monitor ae2:ItemMaterial.CalcProcessor oredictionary:chestWood -> ae2:ToolNetworkTool +shapeless= + ae2:ToolNetworkTool ae2:ItemPart.ConversionMonitor ae2:ItemMaterial.Cell64kPart ae2:ItemMaterial.CardCapacity + -> ae2:ToolAdvancedNetworkTool + shaped= ae2:ItemMaterial.EngProcessor oredictionary:ingotIron oredictionary:ingotIron, oredictionary:ingotGold oredictionary:dustRedstone oredictionary:ingotGold From 8369c39d34e8874286e4ac087907e3a8ff985e4c Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Fri, 10 Nov 2023 12:02:42 +0800 Subject: [PATCH 27/34] Fix the wrong info when cell in ME chest --- .../appeng/me/cache/GridStorageCache.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 1d162d9852d..d74361ae941 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -48,6 +48,7 @@ import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.DriveWatcher; import appeng.me.storage.ItemWatcher; +import appeng.me.storage.MEInventoryHandler; import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.VoidCellInventory; import appeng.tile.inventory.AppEngInternalInventory; @@ -374,8 +375,8 @@ private void updateBytesInfo() { if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { continue; } - // exclude creative cell if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { + // exclude creative cell if (handler.getCellInv() != null) { itemBytesTotal += handler.getTotalBytes(); itemBytesUsed += handler.getUsedBytes(); @@ -389,14 +390,20 @@ private void updateBytesInfo() { } else if (icp instanceof TileChest tc) { // If there has any better way to get this handler... ItemStack cell = ((AppEngInternalInventory) (tc.getInternalInventory())).getStackInSlot(1); - CellInventoryHandler handler = (CellInventoryHandler) AEApi.instance().registries().cell() - .getCellInventory(cell, tc, StorageChannel.ITEMS); - if (handler != null) { - itemBytesTotal += handler.getTotalBytes(); - itemBytesUsed += handler.getUsedBytes(); + MEInventoryHandler meih = (MEInventoryHandler) AEApi.instance() + .registries().cell().getCellInventory(cell, tc, StorageChannel.ITEMS); + // exclude void cell + if (meih instanceof VoidCellInventory) { + break; + } else if (meih instanceof CellInventoryHandler handler) { + // exclude creative cell + if (handler.getCellInv() != null) { + itemBytesTotal += handler.getTotalBytes(); + itemBytesUsed += handler.getUsedBytes(); + } } else { // TODO - handler = (CellInventoryHandler) AEApi.instance().registries().cell() + meih = (MEInventoryHandler) AEApi.instance().registries().cell() .getCellInventory(cell, tc, StorageChannel.FLUIDS); } } From 781e19fe4fa8e2395db8f6cf866855bbe1d9fc5e Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Sun, 12 Nov 2023 02:47:10 +0800 Subject: [PATCH 28/34] Add external buttons for advanced network status Actual function still working on it --- build.gradle | 1 + src/main/java/appeng/api/config/CellType.java | 9 ++++++++ src/main/java/appeng/api/config/Settings.java | 4 +++- .../gui/implementations/GuiNetworkStatus.java | 14 ++++++++++++ .../client/gui/widgets/GuiImgButton.java | 21 ++++++++++++++++++ src/main/java/appeng/core/AEConfig.java | 11 +++++++++ .../core/localization/ButtonToolTips.java | 7 +++++- .../appliedenergistics2/lang/en_US.lang | 5 +++++ .../appliedenergistics2/lang/zh_CN.lang | 5 +++++ .../appliedenergistics2/lang/zh_TW.lang | 5 +++++ .../textures/guis/states.png | Bin 18891 -> 18651 bytes 11 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/main/java/appeng/api/config/CellType.java diff --git a/build.gradle b/build.gradle index f3a7fa27881..d7d99ef1a4a 100644 --- a/build.gradle +++ b/build.gradle @@ -906,6 +906,7 @@ runClient17Task.configure { mainClass = "GradleStart" username = minecraft.username userUUID = minecraft.userUUID + jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" } def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") diff --git a/src/main/java/appeng/api/config/CellType.java b/src/main/java/appeng/api/config/CellType.java new file mode 100644 index 00000000000..5ff7ee31689 --- /dev/null +++ b/src/main/java/appeng/api/config/CellType.java @@ -0,0 +1,9 @@ +package appeng.api.config; + +public enum CellType { + + ITEM, + FLUID, + ESSENTIA + +} diff --git a/src/main/java/appeng/api/config/Settings.java b/src/main/java/appeng/api/config/Settings.java index 155f8eca5c2..bcc58232595 100644 --- a/src/main/java/appeng/api/config/Settings.java +++ b/src/main/java/appeng/api/config/Settings.java @@ -68,7 +68,9 @@ public enum Settings { ADVANCED_BLOCKING_MODE(EnumSet.allOf(AdvancedBlockingMode.class)), - CRAFTING_MODE(EnumSet.allOf(CraftingMode.class)); + CRAFTING_MODE(EnumSet.allOf(CraftingMode.class)), + + CELL_TYPE(EnumSet.allOf(CellType.class)); private final EnumSet> values; diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index d0e74157194..ff0a23bc6e7 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -44,8 +44,10 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource { private final ItemRepo repo; private final int rows = 4; private GuiImgButton units; + private GuiImgButton cell; private int tooltip = -1; private final DecimalFormat df; + private final boolean isAdvanced; public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkTool te) { super(new ContainerNetworkStatus(inventoryPlayer, te)); @@ -57,6 +59,7 @@ public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkToo this.ySize = 183; this.xSize = 195; this.repo.setRowSize(5); + this.isAdvanced = te.getSize() != 3; } @Override @@ -68,6 +71,9 @@ protected void actionPerformed(final GuiButton btn) { if (btn == this.units) { AEConfig.instance.nextPowerUnit(backwards); this.units.set(AEConfig.instance.selectedPowerUnit()); + } else if (btn == this.cell) { + AEConfig.instance.nextCellType(backwards); + this.cell.set(AEConfig.instance.selectedCellType()); } } @@ -81,6 +87,14 @@ public void initGui() { Settings.POWER_UNITS, AEConfig.instance.selectedPowerUnit()); this.buttonList.add(this.units); + if (this.isAdvanced) { + this.cell = new GuiImgButton( + this.guiLeft - 18, + this.guiTop + 28, + Settings.CELL_TYPE, + AEConfig.instance.selectedCellType()); + this.buttonList.add(this.cell); + } } @Override diff --git a/src/main/java/appeng/client/gui/widgets/GuiImgButton.java b/src/main/java/appeng/client/gui/widgets/GuiImgButton.java index bf28fc67d26..11e68b39163 100644 --- a/src/main/java/appeng/client/gui/widgets/GuiImgButton.java +++ b/src/main/java/appeng/client/gui/widgets/GuiImgButton.java @@ -23,6 +23,7 @@ import appeng.api.config.AccessRestriction; import appeng.api.config.ActionItems; import appeng.api.config.AdvancedBlockingMode; +import appeng.api.config.CellType; import appeng.api.config.CondenserOutput; import appeng.api.config.CraftingMode; import appeng.api.config.CraftingStatus; @@ -636,6 +637,26 @@ public GuiImgButton(final int x, final int y, final Enum idx, final Enum val) { ButtonToolTips.CraftingModeIgnoreMissing, ButtonToolTips.CraftingModeIgnoreMissingDesc); this.registerApp(16 * 6 + 5, Settings.ACTIONS, ActionItems.EXTRA_OPTIONS, ButtonToolTips.ExtraOptions, ""); + + this.registerApp( + 16 * 10 + 6, + Settings.CELL_TYPE, + CellType.ITEM, + ButtonToolTips.SwitchBytesInfo, + ButtonToolTips.SwitchBytesInfo_Item); + this.registerApp( + 16 * 10 + 7, + Settings.CELL_TYPE, + CellType.FLUID, + ButtonToolTips.SwitchBytesInfo, + ButtonToolTips.SwitchBytesInfo_Fluid); + this.registerApp( + 16 * 10 + 8, + Settings.CELL_TYPE, + CellType.ESSENTIA, + ButtonToolTips.SwitchBytesInfo, + ButtonToolTips.SwitchBytesInfo_Essentia); + } } diff --git a/src/main/java/appeng/core/AEConfig.java b/src/main/java/appeng/core/AEConfig.java index 11ff9a63164..2e33987dc3f 100644 --- a/src/main/java/appeng/core/AEConfig.java +++ b/src/main/java/appeng/core/AEConfig.java @@ -18,6 +18,7 @@ import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; +import appeng.api.config.CellType; import appeng.api.config.CondenserOutput; import appeng.api.config.CraftingStatus; import appeng.api.config.PowerMultiplier; @@ -100,6 +101,7 @@ public final class AEConfig extends Configuration implements IConfigurableObject public int[] meteoriteDimensionWhitelist = { 0 }; public int craftingCalculationTimePerTick = 5; PowerUnits selectedPowerUnit = PowerUnits.AE; + CellType selectedCellType = CellType.ITEM; private double WirelessBaseCost = 8; private double WirelessCostMultiplier = 1; private double WirelessTerminalDrainMultiplier = 1; @@ -536,9 +538,18 @@ public PowerUnits selectedPowerUnit() { return this.selectedPowerUnit; } + public CellType selectedCellType() { + return this.selectedCellType; + } + public void nextPowerUnit(final boolean backwards) { this.selectedPowerUnit = Platform .rotateEnum(this.selectedPowerUnit, backwards, Settings.POWER_UNITS.getPossibleValues()); this.save(); } + + public void nextCellType(final boolean backwards) { + this.selectedCellType = Platform + .rotateEnum(this.selectedCellType, backwards, Settings.CELL_TYPE.getPossibleValues()); + } } diff --git a/src/main/java/appeng/core/localization/ButtonToolTips.java b/src/main/java/appeng/core/localization/ButtonToolTips.java index 35b644d661f..f0aedc0e26d 100644 --- a/src/main/java/appeng/core/localization/ButtonToolTips.java +++ b/src/main/java/appeng/core/localization/ButtonToolTips.java @@ -185,7 +185,12 @@ public enum ButtonToolTips { CraftingModeStandardDesc, CraftingModeIgnoreMissing, CraftingModeIgnoreMissingDesc, - ExtraOptions; + ExtraOptions, + + SwitchBytesInfo, + SwitchBytesInfo_Item, + SwitchBytesInfo_Fluid, + SwitchBytesInfo_Essentia; private final String root; diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 15fcf70e7c1..d7cb3707bc9 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -453,6 +453,11 @@ gui.tooltips.appliedenergistics2.CraftingModeIgnoreMissingDesc=Starts craft even gui.tooltips.appliedenergistics2.ExtraOptions=Extra Options +gui.tooltips.appliedenergistics2.SwitchBytesInfo=Cell Info +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Item=Item +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Fluid=Fluid +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Essentia=Essentia + # Units gui.appliedenergistics2.units.appliedenergstics=AE gui.appliedenergistics2.units.ic2=Energy Units diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 524875d4f8f..b9fad881fc2 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -420,6 +420,11 @@ gui.tooltips.appliedenergistics2.InsertionModePreferEmptyDesc=类似默认模式 gui.tooltips.appliedenergistics2.InsertionModeOnlyEmpty=只向空槽输出 gui.tooltips.appliedenergistics2.InsertionModeOnlyEmptyDesc=从前到后,不堆叠 +gui.tooltips.appliedenergistics2.SwitchBytesInfo=存储信息 +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Item=物品 +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Fluid=流体 +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Essentia=源质 + # Units gui.appliedenergistics2.units.appliedenergstics=AE gui.appliedenergistics2.units.ic2=EU diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang index 5e14defcabe..93b1c8462f6 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang @@ -268,6 +268,11 @@ gui.tooltips.appliedenergistics2.TerminalStyle_Tall=長 gui.tooltips.appliedenergistics2.TerminalStyle_Small=短 gui.tooltips.appliedenergistics2.CraftingStatus=合成狀態 +gui.tooltips.appliedenergistics2.SwitchBytesInfo=存儲信息 +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Item=物品 +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Fluid=流體 +gui.tooltips.appliedenergistics2.SwitchBytesInfo_Essentia=源質 + gui.appliedenergistics2.units.appliedenergstics=AE gui.appliedenergistics2.units.ic2=EU gui.appliedenergistics2.units.universalelectricity=KJ diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/states.png b/src/main/resources/assets/appliedenergistics2/textures/guis/states.png index fef9c0f46df531fa1b019cdab913bab465038309..7b477a79418e071f94bdc315adaf4eb7ec3b310e 100644 GIT binary patch literal 18651 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 Date: Sun, 12 Nov 2023 02:50:03 +0800 Subject: [PATCH 29/34] merge with main branch Update Settings.java --- build.gradle | 1 - src/main/java/appeng/api/config/Settings.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index d7d99ef1a4a..f3a7fa27881 100644 --- a/build.gradle +++ b/build.gradle @@ -906,7 +906,6 @@ runClient17Task.configure { mainClass = "GradleStart" username = minecraft.username userUUID = minecraft.userUUID - jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" } def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") diff --git a/src/main/java/appeng/api/config/Settings.java b/src/main/java/appeng/api/config/Settings.java index 4f3d9224b26..113840ee590 100644 --- a/src/main/java/appeng/api/config/Settings.java +++ b/src/main/java/appeng/api/config/Settings.java @@ -70,7 +70,7 @@ public enum Settings { CRAFTING_MODE(EnumSet.allOf(CraftingMode.class)), - CELL_TYPE(EnumSet.allOf(CellType.class)); + CELL_TYPE(EnumSet.allOf(CellType.class)), STICKY_MODE(EnumSet.of(YesNo.YES, YesNo.NO)); From 2b999db6fa723e3bda1b6e4d456015e2138bbbac Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Sun, 12 Nov 2023 09:01:05 +0800 Subject: [PATCH 30/34] Apply spotless --- src/main/java/appeng/api/config/Settings.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/appeng/api/config/Settings.java b/src/main/java/appeng/api/config/Settings.java index 113840ee590..57bef676ce2 100644 --- a/src/main/java/appeng/api/config/Settings.java +++ b/src/main/java/appeng/api/config/Settings.java @@ -74,7 +74,6 @@ public enum Settings { STICKY_MODE(EnumSet.of(YesNo.YES, YesNo.NO)); - private final EnumSet> values; Settings(@Nonnull final EnumSet> possibleOptions) { From ddb9cc3ebd17645f8a00bada374ef0598fef3749 Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Mon, 13 Nov 2023 04:21:12 +0800 Subject: [PATCH 31/34] Add external Gui for advanced network tool --- build.gradle | 1 + .../api/storage/ICellCacheRegistry.java | 2 + .../gui/implementations/GuiNetworkStatus.java | 275 ++++++++++++------ .../ContainerNetworkStatus.java | 160 ++++++++-- src/main/java/appeng/core/AEConfig.java | 1 + .../appeng/core/localization/GuiColors.java | 4 +- .../appeng/core/localization/GuiText.java | 7 + .../appeng/me/cache/GridStorageCache.java | 141 ++++++++- .../me/storage/CellInventoryHandler.java | 5 + .../appliedenergistics2/lang/en_US.lang | 8 + .../appliedenergistics2/lang/zh_CN.lang | 7 + .../appliedenergistics2/lang/zh_TW.lang | 7 + 12 files changed, 496 insertions(+), 122 deletions(-) diff --git a/build.gradle b/build.gradle index f3a7fa27881..4f779070996 100644 --- a/build.gradle +++ b/build.gradle @@ -906,6 +906,7 @@ runClient17Task.configure { mainClass = "GradleStart" username = minecraft.username userUUID = minecraft.userUUID +// jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" } def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") diff --git a/src/main/java/appeng/api/storage/ICellCacheRegistry.java b/src/main/java/appeng/api/storage/ICellCacheRegistry.java index 75c57585282..df595bb2efd 100644 --- a/src/main/java/appeng/api/storage/ICellCacheRegistry.java +++ b/src/main/java/appeng/api/storage/ICellCacheRegistry.java @@ -18,6 +18,8 @@ public interface ICellCacheRegistry { long getUsedTypes(); + int getCellStatus(); + StorageChannel getCellType(); } diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index ff0a23bc6e7..e3034703dc7 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -48,6 +48,7 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource { private int tooltip = -1; private final DecimalFormat df; private final boolean isAdvanced; + private boolean isConsume; public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkTool te) { super(new ContainerNetworkStatus(inventoryPlayer, te)); @@ -60,6 +61,7 @@ public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkToo this.xSize = 195; this.repo.setRowSize(5); this.isAdvanced = te.getSize() != 3; + this.isConsume = true; } @Override @@ -69,18 +71,25 @@ protected void actionPerformed(final GuiButton btn) { final boolean backwards = Mouse.isButtonDown(1); if (btn == this.units) { - AEConfig.instance.nextPowerUnit(backwards); - this.units.set(AEConfig.instance.selectedPowerUnit()); + if (this.isConsume) { + AEConfig.instance.nextPowerUnit(backwards); + this.units.set(AEConfig.instance.selectedPowerUnit()); + } else { + this.isConsume = !this.isConsume; + } } else if (btn == this.cell) { - AEConfig.instance.nextCellType(backwards); - this.cell.set(AEConfig.instance.selectedCellType()); + if (!this.isConsume) { + AEConfig.instance.nextCellType(backwards); + this.cell.set(AEConfig.instance.selectedCellType()); + } else { + this.isConsume = !this.isConsume; + } } } @Override public void initGui() { super.initGui(); - this.units = new GuiImgButton( this.guiLeft - 18, this.guiTop + 8, @@ -131,6 +140,109 @@ public void drawScreen(final int mouseX, final int mouseY, final float btn) { @Override public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + if (this.isConsume) drawConsume(); + else { + switch (AEConfig.instance.selectedCellType()) { + case ITEM -> drawItemInfo(); + case FLUID -> drawFluidInfo(); + case ESSENTIA -> drawEssentiaInfo(); + } + + } + } + + @Override + public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + this.bindTexture("guis/networkstatus.png"); + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + } + + public void postUpdate(final List list) { + this.repo.clear(); + + for (final IAEItemStack is : list) { + this.repo.postUpdate(is); + } + + this.repo.updateView(); + this.setScrollBar(); + } + + private void setScrollBar() { + final int size = this.repo.size(); + this.getScrollBar().setTop(39).setLeft(175).setHeight(78); + this.getScrollBar().setRange(0, (size + 4) / 5 - this.rows, 1); + } + + // @Override - NEI + public List handleItemTooltip(final ItemStack stack, final int mouseX, final int mouseY, + final List currentToolTip) { + if (stack != null) { + final Slot s = this.getSlot(mouseX, mouseY); + if (s instanceof SlotME) { + IAEItemStack myStack = null; + + try { + final SlotME theSlotField = (SlotME) s; + myStack = theSlotField.getAEStack(); + } catch (final Throwable ignore) {} + + if (myStack != null) { + while (currentToolTip.size() > 1) { + currentToolTip.remove(1); + } + } + } + } + return currentToolTip; + } + + // Vanilla version... + protected void drawItemStackTooltip(final ItemStack stack, final int x, final int y) { + final Slot s = this.getSlot(x, y); + if (s instanceof SlotME && stack != null) { + IAEItemStack myStack = null; + + try { + final SlotME theSlotField = (SlotME) s; + myStack = theSlotField.getAEStack(); + } catch (final Throwable ignore) {} + + if (myStack != null) { + final List currentToolTip = stack + .getTooltip(this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips); + + while (currentToolTip.size() > 1) { + currentToolTip.remove(1); + } + + currentToolTip.add(GuiText.Installed.getLocal() + ": " + (myStack.getStackSize())); + currentToolTip.add( + GuiText.EnergyDrain.getLocal() + ": " + + Platform.formatPowerLong(myStack.getCountRequestable(), true)); + + this.drawTooltip(x, y, 0, join(currentToolTip, "\n")); + } + } + // super.drawItemStackTooltip( stack, x, y ); + } + + @Override + public Enum getSortBy() { + return SortOrder.NAME; + } + + @Override + public Enum getSortDir() { + return SortDir.ASCENDING; + } + + @Override + public Enum getSortDisplay() { + return ViewItems.ALL; + } + + private void drawConsume() { final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; String tempStr; this.fontRendererObj @@ -260,96 +372,81 @@ public void drawFG(final int offsetX, final int offsetY, final int mouseX, final if (this.tooltip >= 0 && toolTip.length() > 0) { this.drawTooltip(toolPosX, toolPosY + 10, 0, toolTip); } - } - @Override - public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { - this.bindTexture("guis/networkstatus.png"); - this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); } - public void postUpdate(final List list) { - this.repo.clear(); - - for (final IAEItemStack is : list) { - this.repo.postUpdate(is); - } - - this.repo.updateView(); - this.setScrollBar(); - } - - private void setScrollBar() { - final int size = this.repo.size(); - this.getScrollBar().setTop(39).setLeft(175).setHeight(78); - this.getScrollBar().setRange(0, (size + 4) / 5 - this.rows, 1); - } - - // @Override - NEI - public List handleItemTooltip(final ItemStack stack, final int mouseX, final int mouseY, - final List currentToolTip) { - if (stack != null) { - final Slot s = this.getSlot(mouseX, mouseY); - if (s instanceof SlotME) { - IAEItemStack myStack = null; - - try { - final SlotME theSlotField = (SlotME) s; - myStack = theSlotField.getAEStack(); - } catch (final Throwable ignore) {} - - if (myStack != null) { - while (currentToolTip.size() > 1) { - currentToolTip.remove(1); - } - } - } - } - return currentToolTip; - } - - // Vanilla version... - protected void drawItemStackTooltip(final ItemStack stack, final int x, final int y) { - final Slot s = this.getSlot(x, y); - if (s instanceof SlotME && stack != null) { - IAEItemStack myStack = null; - - try { - final SlotME theSlotField = (SlotME) s; - myStack = theSlotField.getAEStack(); - } catch (final Throwable ignore) {} - - if (myStack != null) { - final List currentToolTip = stack - .getTooltip(this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips); - - while (currentToolTip.size() > 1) { - currentToolTip.remove(1); - } - - currentToolTip.add(GuiText.Installed.getLocal() + ": " + (myStack.getStackSize())); - currentToolTip.add( - GuiText.EnergyDrain.getLocal() + ": " - + Platform.formatPowerLong(myStack.getCountRequestable(), true)); - - this.drawTooltip(x, y, 0, join(currentToolTip, "\n")); - } - } - // super.drawItemStackTooltip( stack, x, y ); - } - - @Override - public Enum getSortBy() { - return SortOrder.NAME; + private void drawItemInfo() { + final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; + this.fontRendererObj + .drawString(GuiText.NetworkBytesDetails.getLocal(), 8, 6, GuiColors.DefaultBlack.getColor()); + this.fontRendererObj.drawString( + GuiText.NetworkItemCellCount.getLocal() + " : " + ns.getItemCellCount(), + 13, + 16, + GuiColors.DefaultBlack.getColor()); + this.fontRendererObj.drawString( + GuiText.Green.getLocal() + " : " + + ns.getItemCellG() + + " " + + GuiText.Orange.getLocal() + + " : " + + ns.getItemCellO() + + " " + + GuiText.Red.getLocal() + + " : " + + ns.getItemCellR(), + 13, + 26, + GuiColors.DefaultBlack.getColor()); } - @Override - public Enum getSortDir() { - return SortDir.ASCENDING; + private void drawFluidInfo() { + final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; + this.fontRendererObj + .drawString(GuiText.NetworkBytesDetails.getLocal(), 8, 6, GuiColors.DefaultBlack.getColor()); + this.fontRendererObj.drawString( + GuiText.NetworkFluidCellCount.getLocal() + " : " + ns.getFluidCellCount(), + 13, + 16, + GuiColors.DefaultBlack.getColor()); + this.fontRendererObj.drawString( + GuiText.Green.getLocal() + " : " + + ns.getFluidCellG() + + " " + + GuiText.Orange.getLocal() + + " : " + + ns.getFluidCellO() + + " " + + GuiText.Red.getLocal() + + " : " + + ns.getFluidCellR(), + 13, + 26, + GuiColors.DefaultBlack.getColor()); } - @Override - public Enum getSortDisplay() { - return ViewItems.ALL; + private void drawEssentiaInfo() { + final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; + this.fontRendererObj + .drawString(GuiText.NetworkBytesDetails.getLocal(), 8, 6, GuiColors.DefaultBlack.getColor()); + this.fontRendererObj.drawString( + GuiText.NetworkEssentiaCellCount.getLocal() + " : " + ns.getEssentiaCellCount(), + 13, + 16, + GuiColors.DefaultBlack.getColor()); + this.fontRendererObj.drawString( + GuiText.Green.getLocal() + " : " + + ns.getEssentiaCellG() + + " " + + GuiText.Orange.getLocal() + + " : " + + ns.getEssentiaCellO() + + " " + + GuiText.Red.getLocal() + + " : " + + ns.getEssentiaCellR(), + 13, + 26, + GuiColors.DefaultBlack.getColor()); } } diff --git a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java index 946fe2a33b7..ebd4389d9ff 100644 --- a/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java +++ b/src/main/java/appeng/container/implementations/ContainerNetworkStatus.java @@ -58,17 +58,71 @@ public class ContainerNetworkStatus extends AEBaseContainer { public long itemBytesUsed; @GuiSync(6) - public long fluidBytesTotal; + public long itemTypesTotal; @GuiSync(7) - public long fluidBytesUsed; + public long itemTypesUsed; @GuiSync(8) - public long essentiaBytesTotal; + public long itemCellG; @GuiSync(9) + public long itemCellO; + + @GuiSync(10) + public long itemCellR; + + @GuiSync(11) + public long fluidBytesTotal; + + @GuiSync(12) + public long fluidBytesUsed; + + @GuiSync(13) + public long fluidTypesTotal; + + @GuiSync(14) + public long fluidTypesUsed; + + @GuiSync(15) + public long fluidCellG; + + @GuiSync(16) + public long fluidCellO; + + @GuiSync(17) + public long fluidCellR; + + @GuiSync(18) + public long essentiaBytesTotal; + + @GuiSync(19) public long essentiaBytesUsed; + @GuiSync(20) + public long essentiaTypesTotal; + + @GuiSync(21) + public long essentiaTypesUsed; + + @GuiSync(22) + public long essentiaCellG; + + @GuiSync(23) + public long essentiaCellO; + + @GuiSync(24) + public long essentiaCellR; + + @GuiSync(25) + public long itemCellCount; + + @GuiSync(26) + public long fluidCellCount; + + @GuiSync(27) + public long essentiaCellCount; + private IGrid network; private int delay = 40; @@ -143,12 +197,21 @@ public void detectAndSendChanges() { } final GridStorageCache sg = this.network.getCache(IStorageGrid.class); if (sg != null) { - this.setItemBytesTotal(sg.getItemBytesTotal()); - this.setItemBytesUsed(sg.getItemBytesUsed()); - this.setFluidBytesTotal(sg.getFluidBytesTotal()); - this.setFluidBytesUsed(sg.getFluidBytesUsed()); - this.setEssentiaBytesTotal(sg.getEssentiaBytesTotal()); - this.setEssentiaBytesUsed(sg.getEssentiaBytesUsed()); + this.itemBytesUsed = sg.getItemBytesUsed(); + this.itemBytesTotal = sg.getItemBytesTotal(); + this.itemCellG = sg.getItemCellG(); + this.itemCellO = sg.getItemCellO(); + this.itemCellR = sg.getItemCellR(); + this.itemCellCount = sg.getItemCellCount(); + + this.itemTypesUsed = sg.getItemTypesUsed(); + this.itemTypesTotal = sg.getItemTypesTotal(); + + this.fluidBytesUsed = sg.getFluidBytesUsed(); + this.fluidBytesTotal = sg.getFluidBytesTotal(); + + this.essentiaBytesUsed = sg.getEssentiaBytesUsed(); + this.essentiaBytesTotal = sg.getEssentiaBytesTotal(); } } super.detectAndSendChanges(); @@ -187,35 +250,59 @@ private void setPowerUsage(final long powerUsage) { } public long getItemBytesTotal() { - return this.itemBytesTotal; + return itemBytesTotal; } public long getItemBytesUsed() { - return this.itemBytesUsed; + return itemBytesUsed; + } + + public long getItemTypesTotal() { + return itemTypesTotal; } - public void setItemBytesTotal(final long itemBytesTotal) { - this.itemBytesTotal = itemBytesTotal; + public long getItemTypesUsed() { + return itemTypesUsed; } - public void setItemBytesUsed(final long itemBytesUsed) { - this.itemBytesUsed = itemBytesUsed; + public long getItemCellG() { + return itemCellG; + } + + public long getItemCellO() { + return itemCellO; + } + + public long getItemCellR() { + return itemCellR; } public long getFluidBytesTotal() { - return this.fluidBytesTotal; + return fluidBytesTotal; } public long getFluidBytesUsed() { - return this.fluidBytesUsed; + return fluidBytesUsed; + } + + public long getFluidTypesTotal() { + return fluidTypesTotal; } - public void setFluidBytesTotal(final long fluidBytesTotal) { - this.fluidBytesTotal = fluidBytesTotal; + public long getFluidTypesUsed() { + return fluidTypesUsed; } - public void setFluidBytesUsed(final long fluidBytesUsed) { - this.fluidBytesUsed = fluidBytesUsed; + public long getFluidCellG() { + return fluidCellG; + } + + public long getFluidCellO() { + return fluidCellO; + } + + public long getFluidCellR() { + return fluidCellR; } public long getEssentiaBytesTotal() { @@ -226,12 +313,35 @@ public long getEssentiaBytesUsed() { return essentiaBytesUsed; } - public void setEssentiaBytesTotal(long essentiaBytesTotal) { - this.essentiaBytesTotal = essentiaBytesTotal; + public long getEssentiaTypesTotal() { + return essentiaTypesTotal; + } + + public long getEssentiaTypesUsed() { + return essentiaTypesUsed; + } + + public long getEssentiaCellG() { + return essentiaCellG; + } + + public long getEssentiaCellO() { + return essentiaCellO; + } + + public long getEssentiaCellR() { + return essentiaCellR; } - public void setEssentiaBytesUsed(long essentiaBytesUsed) { - this.essentiaBytesUsed = essentiaBytesUsed; + public long getItemCellCount() { + return itemCellCount; } + public long getFluidCellCount() { + return fluidCellCount; + } + + public long getEssentiaCellCount() { + return essentiaCellCount; + } } diff --git a/src/main/java/appeng/core/AEConfig.java b/src/main/java/appeng/core/AEConfig.java index 2e33987dc3f..dd5fca37c38 100644 --- a/src/main/java/appeng/core/AEConfig.java +++ b/src/main/java/appeng/core/AEConfig.java @@ -552,4 +552,5 @@ public void nextCellType(final boolean backwards) { this.selectedCellType = Platform .rotateEnum(this.selectedCellType, backwards, Settings.CELL_TYPE.getPossibleValues()); } + } diff --git a/src/main/java/appeng/core/localization/GuiColors.java b/src/main/java/appeng/core/localization/GuiColors.java index 9d7e3ae8f84..b3b21a82582 100644 --- a/src/main/java/appeng/core/localization/GuiColors.java +++ b/src/main/java/appeng/core/localization/GuiColors.java @@ -86,6 +86,7 @@ public enum GuiColors { IOPortInventory(0x404040), NetworkStatusDetails(0x404040), + NetworkBytesDetails(0x404040), NetworkStatusStoredPower(0x404040), NetworkStatusMaxPower(0x404040), NetworkStatusPowerInputRate(0x404040), @@ -140,7 +141,8 @@ public enum GuiColors { NEIGrindstoneNoSecondOutput(0x000000), MEMonitorableTitle(0x404040), - MEMonitorableInventory(0x404040); + MEMonitorableInventory(0x404040), + DefaultBlack(0x404040); private final String root; private final int color; diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index 3cbbf69ba6d..fba5a21ddb6 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -210,6 +210,13 @@ public enum GuiText { Deprecated, // Network bytes status + NetworkItemCellCount, + NetworkFluidCellCount, + NetworkEssentiaCellCount, + Green, + Orange, + Red, + NetworkBytesDetails, Items, Fluids, Essentias; diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index d74361ae941..883d5478f42 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -69,10 +69,28 @@ public class GridStorageCache implements IStorageGrid { private NetworkInventoryHandler myFluidNetwork; private long itemBytesTotal; private long itemBytesUsed; + private long itemTypesTotal; + private long itemTypesUsed; + private long itemCellG; + private long itemCellO; + private long itemCellR; + private long itemCellCount; private long fluidBytesTotal; private long fluidBytesUsed; + private long fluidTypesTotal; + private long fluidTypesUsed; + private long fluidCellG; + private long fluidCellO; + private long fluidCellR; + private long fluidCellCount; private long essentiaBytesTotal; private long essentiaBytesUsed; + private long essentiaTypesTotal; + private long essentiaTypesUsed; + private long essentiaCellG; + private long essentiaCellO; + private long essentiaCellR; + private long essentiaCellCount; private int ticksCount; private int networkBytesUpdateFrequency; @@ -360,12 +378,7 @@ public void applyChanges() { } private void updateBytesInfo() { - this.itemBytesTotal = 0; - this.itemBytesUsed = 0; - this.fluidBytesTotal = 0; - this.fluidBytesUsed = 0; - this.essentiaBytesTotal = 0; - this.essentiaBytesUsed = 0; + this.resetCellInfo(); try { for (ICellProvider icp : this.activeCellProviders) { if (icp instanceof TileDrive) { @@ -380,8 +393,16 @@ private void updateBytesInfo() { if (handler.getCellInv() != null) { itemBytesTotal += handler.getTotalBytes(); itemBytesUsed += handler.getUsedBytes(); + switch (handler.getStatusForCell()) { + case 1 -> itemCellG++; + case 2 -> itemCellO++; + case 3 -> itemCellR++; + } + itemTypesTotal += handler.getTotalTypes(); + itemTypesUsed += handler.getUsedTypes(); } } + itemCellCount++; } // TODO for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.FLUIDS)) { @@ -394,13 +415,21 @@ private void updateBytesInfo() { .registries().cell().getCellInventory(cell, tc, StorageChannel.ITEMS); // exclude void cell if (meih instanceof VoidCellInventory) { - break; + continue; } else if (meih instanceof CellInventoryHandler handler) { // exclude creative cell if (handler.getCellInv() != null) { itemBytesTotal += handler.getTotalBytes(); itemBytesUsed += handler.getUsedBytes(); + switch (handler.getStatusForCell()) { + case 1 -> itemCellG++; + case 2 -> itemCellO++; + case 3 -> itemCellR++; + } + itemTypesTotal += handler.getTotalTypes(); + itemTypesUsed += handler.getUsedTypes(); } + itemCellCount++; } else { // TODO meih = (MEInventoryHandler) AEApi.instance().registries().cell() @@ -413,6 +442,33 @@ private void updateBytesInfo() { } } + private void resetCellInfo() { + this.itemBytesTotal = 0; + this.itemBytesUsed = 0; + this.itemTypesTotal = 0; + this.itemTypesUsed = 0; + this.itemCellG = 0; + this.itemCellO = 0; + this.itemCellR = 0; + this.itemCellCount = 0; + this.fluidBytesTotal = 0; + this.fluidBytesUsed = 0; + this.fluidTypesTotal = 0; + this.fluidTypesUsed = 0; + this.fluidCellG = 0; + this.fluidCellO = 0; + this.fluidCellR = 0; + this.fluidCellCount = 0; + this.essentiaBytesTotal = 0; + this.essentiaBytesUsed = 0; + this.essentiaTypesTotal = 0; + this.essentiaTypesUsed = 0; + this.essentiaCellG = 0; + this.essentiaCellO = 0; + this.essentiaCellR = 0; + this.essentiaCellCount = 0; + } + public long getItemBytesTotal() { return itemBytesTotal; } @@ -421,6 +477,30 @@ public long getItemBytesUsed() { return itemBytesUsed; } + public long getItemTypesTotal() { + return itemTypesTotal; + } + + public long getItemTypesUsed() { + return itemTypesUsed; + } + + public long getItemCellG() { + return itemCellG; + } + + public long getItemCellO() { + return itemCellO; + } + + public long getItemCellR() { + return itemCellR; + } + + public long getItemCellCount() { + return itemCellCount; + } + public long getFluidBytesTotal() { return fluidBytesTotal; } @@ -429,6 +509,30 @@ public long getFluidBytesUsed() { return fluidBytesUsed; } + public long getFluidTypesTotal() { + return fluidTypesTotal; + } + + public long getFluidTypesUsed() { + return fluidTypesUsed; + } + + public long getFluidCellG() { + return fluidCellG; + } + + public long getFluidCellO() { + return fluidCellO; + } + + public long getFluidCellR() { + return fluidCellR; + } + + public long getFluidCellCount() { + return fluidCellCount; + } + public long getEssentiaBytesTotal() { return essentiaBytesTotal; } @@ -437,4 +541,27 @@ public long getEssentiaBytesUsed() { return essentiaBytesUsed; } + public long getEssentiaTypesTotal() { + return essentiaTypesTotal; + } + + public long getEssentiaTypesUsed() { + return essentiaTypesUsed; + } + + public long getEssentiaCellG() { + return essentiaCellG; + } + + public long getEssentiaCellO() { + return essentiaCellO; + } + + public long getEssentiaCellR() { + return essentiaCellR; + } + + public long getEssentiaCellCount() { + return essentiaCellCount; + } } diff --git a/src/main/java/appeng/me/storage/CellInventoryHandler.java b/src/main/java/appeng/me/storage/CellInventoryHandler.java index c34f6081a9b..76ccaf61212 100644 --- a/src/main/java/appeng/me/storage/CellInventoryHandler.java +++ b/src/main/java/appeng/me/storage/CellInventoryHandler.java @@ -155,6 +155,11 @@ public long getUsedTypes() { return this.getCellInv().getStoredItemTypes(); } + @Override + public int getCellStatus() { + return this.getStatusForCell(); + } + @Override public StorageChannel getCellType() { return StorageChannel.ITEMS; diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 02254508669..73325aca1da 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -274,9 +274,17 @@ gui.appliedenergistics2.Nothing=Nothing gui.appliedenergistics2.VoidCellTooltip=Deletes §4everything§7 stored on it gui.appliedenergistics2.Deprecated=Deprecated, will be removed soon! +gui.appliedenergistics2.NetworkBytesDetails=Network Bytes Details gui.appliedenergistics2.Items=Items gui.appliedenergistics2.Fluids=Fluids gui.appliedenergistics2.Essentias=Essen +gui.appliedenergistics2.NetworkItemCellCount=Network Item Cell Count +gui.appliedenergistics2.NetworkFluidCellCount=Network Fluid Cell Count +gui.appliedenergistics2.NetworkEssentiaCellCount=Network Essentia Cell Count +gui.appliedenergistics2.Green=Green +gui.appliedenergistics2.Orange=Orange +gui.appliedenergistics2.Red=Red + # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index b9fad881fc2..31f60d7c713 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -266,9 +266,16 @@ gui.appliedenergistics2.HoldShiftClick_HIGHLIGHT_INTERFACE=shift点击,高亮ME gui.appliedenergistics2.VoidCellTooltip=删除§任何§7存储在里面的物品 gui.appliedenergistics2.Nothing=无 +gui.appliedenergistics2.NetworkBytesDetails=网络存储信息 gui.appliedenergistics2.Items=物品 gui.appliedenergistics2.Fluids=流体 gui.appliedenergistics2.Essentias=源质 +gui.appliedenergistics2.NetworkItemCellCount=网络物品元件数量 +gui.appliedenergistics2.NetworkFluidCellCount=网络流体元件数量 +gui.appliedenergistics2.NetworkEssentiaCellCount=网络源质元件数量 +gui.appliedenergistics2.Green=绿 +gui.appliedenergistics2.Orange=橙 +gui.appliedenergistics2.Red=红 # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang index 93b1c8462f6..75332033b30 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang @@ -189,9 +189,16 @@ gui.appliedenergistics2.CalculatingWait=正在計算,請等待... gui.appliedenergistics2.Clean=清空 gui.appliedenergistics2.InvalidPattern=無效樣板 +gui.appliedenergistics2.NetworkBytesDetails=網絡存儲信息 gui.appliedenergistics2.Items=物品 gui.appliedenergistics2.Fluids=流體 gui.appliedenergistics2.Essentias=源質 +gui.appliedenergistics2.NetworkItemCellCount=網絡物品元件數量 +gui.appliedenergistics2.NetworkFluidCellCount=網絡流體元件數量 +gui.appliedenergistics2.NetworkEssentiaCellCount=網絡源質元件數量 +gui.appliedenergistics2.Green=綠 +gui.appliedenergistics2.Orange=橙 +gui.appliedenergistics2.Red=紅 gui.tooltips.appliedenergistics2.Stash=存儲物品 gui.tooltips.appliedenergistics2.StashDesc=將合成槽的物品返回網絡 From 39c01cbf808c6988e7a98d6af4ee83a9276d039a Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Tue, 14 Nov 2023 13:33:40 +0800 Subject: [PATCH 32/34] Add more info to new Gui --- build.gradle | 1 - .../gui/implementations/GuiNetworkStatus.java | 154 +++++++++++++++++- .../appeng/core/localization/GuiColors.java | 4 +- .../appeng/core/localization/GuiText.java | 4 +- .../appliedenergistics2/lang/en_US.lang | 3 +- .../appliedenergistics2/lang/zh_CN.lang | 2 + .../appliedenergistics2/lang/zh_TW.lang | 2 + 7 files changed, 162 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 4f779070996..f3a7fa27881 100644 --- a/build.gradle +++ b/build.gradle @@ -906,7 +906,6 @@ runClient17Task.configure { mainClass = "GradleStart" username = minecraft.username userUUID = minecraft.userUUID -// jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" } def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index e3034703dc7..f920b01c254 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -49,11 +49,15 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource { private final DecimalFormat df; private final boolean isAdvanced; private boolean isConsume; + private final StringBuilder sb; + private final String Equal; + private final String Minus; public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkTool te) { super(new ContainerNetworkStatus(inventoryPlayer, te)); final GuiScrollbar scrollbar = new GuiScrollbar(); - + + this.sb= new StringBuilder(); this.df = new DecimalFormat("#.##"); this.setScrollBar(scrollbar); this.repo = new ItemRepo(scrollbar, this); @@ -62,6 +66,8 @@ public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkToo this.repo.setRowSize(5); this.isAdvanced = te.getSize() != 3; this.isConsume = true; + this.Equal = "="; + this.Minus = "-"; } @Override @@ -281,7 +287,7 @@ private void drawConsume() { + tempStr, 13, 143, - GuiColors.NetworkStatusPowerUsageRate.getColor()); + GuiColors.DefaultBlack.getColor()); tempStr = ns.getFluidBytesTotal() == 0 ? "" : " (" + df.format(ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal()) + "%)"; @@ -294,7 +300,7 @@ private void drawConsume() { + tempStr, 13, 143 + 10, - GuiColors.NetworkStatusPowerUsageRate.getColor()); + GuiColors.DefaultBlack.getColor()); tempStr = ns.getEssentiaBytesTotal() == 0 ? "" : " (" + df.format(ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal()) + "%)"; @@ -307,7 +313,7 @@ private void drawConsume() { + tempStr, 13, 143 + 20, - GuiColors.NetworkStatusPowerUsageRate.getColor()); + GuiColors.DefaultBlack.getColor()); final int sectionLength = 30; @@ -374,9 +380,37 @@ private void drawConsume() { } } + + private GuiColors getCorrespondingColor(final double percentage) { + if(Double.isNaN(percentage)) { + return GuiColors.DefaultBlack; + }else { + if(percentage > 95) { + return GuiColors.WarningRed; + }else if(percentage > 75) { + return GuiColors.WarningOrange; + }else { + return GuiColors.DefaultBlack; + } + } + } + + private String getProgressBar(final double percentage) { + int count = (int) Math.round(percentage / 5d); + sb.setLength(0); + sb.append('<'); + for(int i = 0; i < 20; i ++) { + if(i < count) sb.append(this.Equal); + else sb.append(this.Minus); + } + sb.append('>'); + return sb.toString(); + } private void drawItemInfo() { final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; + String tempStr; + double tempDouble; this.fontRendererObj .drawString(GuiText.NetworkBytesDetails.getLocal(), 8, 6, GuiColors.DefaultBlack.getColor()); this.fontRendererObj.drawString( @@ -398,10 +432,48 @@ private void drawItemInfo() { 13, 26, GuiColors.DefaultBlack.getColor()); + // Item byte status + tempDouble = ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal(); + tempStr = ns.getItemBytesTotal() == 0 ? "(0%)" + : " (" + df.format(tempDouble) + "%)"; + this.fontRendererObj.drawString( + GuiText.BytesInfo.getLocal() + ": " + + Platform.formatByteLong(ns.getItemBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getItemBytesTotal()), + 13, + 143 - 20, + getCorrespondingColor(tempDouble).getColor()); + this.fontRendererObj.drawString( + getProgressBar(tempDouble) + tempStr, + 13, + 143 - 10, + getCorrespondingColor(tempDouble).getColor()); + + // Item type status + tempDouble = ns.getItemTypesUsed() * 100d / ns.getItemTypesTotal(); + tempStr = ns.getItemTypesTotal() == 0 ? "(0%)" + : " (" + df.format(tempDouble) + "%)"; + this.fontRendererObj.drawString( + GuiText.TypesInfo.getLocal() + ": " + + ns.getItemTypesUsed() + + " / " + + ns.getItemTypesTotal() + , + 13, + 143, + getCorrespondingColor(tempDouble).getColor()); + this.fontRendererObj.drawString( + getProgressBar(tempDouble) + tempStr, + 13, + 143 + 10, + getCorrespondingColor(tempDouble).getColor()); } private void drawFluidInfo() { final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; + String tempStr; + double tempDouble; this.fontRendererObj .drawString(GuiText.NetworkBytesDetails.getLocal(), 8, 6, GuiColors.DefaultBlack.getColor()); this.fontRendererObj.drawString( @@ -423,10 +495,47 @@ private void drawFluidInfo() { 13, 26, GuiColors.DefaultBlack.getColor()); + // Fluid byte status + tempDouble = ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal(); + tempStr = ns.getFluidBytesTotal() == 0 ? "(0%)" + : " (" + df.format(tempDouble) + "%)"; + this.fontRendererObj.drawString( + GuiText.BytesInfo.getLocal() + ": " + + Platform.formatByteLong(ns.getFluidBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getFluidBytesTotal()), + 13, + 143 - 20, + getCorrespondingColor(tempDouble).getColor()); + this.fontRendererObj.drawString( + getProgressBar(tempDouble)+ tempStr, + 13, + 143 - 10, + getCorrespondingColor(tempDouble).getColor()); + + // Fluid type status + tempDouble = ns.getFluidTypesUsed() * 100d / ns.getFluidTypesTotal(); + tempStr = ns.getFluidTypesTotal() == 0 ? "(0%)" + : " (" + df.format(tempDouble) + "%)"; + this.fontRendererObj.drawString( + GuiText.TypesInfo.getLocal() + ": " + + ns.getFluidTypesUsed() + + " / " + + ns.getFluidTypesTotal(), + 13, + 143, + getCorrespondingColor(tempDouble).getColor()); + this.fontRendererObj.drawString( + getProgressBar(tempDouble) + tempStr, + 13, + 143 + 10, + getCorrespondingColor(tempDouble).getColor()); } private void drawEssentiaInfo() { final ContainerNetworkStatus ns = (ContainerNetworkStatus) this.inventorySlots; + String tempStr; + double tempDouble; this.fontRendererObj .drawString(GuiText.NetworkBytesDetails.getLocal(), 8, 6, GuiColors.DefaultBlack.getColor()); this.fontRendererObj.drawString( @@ -448,5 +557,42 @@ private void drawEssentiaInfo() { 13, 26, GuiColors.DefaultBlack.getColor()); + // Essentia byte status + tempDouble = ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal(); + tempStr = ns.getEssentiaBytesTotal() == 0 ? "(0%)" + : " (" + df.format(tempDouble) + "%)"; + this.fontRendererObj.drawString( + GuiText.BytesInfo.getLocal() + ": " + + Platform.formatByteLong(ns.getEssentiaBytesUsed()) + + " / " + + Platform.formatByteLong(ns.getEssentiaBytesTotal()) + , + 13, + 143 - 20, + getCorrespondingColor(tempDouble).getColor()); + this.fontRendererObj.drawString( + getProgressBar(tempDouble)+ tempStr, + 13, + 143 - 10, + getCorrespondingColor(tempDouble).getColor()); + + // Essentia type status + tempDouble = ns.getEssentiaTypesUsed() * 100d / ns.getEssentiaTypesTotal(); + tempStr = ns.getEssentiaTypesTotal() == 0 ? "(0%)" + : " (" + df.format(tempDouble) + "%)"; + this.fontRendererObj.drawString( + GuiText.TypesInfo.getLocal() + ": " + + ns.getEssentiaTypesUsed() + + " / " + + ns.getEssentiaTypesTotal() + , + 13, + 143, + getCorrespondingColor(tempDouble).getColor()); + this.fontRendererObj.drawString( + getProgressBar(tempDouble)+ tempStr, + 13, + 143 + 10, + getCorrespondingColor(tempDouble).getColor()); } } diff --git a/src/main/java/appeng/core/localization/GuiColors.java b/src/main/java/appeng/core/localization/GuiColors.java index b3b21a82582..5934ba925f0 100644 --- a/src/main/java/appeng/core/localization/GuiColors.java +++ b/src/main/java/appeng/core/localization/GuiColors.java @@ -142,7 +142,9 @@ public enum GuiColors { MEMonitorableTitle(0x404040), MEMonitorableInventory(0x404040), - DefaultBlack(0x404040); + DefaultBlack(0x404040), + WarningOrange(0xFBA900), + WarningRed(0xFB0000); private final String root; private final int color; diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index fba5a21ddb6..76fc763a795 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -219,7 +219,9 @@ public enum GuiText { NetworkBytesDetails, Items, Fluids, - Essentias; + Essentias, + TypesInfo, + BytesInfo; private final String root; diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang index 73325aca1da..ce61d9fcbbf 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_US.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_US.lang @@ -284,7 +284,8 @@ gui.appliedenergistics2.NetworkEssentiaCellCount=Network Essentia Cell Count gui.appliedenergistics2.Green=Green gui.appliedenergistics2.Orange=Orange gui.appliedenergistics2.Red=Red - +gui.appliedenergistics2.TypesInfo=Types +gui.appliedenergistics2.BytesInfo=Bytes # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang index 31f60d7c713..608fdf84178 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_CN.lang @@ -276,6 +276,8 @@ gui.appliedenergistics2.NetworkEssentiaCellCount=网络源质元件数量 gui.appliedenergistics2.Green=绿 gui.appliedenergistics2.Orange=橙 gui.appliedenergistics2.Red=红 +gui.appliedenergistics2.TypesInfo=种类 +gui.appliedenergistics2.BytesInfo=字节 # GUI Colors - ARGB gui.color.appliedenergistics2.SearchboxFocused=6E000000 diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang index 75332033b30..178106d9262 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_TW.lang @@ -199,6 +199,8 @@ gui.appliedenergistics2.NetworkEssentiaCellCount=網絡源質元件數量 gui.appliedenergistics2.Green=綠 gui.appliedenergistics2.Orange=橙 gui.appliedenergistics2.Red=紅 +gui.appliedenergistics2.TypesInfo=種類 +gui.appliedenergistics2.BytesInfo=字節 gui.tooltips.appliedenergistics2.Stash=存儲物品 gui.tooltips.appliedenergistics2.StashDesc=將合成槽的物品返回網絡 From 41b822b58628c33dc6e0b2e29255bf6ce58ad34f Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Tue, 14 Nov 2023 13:34:50 +0800 Subject: [PATCH 33/34] Apply spotless --- .../gui/implementations/GuiNetworkStatus.java | 96 ++++++++----------- 1 file changed, 39 insertions(+), 57 deletions(-) diff --git a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java index f920b01c254..3547f0690e7 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java +++ b/src/main/java/appeng/client/gui/implementations/GuiNetworkStatus.java @@ -56,8 +56,8 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource { public GuiNetworkStatus(final InventoryPlayer inventoryPlayer, final INetworkTool te) { super(new ContainerNetworkStatus(inventoryPlayer, te)); final GuiScrollbar scrollbar = new GuiScrollbar(); - - this.sb= new StringBuilder(); + + this.sb = new StringBuilder(); this.df = new DecimalFormat("#.##"); this.setScrollBar(scrollbar); this.repo = new ItemRepo(scrollbar, this); @@ -380,31 +380,31 @@ private void drawConsume() { } } - + private GuiColors getCorrespondingColor(final double percentage) { - if(Double.isNaN(percentage)) { - return GuiColors.DefaultBlack; - }else { - if(percentage > 95) { - return GuiColors.WarningRed; - }else if(percentage > 75) { - return GuiColors.WarningOrange; - }else { - return GuiColors.DefaultBlack; - } - } + if (Double.isNaN(percentage)) { + return GuiColors.DefaultBlack; + } else { + if (percentage > 95) { + return GuiColors.WarningRed; + } else if (percentage > 75) { + return GuiColors.WarningOrange; + } else { + return GuiColors.DefaultBlack; + } + } } - + private String getProgressBar(final double percentage) { - int count = (int) Math.round(percentage / 5d); - sb.setLength(0); - sb.append('<'); - for(int i = 0; i < 20; i ++) { - if(i < count) sb.append(this.Equal); - else sb.append(this.Minus); - } - sb.append('>'); - return sb.toString(); + int count = (int) Math.round(percentage / 5d); + sb.setLength(0); + sb.append('<'); + for (int i = 0; i < 20; i++) { + if (i < count) sb.append(this.Equal); + else sb.append(this.Minus); + } + sb.append('>'); + return sb.toString(); } private void drawItemInfo() { @@ -434,8 +434,7 @@ private void drawItemInfo() { GuiColors.DefaultBlack.getColor()); // Item byte status tempDouble = ns.getItemBytesUsed() * 100d / ns.getItemBytesTotal(); - tempStr = ns.getItemBytesTotal() == 0 ? "(0%)" - : " (" + df.format(tempDouble) + "%)"; + tempStr = ns.getItemBytesTotal() == 0 ? "(0%)" : " (" + df.format(tempDouble) + "%)"; this.fontRendererObj.drawString( GuiText.BytesInfo.getLocal() + ": " + Platform.formatByteLong(ns.getItemBytesUsed()) @@ -449,17 +448,12 @@ private void drawItemInfo() { 13, 143 - 10, getCorrespondingColor(tempDouble).getColor()); - + // Item type status tempDouble = ns.getItemTypesUsed() * 100d / ns.getItemTypesTotal(); - tempStr = ns.getItemTypesTotal() == 0 ? "(0%)" - : " (" + df.format(tempDouble) + "%)"; + tempStr = ns.getItemTypesTotal() == 0 ? "(0%)" : " (" + df.format(tempDouble) + "%)"; this.fontRendererObj.drawString( - GuiText.TypesInfo.getLocal() + ": " - + ns.getItemTypesUsed() - + " / " - + ns.getItemTypesTotal() - , + GuiText.TypesInfo.getLocal() + ": " + ns.getItemTypesUsed() + " / " + ns.getItemTypesTotal(), 13, 143, getCorrespondingColor(tempDouble).getColor()); @@ -497,8 +491,7 @@ private void drawFluidInfo() { GuiColors.DefaultBlack.getColor()); // Fluid byte status tempDouble = ns.getFluidBytesUsed() * 100d / ns.getFluidBytesTotal(); - tempStr = ns.getFluidBytesTotal() == 0 ? "(0%)" - : " (" + df.format(tempDouble) + "%)"; + tempStr = ns.getFluidBytesTotal() == 0 ? "(0%)" : " (" + df.format(tempDouble) + "%)"; this.fontRendererObj.drawString( GuiText.BytesInfo.getLocal() + ": " + Platform.formatByteLong(ns.getFluidBytesUsed()) @@ -508,20 +501,16 @@ private void drawFluidInfo() { 143 - 20, getCorrespondingColor(tempDouble).getColor()); this.fontRendererObj.drawString( - getProgressBar(tempDouble)+ tempStr, + getProgressBar(tempDouble) + tempStr, 13, 143 - 10, getCorrespondingColor(tempDouble).getColor()); // Fluid type status tempDouble = ns.getFluidTypesUsed() * 100d / ns.getFluidTypesTotal(); - tempStr = ns.getFluidTypesTotal() == 0 ? "(0%)" - : " (" + df.format(tempDouble) + "%)"; + tempStr = ns.getFluidTypesTotal() == 0 ? "(0%)" : " (" + df.format(tempDouble) + "%)"; this.fontRendererObj.drawString( - GuiText.TypesInfo.getLocal() + ": " - + ns.getFluidTypesUsed() - + " / " - + ns.getFluidTypesTotal(), + GuiText.TypesInfo.getLocal() + ": " + ns.getFluidTypesUsed() + " / " + ns.getFluidTypesTotal(), 13, 143, getCorrespondingColor(tempDouble).getColor()); @@ -559,38 +548,31 @@ private void drawEssentiaInfo() { GuiColors.DefaultBlack.getColor()); // Essentia byte status tempDouble = ns.getEssentiaBytesUsed() * 100d / ns.getEssentiaBytesTotal(); - tempStr = ns.getEssentiaBytesTotal() == 0 ? "(0%)" - : " (" + df.format(tempDouble) + "%)"; + tempStr = ns.getEssentiaBytesTotal() == 0 ? "(0%)" : " (" + df.format(tempDouble) + "%)"; this.fontRendererObj.drawString( GuiText.BytesInfo.getLocal() + ": " + Platform.formatByteLong(ns.getEssentiaBytesUsed()) + " / " - + Platform.formatByteLong(ns.getEssentiaBytesTotal()) - , + + Platform.formatByteLong(ns.getEssentiaBytesTotal()), 13, 143 - 20, getCorrespondingColor(tempDouble).getColor()); this.fontRendererObj.drawString( - getProgressBar(tempDouble)+ tempStr, + getProgressBar(tempDouble) + tempStr, 13, 143 - 10, getCorrespondingColor(tempDouble).getColor()); - + // Essentia type status tempDouble = ns.getEssentiaTypesUsed() * 100d / ns.getEssentiaTypesTotal(); - tempStr = ns.getEssentiaTypesTotal() == 0 ? "(0%)" - : " (" + df.format(tempDouble) + "%)"; + tempStr = ns.getEssentiaTypesTotal() == 0 ? "(0%)" : " (" + df.format(tempDouble) + "%)"; this.fontRendererObj.drawString( - GuiText.TypesInfo.getLocal() + ": " - + ns.getEssentiaTypesUsed() - + " / " - + ns.getEssentiaTypesTotal() - , + GuiText.TypesInfo.getLocal() + ": " + ns.getEssentiaTypesUsed() + " / " + ns.getEssentiaTypesTotal(), 13, 143, getCorrespondingColor(tempDouble).getColor()); this.fontRendererObj.drawString( - getProgressBar(tempDouble)+ tempStr, + getProgressBar(tempDouble) + tempStr, 13, 143 + 10, getCorrespondingColor(tempDouble).getColor()); From f01f40cc0c6b57ea2f0cc5d6a977ef1429b090ac Mon Sep 17 00:00:00 2001 From: MCTBL <2772337924@qq.com> Date: Wed, 15 Nov 2023 18:36:05 +0800 Subject: [PATCH 34/34] Replace some class to interface --- .../HasServerSideToolLogic.java | 12 ++++++++++++ .../api/storage/ICellCacheRegistry.java | 2 ++ .../appeng/core/sync/packets/PacketClick.java | 19 +++---------------- .../items/tools/ToolAdvancedNetworkTool.java | 5 ++++- .../appeng/items/tools/ToolNetworkTool.java | 5 ++++- .../appeng/me/cache/GridStorageCache.java | 18 ++++++++---------- .../me/storage/CellInventoryHandler.java | 5 +++++ 7 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 src/main/java/appeng/api/implementations/HasServerSideToolLogic.java diff --git a/src/main/java/appeng/api/implementations/HasServerSideToolLogic.java b/src/main/java/appeng/api/implementations/HasServerSideToolLogic.java new file mode 100644 index 00000000000..be10f524b68 --- /dev/null +++ b/src/main/java/appeng/api/implementations/HasServerSideToolLogic.java @@ -0,0 +1,12 @@ +package appeng.api.implementations; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public interface HasServerSideToolLogic { + + boolean serverSideToolLogic(final ItemStack is, final EntityPlayer p, final World w, final int x, final int y, + final int z, final int side, final float hitX, final float hitY, final float hitZ); + +} diff --git a/src/main/java/appeng/api/storage/ICellCacheRegistry.java b/src/main/java/appeng/api/storage/ICellCacheRegistry.java index df595bb2efd..b6a87cb6feb 100644 --- a/src/main/java/appeng/api/storage/ICellCacheRegistry.java +++ b/src/main/java/appeng/api/storage/ICellCacheRegistry.java @@ -6,6 +6,8 @@ */ public interface ICellCacheRegistry { + boolean canGetInv(); + long getTotalBytes(); long getFreeBytes(); diff --git a/src/main/java/appeng/core/sync/packets/PacketClick.java b/src/main/java/appeng/core/sync/packets/PacketClick.java index 378b0809b1a..f085247ea78 100644 --- a/src/main/java/appeng/core/sync/packets/PacketClick.java +++ b/src/main/java/appeng/core/sync/packets/PacketClick.java @@ -16,12 +16,11 @@ import appeng.api.AEApi; import appeng.api.definitions.IComparableDefinition; import appeng.api.definitions.IItems; +import appeng.api.implementations.HasServerSideToolLogic; import appeng.api.implementations.items.IMemoryCard; import appeng.api.implementations.items.MemoryCardMessages; import appeng.core.sync.AppEngPacket; import appeng.core.sync.network.INetworkInfo; -import appeng.items.tools.ToolAdvancedNetworkTool; -import appeng.items.tools.ToolNetworkTool; import appeng.items.tools.powered.ToolColorApplicator; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -73,20 +72,8 @@ public void serverPacketData(final INetworkInfo manager, final AppEngPacket pack final IComparableDefinition maybeColorApplicator = items.colorApplicator(); if (is != null) { - if (is.getItem() instanceof ToolNetworkTool tnt) { - tnt.serverSideToolLogic( - is, - player, - player.worldObj, - this.x, - this.y, - this.z, - this.side, - this.hitX, - this.hitY, - this.hitZ); - } else if (is.getItem() instanceof ToolAdvancedNetworkTool atnt) { - atnt.serverSideToolLogic( + if (is.getItem() instanceof HasServerSideToolLogic hsstl) { + hsstl.serverSideToolLogic( is, player, player.worldObj, diff --git a/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java index 67282c5ec73..6e92dc716b7 100644 --- a/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java +++ b/src/main/java/appeng/items/tools/ToolAdvancedNetworkTool.java @@ -16,6 +16,7 @@ import com.google.common.base.Optional; +import appeng.api.implementations.HasServerSideToolLogic; import appeng.api.implementations.guiobjects.IGuiItem; import appeng.api.implementations.guiobjects.IGuiItemObject; import appeng.api.implementations.items.IAEWrench; @@ -42,7 +43,8 @@ @InterfaceList( value = { @Interface(iface = "cofh.api.item.IToolHammer", iname = IntegrationType.CoFHWrench), @Interface(iface = "buildcraft.api.tools.IToolWrench", iname = IntegrationType.BuildCraftCore) }) -public class ToolAdvancedNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench, IToolWrench, IToolHammer { +public class ToolAdvancedNetworkTool extends AEBaseItem + implements IGuiItem, IAEWrench, IToolWrench, IToolHammer, HasServerSideToolLogic { public ToolAdvancedNetworkTool() { super(Optional.absent()); @@ -115,6 +117,7 @@ public boolean onItemUseFirst(final ItemStack is, final EntityPlayer player, fin return true; } + @Override public boolean serverSideToolLogic(final ItemStack is, final EntityPlayer p, final World w, final int x, final int y, final int z, final int side, final float hitX, final float hitY, final float hitZ) { if (side >= 0) { diff --git a/src/main/java/appeng/items/tools/ToolNetworkTool.java b/src/main/java/appeng/items/tools/ToolNetworkTool.java index ea68b0856cc..2c6cf89639e 100644 --- a/src/main/java/appeng/items/tools/ToolNetworkTool.java +++ b/src/main/java/appeng/items/tools/ToolNetworkTool.java @@ -26,6 +26,7 @@ import com.google.common.base.Optional; +import appeng.api.implementations.HasServerSideToolLogic; import appeng.api.implementations.guiobjects.IGuiItem; import appeng.api.implementations.guiobjects.IGuiItemObject; import appeng.api.implementations.items.IAEWrench; @@ -52,7 +53,8 @@ @InterfaceList( value = { @Interface(iface = "cofh.api.item.IToolHammer", iname = IntegrationType.CoFHWrench), @Interface(iface = "buildcraft.api.tools.IToolWrench", iname = IntegrationType.BuildCraftCore) }) -public class ToolNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench, IToolWrench, IToolHammer { +public class ToolNetworkTool extends AEBaseItem + implements IGuiItem, IAEWrench, IToolWrench, IToolHammer, HasServerSideToolLogic { public ToolNetworkTool() { super(Optional.absent()); @@ -137,6 +139,7 @@ public boolean doesSneakBypassUse(final World world, final int x, final int y, f return true; } + @Override public boolean serverSideToolLogic(final ItemStack is, final EntityPlayer p, final World w, final int x, final int y, final int z, final int side, final float hitX, final float hitY, final float hitZ) { if (side >= 0) { diff --git a/src/main/java/appeng/me/cache/GridStorageCache.java b/src/main/java/appeng/me/cache/GridStorageCache.java index 883d5478f42..33c68310d66 100644 --- a/src/main/java/appeng/me/cache/GridStorageCache.java +++ b/src/main/java/appeng/me/cache/GridStorageCache.java @@ -34,6 +34,7 @@ import appeng.api.networking.storage.IStackWatcher; import appeng.api.networking.storage.IStackWatcherHost; import appeng.api.networking.storage.IStorageGrid; +import appeng.api.storage.ICellCacheRegistry; import appeng.api.storage.ICellContainer; import appeng.api.storage.ICellProvider; import appeng.api.storage.IMEInventoryHandler; @@ -385,21 +386,18 @@ private void updateBytesInfo() { // All Item Cell for (IMEInventoryHandler meih : icp.getCellArray(StorageChannel.ITEMS)) { // exclude void cell - if (((DriveWatcher) meih).getInternal() instanceof VoidCellInventory) { - continue; - } - if (((DriveWatcher) meih).getInternal() instanceof CellInventoryHandler handler) { + if (((DriveWatcher) meih).getInternal() instanceof ICellCacheRegistry iccr) { // exclude creative cell - if (handler.getCellInv() != null) { - itemBytesTotal += handler.getTotalBytes(); - itemBytesUsed += handler.getUsedBytes(); - switch (handler.getStatusForCell()) { + if (iccr.canGetInv()) { + itemBytesTotal += iccr.getTotalBytes(); + itemBytesUsed += iccr.getUsedBytes(); + switch (iccr.getCellStatus()) { case 1 -> itemCellG++; case 2 -> itemCellO++; case 3 -> itemCellR++; } - itemTypesTotal += handler.getTotalTypes(); - itemTypesUsed += handler.getUsedTypes(); + itemTypesTotal += iccr.getTotalTypes(); + itemTypesUsed += iccr.getUsedTypes(); } } itemCellCount++; diff --git a/src/main/java/appeng/me/storage/CellInventoryHandler.java b/src/main/java/appeng/me/storage/CellInventoryHandler.java index 76ccaf61212..d6b2146bfd2 100644 --- a/src/main/java/appeng/me/storage/CellInventoryHandler.java +++ b/src/main/java/appeng/me/storage/CellInventoryHandler.java @@ -125,6 +125,11 @@ public int getStatusForCell() { return val; } + @Override + public boolean canGetInv() { + return this.getCellInv() != null; + } + @Override public long getTotalBytes() { return this.getCellInv().getTotalBytes();