diff --git a/CHANGELOG.md b/CHANGELOG.md index 32bdec338..c89e76303 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Fixed Refined Storage blocks requiring a pickaxe to be broken (raoulvdberge) - Fixed Grid GUI crash (raoulvdberge) - Fixed device names overflowing Controller GUI (raoulvdberge) +- Fixed high CPU load when Refined Storage GUIs are open (raoulvdberge) ### 1.5.18 - Added Project E integration for the External Storage on the Transmutation Table (raoulvdberge) diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java index 167745a9e..0b98a81b0 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java @@ -69,15 +69,7 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC @Override public int getEnergyUsage() { - int usage = RS.INSTANCE.config.crafterUsage + upgrades.getEnergyUsage(); - - for (int i = 0; i < patterns.getSlots(); ++i) { - if (!patterns.getStackInSlot(i).isEmpty()) { - usage += RS.INSTANCE.config.crafterPerPatternUsage; - } - } - - return usage; + return RS.INSTANCE.config.crafterUsage + upgrades.getEnergyUsage() + (RS.INSTANCE.config.crafterPerPatternUsage * actualPatterns.size()); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskdrive/NetworkNodeDiskDrive.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskdrive/NetworkNodeDiskDrive.java index a7fe0b5a3..f5a2c2299 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskdrive/NetworkNodeDiskDrive.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskdrive/NetworkNodeDiskDrive.java @@ -107,8 +107,13 @@ public class NetworkNodeDiskDrive extends NetworkNode implements IGuiStorage, IS public int getEnergyUsage() { int usage = RS.INSTANCE.config.diskDriveUsage; - for (int i = 0; i < disks.getSlots(); ++i) { - if (!disks.getStackInSlot(i).isEmpty()) { + for (IStorage storage : itemStorages) { + if (storage != null) { + usage += RS.INSTANCE.config.diskDrivePerDiskUsage; + } + } + for (IStorage storage : fluidStorages) { + if (storage != null) { usage += RS.INSTANCE.config.diskDrivePerDiskUsage; } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/storage/StorageCacheItemPortable.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/storage/StorageCacheItemPortable.java index 062d4bfee..34b1f30fc 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/storage/StorageCacheItemPortable.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/storage/StorageCacheItemPortable.java @@ -9,7 +9,6 @@ import com.raoulvdberge.refinedstorage.network.MessageGridItemDelta; import com.raoulvdberge.refinedstorage.network.MessageGridItemUpdate; import com.raoulvdberge.refinedstorage.tile.grid.portable.IPortableGrid; import com.raoulvdberge.refinedstorage.util.StackUtils; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -37,7 +36,7 @@ public class StorageCacheItemPortable implements IStorageCache { listeners.forEach(Runnable::run); - portableGrid.getWatchers().forEach(this::sendUpdateTo); + portableGrid.getWatchers().forEach(w -> sendUpdateTo(w.getPlayer())); } @Override @@ -45,7 +44,7 @@ public class StorageCacheItemPortable implements IStorageCache { list.add(stack, size); if (!rebuilding) { - portableGrid.getWatchers().forEach(w -> RS.INSTANCE.network.sendTo(new MessageGridItemDelta(null, stack, size), (EntityPlayerMP) w)); + portableGrid.getWatchers().forEach(w -> RS.INSTANCE.network.sendTo(new MessageGridItemDelta(null, stack, size), w.getPlayer())); listeners.forEach(Runnable::run); } @@ -54,7 +53,7 @@ public class StorageCacheItemPortable implements IStorageCache { @Override public void remove(@Nonnull ItemStack stack, int size, boolean batched) { if (list.remove(stack, size)) { - portableGrid.getWatchers().forEach(w -> RS.INSTANCE.network.sendTo(new MessageGridItemDelta(null, stack, -size), (EntityPlayerMP) w)); + portableGrid.getWatchers().forEach(w -> RS.INSTANCE.network.sendTo(new MessageGridItemDelta(null, stack, -size), w.getPlayer())); listeners.forEach(Runnable::run); } @@ -85,13 +84,13 @@ public class StorageCacheItemPortable implements IStorageCache { return Collections.emptyList(); } - public void sendUpdateTo(EntityPlayer player) { + public void sendUpdateTo(EntityPlayerMP player) { RS.INSTANCE.network.sendTo(new MessageGridItemUpdate(buf -> { buf.writeInt(list.getStacks().size()); for (ItemStack stack : list.getStacks()) { StackUtils.writeItemStack(buf, stack, null, false); } - }, false), (EntityPlayerMP) player); + }, false), player); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/block/BlockPortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/block/BlockPortableGrid.java index 2e6842701..86aeb1b03 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/block/BlockPortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/block/BlockPortableGrid.java @@ -10,6 +10,7 @@ import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -120,7 +121,7 @@ public class BlockPortableGrid extends BlockBase { if (!world.isRemote) { player.openGui(RS.INSTANCE, RSGui.PORTABLE_GRID, world, pos.getX(), pos.getY(), pos.getZ()); - ((TilePortableGrid) world.getTileEntity(pos)).onOpened(player); + ((TilePortableGrid) world.getTileEntity(pos)).onOpened((EntityPlayerMP) player); } return true; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java index 94a075639..ac8ffac61 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/container/ContainerBase.java @@ -4,8 +4,10 @@ import com.raoulvdberge.refinedstorage.RSItems; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.container.slot.*; import com.raoulvdberge.refinedstorage.tile.TileBase; +import com.raoulvdberge.refinedstorage.tile.data.TileDataWatcher; import invtweaks.api.container.InventoryContainer; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.ClickType; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; @@ -13,14 +15,21 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; +import javax.annotation.Nullable; @InventoryContainer(showOptions = false) public abstract class ContainerBase extends Container { + @Nullable private TileBase tile; + @Nullable + private TileDataWatcher listener; private EntityPlayer player; - public ContainerBase(TileBase tile, EntityPlayer player) { + public ContainerBase(@Nullable TileBase tile, EntityPlayer player) { this.tile = tile; + if (tile != null && player instanceof EntityPlayerMP) { + listener = new TileDataWatcher((EntityPlayerMP) player, tile.getDataManager()); + } this.player = player; } @@ -28,6 +37,7 @@ public abstract class ContainerBase extends Container { return player; } + @Nullable public TileBase getTile() { return tile; } @@ -161,4 +171,22 @@ public abstract class ContainerBase extends Container { protected boolean isHeldItemDisabled() { return false; } + + @Override + public void detectAndSendChanges() { + super.detectAndSendChanges(); + + if (listener != null) { + listener.detectAndSendChanges(); + } + } + + @Override + public void onContainerClosed(EntityPlayer player) { + super.onContainerClosed(player); + + if (listener != null) { + listener.onClosed(); + } + } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerUpgrade.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerUpgrade.java index 7669b8b94..b1f920f4b 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerUpgrade.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerUpgrade.java @@ -49,9 +49,7 @@ public class ItemHandlerUpgrade extends ItemHandlerBase { int usage = 0; for (int i = 0; i < getSlots(); ++i) { - if (!getStackInSlot(i).isEmpty()) { - usage += ItemUpgrade.getEnergyUsage(getStackInSlot(i)); - } + usage += ItemUpgrade.getEnergyUsage(getStackInSlot(i)); } return usage; diff --git a/src/main/java/com/raoulvdberge/refinedstorage/proxy/ProxyCommon.java b/src/main/java/com/raoulvdberge/refinedstorage/proxy/ProxyCommon.java index 98e569692..920cdb1ef 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/proxy/ProxyCommon.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/proxy/ProxyCommon.java @@ -30,7 +30,6 @@ import com.raoulvdberge.refinedstorage.integration.projecte.IntegrationProjectE; import com.raoulvdberge.refinedstorage.network.*; import com.raoulvdberge.refinedstorage.tile.*; import com.raoulvdberge.refinedstorage.tile.craftingmonitor.TileCraftingMonitor; -import com.raoulvdberge.refinedstorage.tile.data.ContainerListener; import com.raoulvdberge.refinedstorage.tile.data.TileDataManager; import com.raoulvdberge.refinedstorage.tile.grid.TileGrid; import com.raoulvdberge.refinedstorage.tile.grid.WirelessFluidGrid; @@ -138,7 +137,6 @@ public class ProxyCommon { NetworkRegistry.INSTANCE.registerGuiHandler(RS.INSTANCE, new GuiHandler()); - MinecraftForge.EVENT_BUS.register(new ContainerListener()); MinecraftForge.EVENT_BUS.register(new NetworkNodeListener()); registerTile(TileController.class, "controller"); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/data/ContainerListener.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/data/ContainerListener.java deleted file mode 100755 index dab785f24..000000000 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/data/ContainerListener.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.raoulvdberge.refinedstorage.tile.data; - -import com.raoulvdberge.refinedstorage.container.ContainerBase; -import com.raoulvdberge.refinedstorage.tile.TileBase; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.inventory.Container; -import net.minecraftforge.event.entity.player.PlayerContainerEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; - -public class ContainerListener { - @SubscribeEvent - public void onContainerOpen(PlayerContainerEvent.Open e) { - Container container = e.getContainer(); - - if (container instanceof ContainerBase) { - TileBase tile = ((ContainerBase) container).getTile(); - - if (tile != null && !tile.getWorld().isRemote) { - TileDataManager manager = tile.getDataManager(); - - manager.sendParametersTo((EntityPlayerMP) e.getEntityPlayer()); - - int watchers = manager.getWatchers().size(); - - manager.getWatchers().add(e.getEntityPlayer()); - - if (watchers == 0) { - Thread listenerThread = new Thread(() -> { - while (manager.getWatchers().size() > 0) { - manager.detectAndSendChanges(); - } - }, "RS tile listener " + tile.getPos().getX() + ", " + tile.getPos().getY() + ", " + tile.getPos().getZ()); - - listenerThread.start(); - } - } - } - } - - @SubscribeEvent - public void onContainerClose(PlayerContainerEvent.Close e) { - Container container = e.getContainer(); - - if (container instanceof ContainerBase) { - TileBase tile = ((ContainerBase) container).getTile(); - - if (tile != null && !tile.getWorld().isRemote) { - tile.getDataManager().getWatchers().remove(e.getEntityPlayer()); - } - } - } -} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/data/TileDataManager.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/data/TileDataManager.java index c89222d8e..b2ee97395 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/data/TileDataManager.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/data/TileDataManager.java @@ -1,35 +1,32 @@ package com.raoulvdberge.refinedstorage.tile.data; import com.raoulvdberge.refinedstorage.RS; -import com.raoulvdberge.refinedstorage.network.MessageTileDataParameter; import com.raoulvdberge.refinedstorage.network.MessageTileDataParameterUpdate; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.tileentity.TileEntity; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; public class TileDataManager { private static int LAST_ID = 0; private static Map REGISTRY = new HashMap<>(); + private TileEntity tile; + private List parameters = new ArrayList<>(); private List watchedParameters = new ArrayList<>(); - private List watchedParametersCache = new ArrayList<>(); - private List watchers = new ArrayList<>(); - - private TileEntity tile; + private List watchers = new CopyOnWriteArrayList<>(); public TileDataManager(TileEntity tile) { this.tile = tile; } - public List getWatchers() { - return watchers; + public TileEntity getTile() { + return tile; } public void addParameter(TileDataParameter parameter) { @@ -44,34 +41,26 @@ public class TileDataManager { addParameter(parameter); watchedParameters.add(parameter); - watchedParametersCache.add(null); } - public void detectAndSendChanges() { - for (int i = 0; i < watchedParameters.size(); ++i) { - TileDataParameter parameter = watchedParameters.get(i); - - Object real = parameter.getValueProducer().apply(tile); - Object cached = watchedParametersCache.get(i); - - if (!real.equals(cached)) { - watchedParametersCache.set(i, real); - - sendParameterToWatchers(parameter); - } - } + public List getWatchedParameters() { + return watchedParameters; } - public void sendParametersTo(EntityPlayerMP player) { - parameters.forEach(p -> sendParameter(player, p)); + public List getWatchers() { + return watchers; + } + + public void addWatcher(TileDataWatcher listener) { + watchers.add(listener); + } + + public void removeWatcher(TileDataWatcher listener) { + watchers.remove(listener); } public void sendParameterToWatchers(TileDataParameter parameter) { - watchers.forEach(p -> sendParameter((EntityPlayerMP) p, parameter)); - } - - public void sendParameter(EntityPlayerMP player, TileDataParameter parameter) { - RS.INSTANCE.network.sendTo(new MessageTileDataParameter(tile, parameter), player); + watchers.forEach(l -> l.sendParameter(parameter)); } public static void registerParameter(TileDataParameter parameter) { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/data/TileDataWatcher.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/data/TileDataWatcher.java new file mode 100644 index 000000000..a2c26634e --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/data/TileDataWatcher.java @@ -0,0 +1,58 @@ +package com.raoulvdberge.refinedstorage.tile.data; + +import com.raoulvdberge.refinedstorage.RS; +import com.raoulvdberge.refinedstorage.network.MessageTileDataParameter; +import net.minecraft.entity.player.EntityPlayerMP; + +public class TileDataWatcher { + private boolean sentInitial; + private EntityPlayerMP player; + private TileDataManager manager; + + private Object[] cache; + + public TileDataWatcher(EntityPlayerMP player, TileDataManager manager) { + this.player = player; + this.manager = manager; + if (manager != null) { + this.manager.addWatcher(this); + this.cache = new Object[manager.getWatchedParameters().size()]; + } + } + + public EntityPlayerMP getPlayer() { + return player; + } + + public void onClosed() { + this.manager.removeWatcher(this); + } + + public void detectAndSendChanges() { + if (!sentInitial) { + manager.getParameters().forEach(this::sendParameter); + + sentInitial = true; + } else { + for (int i = 0; i < manager.getWatchedParameters().size(); ++i) { + TileDataParameter parameter = manager.getWatchedParameters().get(i); + + Object real = parameter.getValueProducer().apply(manager.getTile()); + Object cached = cache[i]; + + if (!real.equals(cached)) { + cache[i] = real; + + // Avoid sending watched parameter twice (after initial packet) + if (cached != null) { + sendParameter(parameter); + } + } + } + } + } + + public void sendParameter(TileDataParameter parameter) { + RS.INSTANCE.network.sendTo(new MessageTileDataParameter(manager.getTile(), parameter), player); + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/IPortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/IPortableGrid.java index 1ee2925c1..49afb553c 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/IPortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/IPortableGrid.java @@ -3,7 +3,7 @@ package com.raoulvdberge.refinedstorage.tile.grid.portable; import com.raoulvdberge.refinedstorage.api.storage.IStorageCache; import com.raoulvdberge.refinedstorage.api.storage.IStorageDisk; import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBase; -import net.minecraft.entity.player.EntityPlayer; +import com.raoulvdberge.refinedstorage.tile.data.TileDataWatcher; import net.minecraft.item.ItemStack; import net.minecraftforge.items.IItemHandlerModifiable; @@ -16,7 +16,7 @@ public interface IPortableGrid { @Nullable IStorageDisk getStorage(); - List getWatchers(); + List getWatchers(); void drainEnergy(int energy); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java index a69bbc41d..61ace08bd 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java @@ -22,9 +22,11 @@ import com.raoulvdberge.refinedstorage.item.ItemBlockPortableGrid; import com.raoulvdberge.refinedstorage.item.ItemEnergyItem; import com.raoulvdberge.refinedstorage.item.ItemWirelessGrid; import com.raoulvdberge.refinedstorage.network.MessageGridSettingsUpdate; +import com.raoulvdberge.refinedstorage.tile.data.TileDataWatcher; import com.raoulvdberge.refinedstorage.util.StackUtils; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.InventoryCraftResult; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; @@ -37,7 +39,6 @@ import net.minecraftforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; -import java.util.Collections; import java.util.List; public class PortableGrid implements IGrid, IPortableGrid { @@ -49,6 +50,7 @@ public class PortableGrid implements IGrid, IPortableGrid { private ItemGridHandlerPortable handler = new ItemGridHandlerPortable(this, this); private EntityPlayer player; + private List dummyWatchers = new ArrayList<>(); private ItemStack stack; private int sortingType; @@ -122,6 +124,10 @@ public class PortableGrid implements IGrid, IPortableGrid { this.tabSelected = ItemWirelessGrid.getTabSelected(stack); this.tabPage = ItemWirelessGrid.getTabPage(stack); this.size = ItemWirelessGrid.getSize(stack); + + if (player instanceof EntityPlayerMP) { + this.dummyWatchers.add(new TileDataWatcher((EntityPlayerMP) player, null)); + } } if (!stack.hasTagCompound()) { @@ -160,8 +166,8 @@ public class PortableGrid implements IGrid, IPortableGrid { } @Override - public List getWatchers() { - return Collections.singletonList(player); + public List getWatchers() { + return dummyWatchers; } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java index e8be05ac2..95611f4a7 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java @@ -31,10 +31,12 @@ import com.raoulvdberge.refinedstorage.tile.config.IRedstoneConfigurable; import com.raoulvdberge.refinedstorage.tile.config.RedstoneMode; import com.raoulvdberge.refinedstorage.tile.data.TileDataManager; import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter; +import com.raoulvdberge.refinedstorage.tile.data.TileDataWatcher; import com.raoulvdberge.refinedstorage.util.StackUtils; import com.raoulvdberge.refinedstorage.util.WorldUtils; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.InventoryCraftResult; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; @@ -459,7 +461,7 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid, } @Override - public List getWatchers() { + public List getWatchers() { return dataManager.getWatchers(); } @@ -612,7 +614,7 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid, return super.getCapability(capability, facing); } - public void onOpened(EntityPlayer player) { + public void onOpened(EntityPlayerMP player) { cache.sendUpdateTo(player); drainEnergy(RS.INSTANCE.config.portableGridOpenUsage);