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 extends IAEStack> 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 extends IAEStack> 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 extends IGridHost> 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 extends IGridHost> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IGridHost> 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 extends IGridHost> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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 extends IAEStack> 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