Add changes from the mc1.14 branch

Fixed crash when loading a network. Fixes #2381

Experimental test for #2345

Fixed being able to drain energy from the Refined Storage Controller. Fixes #2361

Fixed the Grid crashing on a item/fluid update-heavy storage system. Fixes #2345

Fixed the Grid crashing on a item/fluid update-heavy storage system (PT. 2). Fixes #2345

Fixed the Grid crashing on a item/fluid update-heavy storage system (PT. 3, fix typo). Fixes #2345

Update changelog

Fix issue in extractEnergyInternal

Fixed crash with the Disk Manipulator and using item/fluid filters when inserting into the network. Fixes #2367

Rename IPortableGrid#isActive -> IPortableGrid#isGridActive, IGrid#isActive -> IGrid#isGridActive, ICraftingMonitor#isActive -> ICraftingMonitor#isActiveOnClient, CrafterManagerNetworkNode#isActive -> CrafterManagerNetworkNode#isActiveOnClient

Fixed the network being able to run off 1 FE/t. Fixes #2369

Fixed the Grid displaying the old quantity when shift clicking an entire stack out.

Update the storage stacker entry as well on the crafting stack.

When pressing ESCAPE in the search box on the Grid or Crafter Manager, focus on the search bar will be lost first before closing the GUI immediately. Then on the next ESCAPE press, the GUI will be closed.

Fix performance issue caused by getEnergyUsage calls.

Optimize any call to getEnergyUsage.
This commit is contained in:
raoulvdberge
2019-12-28 22:00:55 +01:00
parent 342779f683
commit e7ab1b12ec
42 changed files with 195 additions and 82 deletions

View File

@@ -235,7 +235,7 @@ public interface IGrid {
/**
* @return true if the grid is active, false otherwise
*/
boolean isActive();
boolean isGridActive();
/**
* @return the slot id where this grid is located, if applicable, otherwise -1

View File

@@ -44,11 +44,11 @@ public interface INetworkNode {
void onDisconnected(INetwork network);
/**
* If a node can be updated typically depends on the redstone configuration.
* Whether this node is active, independent of the network.
*
* @return true if this node can be treated as updatable, false otherwise
* @return true if this node is active, false otherwise
*/
boolean canUpdate();
boolean isActive();
/**
* @return the network, or null if this node is not connected to any network

View File

@@ -69,6 +69,12 @@ public interface IStorageCache<T> {
*/
void removeListener(IStorageCacheListener<T> listener);
/**
* Re-attaches all listeners.
* In practice this means that all listeners will get a {@link IStorageCacheListener#onAttached()} call.
*/
void reAttachListeners();
/**
* Resorts the storages in this cache according to their priority.
* This needs to be called when the priority of a storage changes.

View File

@@ -371,7 +371,7 @@ public class CraftingManager implements ICraftingManager {
List<ICraftingPatternContainer> containers = new ArrayList<>();
for (INetworkNode node : network.getNodeGraph().all()) {
if (node instanceof ICraftingPatternContainer && node.canUpdate()) {
if (node instanceof ICraftingPatternContainer && node.isActive()) {
containers.add((ICraftingPatternContainer) node);
}
}
@@ -396,6 +396,9 @@ public class CraftingManager implements ICraftingManager {
this.containerInventories.computeIfAbsent(container.getName(), k -> new ArrayList<>()).add(handler);
}
}
this.network.getItemStorageCache().reAttachListeners();
this.network.getFluidStorageCache().reAttachListeners();
}
@Nullable

View File

@@ -33,6 +33,7 @@ import com.raoulvdberge.refinedstorage.tile.ControllerTile;
import com.raoulvdberge.refinedstorage.tile.config.IRedstoneConfigurable;
import com.raoulvdberge.refinedstorage.tile.config.RedstoneMode;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
@@ -65,13 +66,14 @@ public class Network implements INetwork, IRedstoneConfigurable {
private final ItemStorageTracker itemStorageTracker = new ItemStorageTracker(this::markDirty);
private final IStorageCache<FluidStack> fluidStorage = new FluidStorageCache(this);
private final FluidStorageTracker fluidStorageTracker = new FluidStorageTracker(this::markDirty);
private final BaseEnergyStorage energy = new BaseEnergyStorage(RS.SERVER_CONFIG.getController().getCapacity(), RS.SERVER_CONFIG.getController().getMaxTransfer());
private final BaseEnergyStorage energy = new BaseEnergyStorage(RS.SERVER_CONFIG.getController().getCapacity(), RS.SERVER_CONFIG.getController().getMaxTransfer(), 0);
private final RootNetworkNode root;
private final BlockPos pos;
private final World world;
private final NetworkType type;
private ControllerBlock.EnergyType lastEnergyType = ControllerBlock.EnergyType.OFF;
private int lastEnergyUsage;
private RedstoneMode redstoneMode = RedstoneMode.IGNORE;
private boolean throttlingDisabled = true; // Will be enabled after first update
@@ -107,7 +109,7 @@ public class Network implements INetwork, IRedstoneConfigurable {
@Override
public boolean canRun() {
return this.energy.getEnergyStored() > 0 && redstoneMode.isEnabled(world, pos);
return energy.getEnergyStored() >= getEnergyUsage() && redstoneMode.isEnabled(world, pos);
}
@Override
@@ -128,6 +130,8 @@ public class Network implements INetwork, IRedstoneConfigurable {
@Override
public void update() {
if (!world.isRemote) {
updateEnergyUsage();
if (canRun()) {
craftingManager.update();
@@ -138,14 +142,12 @@ public class Network implements INetwork, IRedstoneConfigurable {
if (type == NetworkType.NORMAL) {
if (!RS.SERVER_CONFIG.getController().getUseEnergy()) {
this.energy.setStored(this.energy.getMaxEnergyStored());
} else if (this.energy.extractEnergy(getEnergyUsage(), true) >= 0) {
this.energy.extractEnergy(getEnergyUsage(), false);
energy.setStored(this.energy.getMaxEnergyStored());
} else {
this.energy.setStored(0);
energy.extractEnergyBypassCanExtract(getEnergyUsage(), false);
}
} else if (type == NetworkType.CREATIVE) {
this.energy.setStored(this.energy.getMaxEnergyStored());
energy.setStored(energy.getMaxEnergyStored());
}
boolean canRun = canRun();
@@ -170,7 +172,10 @@ public class Network implements INetwork, IRedstoneConfigurable {
if (lastEnergyType != energyType) {
lastEnergyType = energyType;
world.setBlockState(pos, world.getBlockState(pos).with(ControllerBlock.ENERGY_TYPE, energyType));
BlockState state = world.getBlockState(pos);
if (state.getBlock() instanceof ControllerBlock) {
world.setBlockState(pos, state.with(ControllerBlock.ENERGY_TYPE, energyType));
}
}
}
}
@@ -513,17 +518,21 @@ public class Network implements INetwork, IRedstoneConfigurable {
markDirty();
}
@Override
public int getEnergyUsage() {
private void updateEnergyUsage() {
int usage = RS.SERVER_CONFIG.getController().getBaseUsage();
for (INetworkNode node : nodeGraph.all()) {
if (node.canUpdate()) {
if (node.isActive()) {
usage += node.getEnergyUsage();
}
}
return usage;
this.lastEnergyUsage = usage;
}
@Override
public int getEnergyUsage() {
return lastEnergyUsage;
}
@Override

View File

@@ -29,7 +29,7 @@ public class PortableItemGridHandler implements IItemGridHandler {
@Override
public void onExtract(ServerPlayerEntity player, UUID id, int flags) {
if (portableGrid.getStorage() == null || !grid.isActive()) {
if (portableGrid.getStorage() == null || !grid.isGridActive()) {
return;
}
@@ -108,7 +108,7 @@ public class PortableItemGridHandler implements IItemGridHandler {
@Override
@Nonnull
public ItemStack onInsert(ServerPlayerEntity player, ItemStack stack) {
if (portableGrid.getStorage() == null || !grid.isActive()) {
if (portableGrid.getStorage() == null || !grid.isGridActive()) {
return stack;
}
@@ -123,7 +123,7 @@ public class PortableItemGridHandler implements IItemGridHandler {
@Override
public void onInsertHeldItem(ServerPlayerEntity player, boolean single) {
if (player.inventory.getItemStack().isEmpty() || portableGrid.getStorage() == null || !grid.isActive()) {
if (player.inventory.getItemStack().isEmpty() || portableGrid.getStorage() == null || !grid.isGridActive()) {
return;
}

View File

@@ -28,7 +28,8 @@ public class NetworkItemManager implements INetworkItemManager {
for (INetworkNode node : network.getNodeGraph().all()) {
if (node instanceof IWirelessTransmitter &&
node.canUpdate() &&
network.canRun() &&
node.isActive() &&
((IWirelessTransmitter) node).getDimension() == player.dimension) {
IWirelessTransmitter transmitter = (IWirelessTransmitter) node;

View File

@@ -73,7 +73,7 @@ public class CrafterManagerNetworkNode extends NetworkNode {
this.searchBoxMode = searchBoxMode;
}
public boolean isActive() {
public boolean isActiveOnClient() {
BlockState state = world.getBlockState(pos);
if (state.getBlock() instanceof CrafterManagerBlock) {

View File

@@ -77,7 +77,7 @@ public class CraftingMonitorNetworkNode extends NetworkNode implements ICrafting
}
@Override
public boolean isActive() {
public boolean isActiveOnClient() {
BlockState state = world.getBlockState(pos);
if (state.getBlock() instanceof CraftingMonitorBlock) {

View File

@@ -158,7 +158,7 @@ public class FluidInterfaceNetworkNode extends NetworkNode {
INetworkNode facingNode = API.instance().getNetworkNodeManager((ServerWorld) world).getNode(pos.offset(facing));
if (facingNode instanceof ExternalStorageNetworkNode &&
facingNode.canUpdate() &&
facingNode.isActive() &&
((ExternalStorageNetworkNode) facingNode).getDirection() == facing.getOpposite() &&
((ExternalStorageNetworkNode) facingNode).getType() == IType.FLUIDS) {
return true;

View File

@@ -406,7 +406,7 @@ public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, I
}
@Override
public boolean isActive() {
public boolean isGridActive() {
BlockState state = world.getBlockState(pos);
if (state.getBlock() instanceof GridBlock) {

View File

@@ -132,7 +132,7 @@ public class InterfaceNetworkNode extends NetworkNode implements IComparable {
INetworkNode facingNode = API.instance().getNetworkNodeManager((ServerWorld) world).getNode(pos.offset(facing));
if (facingNode instanceof ExternalStorageNetworkNode &&
facingNode.canUpdate() &&
facingNode.isActive() &&
((ExternalStorageNetworkNode) facingNode).getDirection() == facing.getOpposite() &&
((ExternalStorageNetworkNode) facingNode).getType() == IType.ITEMS) {
return true;

View File

@@ -102,11 +102,13 @@ public abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor {
}
@Override
public boolean canUpdate() {
if (redstoneMode.isEnabled(world, pos)) {
if (network != null) {
return network.canRun();
}
public boolean isActive() {
return redstoneMode.isEnabled(world, pos);
}
protected boolean canUpdate() {
if (isActive() && network != null) {
return network.canRun();
}
return false;

View File

@@ -69,7 +69,7 @@ public class RootNetworkNode implements INetworkNode, INetworkNodeVisitor {
}
@Override
public boolean canUpdate() {
public boolean isActive() {
return false;
}

View File

@@ -68,6 +68,10 @@ public class StorageDiskFluidManipulatorWrapper implements IStorageDisk<FluidSta
@Override
@Nonnull
public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) {
if (stack.isEmpty()) {
return stack;
}
if (!IWhitelistBlacklist.acceptsFluid(diskManipulator.getFluidFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) {
return StackUtils.copy(stack, size);
}

View File

@@ -63,6 +63,10 @@ public class StorageDiskItemManipulatorWrapper implements IStorageDisk<ItemStack
@Override
@Nonnull
public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) {
if (stack.isEmpty()) {
return stack;
}
if (!IWhitelistBlacklist.acceptsItem(diskManipulator.getItemFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) {
return ItemHandlerHelper.copyStackWithSize(stack, size);
}

View File

@@ -49,7 +49,7 @@ public class SecurityManager implements ISecurityManager {
this.globalCard = null;
for (INetworkNode node : network.getNodeGraph().all()) {
if (node instanceof ISecurityCardContainer && node.canUpdate()) {
if (node instanceof ISecurityCardContainer && node.isActive()) {
ISecurityCardContainer container = (ISecurityCardContainer) node;
for (ISecurityCard card : container.getCards()) {

View File

@@ -37,7 +37,7 @@ public class FluidStorageCache implements IStorageCache<FluidStack> {
storages.clear();
network.getNodeGraph().all().stream()
.filter(node -> node.canUpdate() && node instanceof IStorageProvider)
.filter(node -> node.isActive() && node instanceof IStorageProvider)
.forEach(node -> ((IStorageProvider) node).addFluidStorages(storages));
list.clear();
@@ -110,6 +110,11 @@ public class FluidStorageCache implements IStorageCache<FluidStack> {
listeners.remove(listener);
}
@Override
public void reAttachListeners() {
listeners.forEach(IStorageCacheListener::onAttached);
}
@Override
public void sort() {
storages.sort(IStorage.COMPARATOR);

View File

@@ -37,7 +37,7 @@ public class ItemStorageCache implements IStorageCache<ItemStack> {
storages.clear();
network.getNodeGraph().all().stream()
.filter(node -> node.canUpdate() && node instanceof IStorageProvider)
.filter(node -> node.isActive() && node instanceof IStorageProvider)
.forEach(node -> ((IStorageProvider) node).addItemStorages(storages));
list.clear();
@@ -110,6 +110,11 @@ public class ItemStorageCache implements IStorageCache<ItemStack> {
listeners.remove(listener);
}
@Override
public void reAttachListeners() {
listeners.forEach(IStorageCacheListener::onAttached);
}
@Override
public void sort() {
storages.sort(IStorage.COMPARATOR);

View File

@@ -69,6 +69,11 @@ public class PortableFluidStorageCache implements IStorageCache<FluidStack> {
listeners.remove(listener);
}
@Override
public void reAttachListeners() {
listeners.forEach(IStorageCacheListener::onAttached);
}
@Override
public void sort() {
// NO OP

View File

@@ -69,6 +69,11 @@ public class PortableItemStorageCache implements IStorageCache<ItemStack> {
listeners.remove(listener);
}
@Override
public void reAttachListeners() {
listeners.forEach(IStorageCacheListener::onAttached);
}
@Override
public void sort() {
// NO OP

View File

@@ -19,6 +19,6 @@ public class CrafterManagerSlot extends BaseSlot {
@Override
public boolean isEnabled() {
return yPos >= display.getTopHeight() && yPos < display.getTopHeight() + 18 * display.getVisibleRows() && visible && crafterManager.isActive();
return yPos >= display.getTopHeight() && yPos < display.getTopHeight() + 18 * display.getVisibleRows() && visible && crafterManager.isActiveOnClient();
}
}

View File

@@ -3,8 +3,19 @@ package com.raoulvdberge.refinedstorage.energy;
import net.minecraftforge.energy.EnergyStorage;
public class BaseEnergyStorage extends EnergyStorage {
public BaseEnergyStorage(int capacity, int maxTransfer) {
super(capacity, maxTransfer);
public BaseEnergyStorage(int capacity, int maxReceive, int maxExtract) {
super(capacity, maxReceive, maxExtract);
}
// @Volatile: Impl from EnergyStorage#extractEnergy, without the canExtract check
public int extractEnergyBypassCanExtract(int maxExtract, boolean simulate) {
int energyExtracted = Math.min(energy, maxExtract);
if (!simulate) {
energy -= energyExtracted;
}
return energyExtracted;
}
public void setStored(int energy) {

View File

@@ -124,7 +124,7 @@ public class PortableGridBakedModel extends DelegateBakedModel {
break;
}
if (portableGrid.isActive()) {
if (portableGrid.isGridActive()) {
return new PortableGridItemBakedModel(baseConnected, myDisk);
} else {
return new PortableGridItemBakedModel(baseDisconnected, myDisk);

View File

@@ -96,7 +96,7 @@ public class CrafterManagerScreen extends BaseScreen<CrafterManagerContainer> im
blit(x, yy, 0, getTopHeight() + (18 * 3), xSize, getBottomHeight());
if (crafterManager.isActive()) {
if (crafterManager.isActiveOnClient()) {
for (Slot slot : container.inventorySlots) {
if (slot instanceof CrafterManagerSlot && slot.isEnabled()) {
blit(x + slot.xPos - 1, y + slot.yPos - 1, 0, 193, 18, 18);
@@ -114,7 +114,7 @@ public class CrafterManagerScreen extends BaseScreen<CrafterManagerContainer> im
renderString(7, 7, title.getFormattedText());
renderString(7, getYPlayerInventory() - 12, I18n.format("container.inventory"));
if (container != null && crafterManager.isActive()) {
if (container != null && crafterManager.isActiveOnClient()) {
for (Map.Entry<String, Integer> heading : container.getHeadings().entrySet()) {
int y = heading.getValue();
@@ -152,12 +152,6 @@ public class CrafterManagerScreen extends BaseScreen<CrafterManagerContainer> im
@Override
public boolean keyPressed(int key, int scanCode, int modifiers) {
if (key == GLFW.GLFW_KEY_ESCAPE) {
minecraft.player.closeScreen();
return true;
}
if (searchField.keyPressed(key, scanCode, modifiers) || searchField.func_212955_f()) {
return true;
}
@@ -220,7 +214,7 @@ public class CrafterManagerScreen extends BaseScreen<CrafterManagerContainer> im
@Override
public int getRows() {
return !crafterManager.isActive() ? 0 : container.getRows();
return !crafterManager.isActiveOnClient() ? 0 : container.getRows();
}
@Override

View File

@@ -141,7 +141,7 @@ public class CraftingMonitorScreen extends BaseScreen<CraftingMonitorContainer>
}
public List<ICraftingMonitorElement> getElements() {
if (!craftingMonitor.isActive()) {
if (!craftingMonitor.isActiveOnClient()) {
return Collections.emptyList();
}
@@ -236,7 +236,7 @@ public class CraftingMonitorScreen extends BaseScreen<CraftingMonitorContainer>
@Override
public void renderBackground(int x, int y, int mouseX, int mouseY) {
if (craftingMonitor.isActive()) {
if (craftingMonitor.isActiveOnClient()) {
tabs.drawBackground(x, y - tabs.getHeight());
}
@@ -246,7 +246,7 @@ public class CraftingMonitorScreen extends BaseScreen<CraftingMonitorContainer>
scrollbar.render();
tabs.drawForeground(x, y - tabs.getHeight(), mouseX, mouseY, craftingMonitor.isActive());
tabs.drawForeground(x, y - tabs.getHeight(), mouseX, mouseY, craftingMonitor.isActiveOnClient());
}
@Override

View File

@@ -65,7 +65,7 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
this.grid = grid;
this.view = grid.getGridType() == GridType.FLUID ? new FluidGridView(this, getDefaultSorter(), getSorters()) : new ItemGridView(this, getDefaultSorter(), getSorters());
this.wasConnected = this.grid.isActive();
this.wasConnected = this.grid.isGridActive();
this.tabs = new TabListWidget(this, new ElementDrawers(this, font), grid::getTabs, grid::getTotalTabPages, grid::getTabPage, grid::getTabSelected, IGrid.TABS_PER_PAGE);
this.tabs.addListener(new TabListWidget.ITabListListener() {
@Override
@@ -160,8 +160,8 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
@Override
public void tick(int x, int y) {
if (wasConnected != grid.isActive()) {
wasConnected = grid.isActive();
if (wasConnected != grid.isGridActive()) {
wasConnected = grid.isGridActive();
view.sort();
}
@@ -238,7 +238,7 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
}
private boolean isOverSlotWithStack() {
return grid.isActive() && isOverSlot() && slotNumber < view.getStacks().size();
return grid.isGridActive() && isOverSlot() && slotNumber < view.getStacks().size();
}
private boolean isOverSlot() {
@@ -354,7 +354,7 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
RenderSystem.setupGui3DDiffuseLighting();
for (int i = 0; i < 9 * getVisibleRows(); ++i) {
if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isActive()) {
if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isGridActive()) {
this.slotNumber = slot;
}
@@ -362,8 +362,8 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
view.getStacks().get(slot).draw(this, x, y);
}
if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isActive()) {
int color = grid.isActive() ? -2130706433 : 0xFF5B5B5B;
if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isGridActive()) {
int color = grid.isGridActive() ? -2130706433 : 0xFF5B5B5B;
RenderSystem.disableLighting();
RenderSystem.disableDepthTest();
@@ -435,7 +435,7 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
RS.NETWORK_HANDLER.sendToServer(new GridPatternCreateMessage(((GridNetworkNode) grid).getPos()));
return true;
} else if (grid.isActive()) {
} else if (grid.isGridActive()) {
if (clickedClear) {
minecraft.getSoundHandler().play(SimpleSound.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
@@ -538,12 +538,6 @@ public class GridScreen extends BaseScreen<GridContainer> implements IScreenInfo
@Override
public boolean keyPressed(int key, int scanCode, int modifiers) {
if (key == GLFW.GLFW_KEY_ESCAPE) {
minecraft.player.closeScreen();
return true;
}
if (searchField.keyPressed(key, scanCode, modifiers) || searchField.func_212955_f()) {
return true;
}

View File

@@ -151,6 +151,10 @@ public class FluidGridStack implements IGridStack {
@Override
public String getFormattedFullQuantity() {
if (zeroed) {
return "0 mB";
}
return API.instance().getQuantityFormatter().format(getQuantity()) + " mB";
}

View File

@@ -164,6 +164,10 @@ public class ItemGridStack implements IGridStack {
@Override
public String getFormattedFullQuantity() {
if (zeroed) {
return "0";
}
return API.instance().getQuantityFormatter().format(getQuantity());
}

View File

@@ -46,7 +46,7 @@ public abstract class BaseGridView implements IGridView {
List<IGridStack> stacks = new ArrayList<>();
if (screen.getGrid().isActive()) {
if (screen.getGrid().isGridActive()) {
stacks.addAll(map.values());
IGrid grid = screen.getGrid();

View File

@@ -27,12 +27,25 @@ public class FluidGridView extends BaseGridView {
return;
}
// COMMENT 1 (about this if check in general)
// Update the other id reference if needed.
// Taking a stack out - and then re-inserting it - gives the new stack a new ID
// With that new id, the reference for the crafting stack would be outdated.
// COMMENT 2 (about map.containsKey(stack.getOtherId()))
// This check is needed or the .updateOtherId() call will crash with a NPE in high-update environments.
// This is because we might have scenarios where we process "old" delta packets from another session when we haven't received any initial update packet from the new session.
// (This is because of the executeLater system)
// This causes the .updateOtherId() to fail with a NPE because the map is still empty or the IDs mismatch.
// We could use !map.isEmpty() here too. But if we have 2 "old" delta packets, it would rightfully ignore the first one. But this method mutates the map and would put an entry.
// This means that on the second delta packet it would still crash because the map wouldn't be empty anymore.
if (!stack.isCraftable() &&
stack.getOtherId() != null) {
map.get(stack.getOtherId()).updateOtherId(stack.getId());
stack.getOtherId() != null &&
map.containsKey(stack.getOtherId())) {
IGridStack craftingStack = map.get(stack.getOtherId());
craftingStack.updateOtherId(stack.getId());
craftingStack.setTrackerEntry(stack.getTrackerEntry());
}
FluidGridStack existing = (FluidGridStack) map.get(stack.getId());

View File

@@ -27,12 +27,25 @@ public class ItemGridView extends BaseGridView {
return;
}
// COMMENT 1 (about this if check in general)
// Update the other id reference if needed.
// Taking a stack out - and then re-inserting it - gives the new stack a new ID
// With that new id, the reference for the crafting stack would be outdated.
// COMMENT 2 (about map.containsKey(stack.getOtherId()))
// This check is needed or the .updateOtherId() call will crash with a NPE in high-update environments.
// This is because we might have scenarios where we process "old" delta packets from another session when we haven't received any initial update packet from the new session.
// (This is because of the executeLater system)
// This causes the .updateOtherId() to fail with a NPE because the map is still empty or the IDs mismatch.
// We could use !map.isEmpty() here too. But if we have 2 "old" delta packets, it would rightfully ignore the first one. But this method mutates the map and would put an entry.
// This means that on the second delta packet it would still crash because the map wouldn't be empty anymore.
if (!stack.isCraftable() &&
stack.getOtherId() != null) {
map.get(stack.getOtherId()).updateOtherId(stack.getId());
stack.getOtherId() != null &&
map.containsKey(stack.getOtherId())) {
IGridStack craftingStack = map.get(stack.getOtherId());
craftingStack.updateOtherId(stack.getId());
craftingStack.setTrackerEntry(stack.getTrackerEntry());
}
ItemGridStack existing = (ItemGridStack) map.get(stack.getId());

View File

@@ -71,6 +71,26 @@ public class SearchWidget extends TextFieldWidget {
}
result = true;
} else if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
saveHistory();
if (!canLoseFocus) {
// If we can't lose focus,
// and we press escape,
// we unfocus ourselves,
// and close the screen immediately.
setFocused(false);
result = false; // Bubble the event up to the screen.
} else {
// If we can lose focus,
// and we press escape,
// we unfocus ourselves.
// On the next escape press, the screen will close.
setFocused(false);
result = true;
}
}
}

View File

@@ -166,7 +166,7 @@ public class ControllerTile extends BaseTile implements INetworkNodeProxy<RootNe
List<ClientNode> nodes = new ArrayList<>();
for (INetworkNode node : tile.getNetwork().getNodeGraph().all()) {
if (node.canUpdate()) {
if (node.isActive()) {
ItemStack stack = node.getItemStack();
if (stack.isEmpty()) {

View File

@@ -26,7 +26,7 @@ public interface ICraftingMonitor {
@Nullable
ICraftingManager getCraftingManager();
boolean isActive();
boolean isActiveOnClient();
void onClosed(PlayerEntity player);

View File

@@ -111,7 +111,7 @@ public class WirelessCraftingMonitor implements ICraftingMonitor {
}
@Override
public boolean isActive() {
public boolean isActiveOnClient() {
return true;
}

View File

@@ -291,7 +291,7 @@ public class WirelessFluidGrid implements INetworkAwareGrid {
}
@Override
public boolean isActive() {
public boolean isGridActive() {
return true;
}

View File

@@ -297,7 +297,7 @@ public class WirelessGrid implements INetworkAwareGrid {
}
@Override
public boolean isActive() {
public boolean isGridActive() {
return true;
}

View File

@@ -45,7 +45,7 @@ public interface IPortableGrid {
IStorageTracker<FluidStack> getFluidStorageTracker();
boolean isActive();
boolean isGridActive();
PortableGridDiskState getDiskState();
}

View File

@@ -427,7 +427,7 @@ public class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainer
}
@Override
public boolean isActive() {
public boolean isGridActive() {
if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() &&
((PortableGridBlockItem) stack.getItem()).getType() != PortableGridBlockItem.Type.CREATIVE &&
stack.getCapability(CapabilityEnergy.ENERGY).orElse(null).getEnergyStored() <= RS.SERVER_CONFIG.getPortableGrid().getOpenUsage()) {
@@ -469,7 +469,7 @@ public class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainer
return PortableGridDiskState.NONE;
}
if (!isActive()) {
if (!isGridActive()) {
return PortableGridDiskState.DISCONNECTED;
}

View File

@@ -222,7 +222,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
this.loadStorage();
active = isActive();
active = isGridActive();
diskState = getDiskState();
}
@@ -518,7 +518,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
}
@Override
public boolean isActive() {
public boolean isGridActive() {
if (world.isRemote) {
BlockState state = world.getBlockState(pos);
@@ -585,7 +585,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
return PortableGridDiskState.NONE;
}
if (!isActive()) {
if (!isGridActive()) {
return PortableGridDiskState.DISCONNECTED;
}
@@ -610,7 +610,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
world.setBlockState(pos, world.getBlockState(pos).with(PortableGridBlock.DISK_STATE, diskState));
}
boolean isActive = isActive();
boolean isActive = isGridActive();
if (this.active != isActive) {
this.active = isActive;