Fixed high CPU load when Refined Storage GUIs are open, fixes #1295

This commit is contained in:
raoulvdberge
2017-10-03 22:23:23 +02:00
parent 171d30c434
commit b29374882d
14 changed files with 138 additions and 113 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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<ItemStack> {
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<ItemStack> {
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<ItemStack> {
@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<ItemStack> {
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);
}
}

View File

@@ -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;

View File

@@ -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();
}
}
}

View File

@@ -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;

View File

@@ -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");

View File

@@ -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());
}
}
}
}

View File

@@ -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<Integer, TileDataParameter> REGISTRY = new HashMap<>();
private TileEntity tile;
private List<TileDataParameter> parameters = new ArrayList<>();
private List<TileDataParameter> watchedParameters = new ArrayList<>();
private List<Object> watchedParametersCache = new ArrayList<>();
private List<EntityPlayer> watchers = new ArrayList<>();
private TileEntity tile;
private List<TileDataWatcher> watchers = new CopyOnWriteArrayList<>();
public TileDataManager(TileEntity tile) {
this.tile = tile;
}
public List<EntityPlayer> 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<TileDataParameter> getWatchedParameters() {
return watchedParameters;
}
public void sendParametersTo(EntityPlayerMP player) {
parameters.forEach(p -> sendParameter(player, p));
public List<TileDataWatcher> 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) {

View File

@@ -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);
}
}

View File

@@ -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<ItemStack> getStorage();
List<EntityPlayer> getWatchers();
List<TileDataWatcher> getWatchers();
void drainEnergy(int energy);

View File

@@ -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<TileDataWatcher> 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<EntityPlayer> getWatchers() {
return Collections.singletonList(player);
public List<TileDataWatcher> getWatchers() {
return dummyWatchers;
}
@Override

View File

@@ -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<EntityPlayer> getWatchers() {
public List<TileDataWatcher> 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);