Fixed cases where Refined Storage unwillingly acts like a chunkloader.

This commit is contained in:
raoulvdberge
2020-07-17 02:58:43 +02:00
parent b0200f457c
commit e78cadec2a
18 changed files with 102 additions and 27 deletions

View File

@@ -2,6 +2,7 @@
### 1.9.2
- Fixed crash with Forge version 67 (Darkere)
- Fixed cases where Refined Storage unwillingly acts like a chunkloader (raoulvdberge)
- Networks that are in a chunk that isn't loaded will no longer work, they will turn off. Chunkload the Controller to maintain a functioning network over long distances (Darkere/raoulvdberge)
- Re-added interdimensional networks with the Network Transmitter and Network Receiver (raoulvdberge)

View File

@@ -21,12 +21,12 @@ public interface IExternalStorageProvider<T> {
/**
* @param context the context of the external storage
* @param tile the tile supplier
* @param tile the tile
* @param direction the direction of the external storage
* @return the external storage handler
*/
@Nonnull
IExternalStorage<T> provide(IExternalStorageContext context, Supplier<TileEntity> tile, Direction direction);
IExternalStorage<T> provide(IExternalStorageContext context, TileEntity tile, Direction direction);
/**
* Returns the priority of this external storage provider.

View File

@@ -80,11 +80,13 @@ public class Network implements INetwork, IRedstoneConfigurable {
private ControllerBlock.EnergyType lastEnergyType = ControllerBlock.EnergyType.OFF;
private int lastEnergyUsage;
private RedstoneMode redstoneMode = RedstoneMode.IGNORE;
private boolean redstonePowered = false;
private boolean amILoaded = false;
private boolean throttlingDisabled = true; // Will be enabled after first update
private boolean couldRun;
private int ticksSinceUpdateChanged;
private int ticks;
public Network(World world, BlockPos pos, NetworkType type) {
this.pos = pos;
@@ -115,7 +117,11 @@ public class Network implements INetwork, IRedstoneConfigurable {
@Override
public boolean canRun() {
return amILoaded && energy.getEnergyStored() >= getEnergyUsage() && redstoneMode.isEnabled(world, pos);
return amILoaded && energy.getEnergyStored() >= getEnergyUsage() && redstoneMode.isEnabled(redstonePowered);
}
public void setRedstonePowered(boolean redstonePowered) {
this.redstonePowered = redstonePowered;
}
@Override
@@ -136,6 +142,12 @@ public class Network implements INetwork, IRedstoneConfigurable {
@Override
public void update() {
if (!world.isRemote) {
if (ticks == 0) {
redstonePowered = world.isBlockPowered(pos);
}
++ticks;
amILoaded = world.isBlockPresent(pos);
updateEnergyUsage();
@@ -498,7 +510,7 @@ public class Network implements INetwork, IRedstoneConfigurable {
}
public ControllerBlock.EnergyType getEnergyType() {
if (!redstoneMode.isEnabled(world, pos)) {
if (!redstoneMode.isEnabled(redstonePowered)) {
return ControllerBlock.EnergyType.OFF;
}
@@ -532,7 +544,7 @@ public class Network implements INetwork, IRedstoneConfigurable {
}
private void updateEnergyUsage() {
if (!redstoneMode.isEnabled(world, pos)) {
if (!redstoneMode.isEnabled(redstonePowered)) {
this.lastEnergyUsage = 0;
return;
}

View File

@@ -77,7 +77,7 @@ public class ConstructorNetworkNode extends NetworkNode implements IComparable,
public void update() {
super.update();
if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0) {
if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0 && world.isBlockPresent(pos)) {
if (type == IType.ITEMS && !itemFilters.getStackInSlot(0).isEmpty()) {
ItemStack stack = itemFilters.getStackInSlot(0);

View File

@@ -84,7 +84,7 @@ public class DestructorNetworkNode extends NetworkNode implements IComparable, I
public void update() {
super.update();
if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0) {
if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0 && world.isBlockPresent(pos)) {
if (type == IType.ITEMS) {
if (pickupItem) {
pickupItems();

View File

@@ -61,7 +61,7 @@ public class DetectorNetworkNode extends NetworkNode implements IComparable, ITy
public void update() {
super.update();
if (powered != wasPowered) {
if (powered != wasPowered && world.isBlockPresent(pos)) {
wasPowered = powered;
world.setBlockState(pos, world.getBlockState(pos).with(DetectorBlock.POWERED, powered));

View File

@@ -85,7 +85,7 @@ public class ExporterNetworkNode extends NetworkNode implements IComparable, ITy
public void update() {
super.update();
if (canUpdate() && ticks % upgrades.getSpeed() == 0) {
if (canUpdate() && ticks % upgrades.getSpeed() == 0 && world.isBlockPresent(pos)) {
if (type == IType.ITEMS) {
IItemHandler handler = WorldUtils.getItemHandler(getFacingTile(), getDirection().getOpposite());
@@ -236,7 +236,6 @@ public class ExporterNetworkNode extends NetworkNode implements IComparable, ITy
markDirty();
}
@Override
public ResourceLocation getId() {
return ID;

View File

@@ -85,7 +85,7 @@ public class ExternalStorageNetworkNode extends NetworkNode implements IStorageP
public void update() {
super.update();
if (canUpdate()) {
if (canUpdate() && world.isBlockPresent(pos)) {
if (networkTicks++ == 0) {
updateStorage(network, InvalidateCause.INITIAL_TICK_INVALIDATION);
@@ -214,7 +214,7 @@ public class ExternalStorageNetworkNode extends NetworkNode implements IStorageP
if (type == IType.ITEMS) {
for (IExternalStorageProvider<ItemStack> provider : API.instance().getExternalStorageProviders(StorageType.ITEM)) {
if (provider.canProvide(facing, getDirection())) {
itemStorages.add(provider.provide(this, this::getFacingTile, getDirection()));
itemStorages.add(provider.provide(this, getFacingTile(), getDirection()));
break;
}
@@ -222,7 +222,7 @@ public class ExternalStorageNetworkNode extends NetworkNode implements IStorageP
} else if (type == IType.FLUIDS) {
for (IExternalStorageProvider<FluidStack> provider : API.instance().getExternalStorageProviders(StorageType.FLUID)) {
if (provider.canProvide(facing, getDirection())) {
fluidStorages.add(provider.provide(this, this::getFacingTile, getDirection()));
fluidStorages.add(provider.provide(this, getFacingTile(), getDirection()));
break;
}

View File

@@ -250,7 +250,7 @@ public class FluidInterfaceNetworkNode extends NetworkNode {
}
private void onTankOutChanged() {
if (!world.isRemote) {
if (!world.isRemote && world.isBlockPresent(pos)) {
((FluidInterfaceTile) world.getTileEntity(pos)).getDataManager().sendParameterToWatchers(FluidInterfaceTile.TANK_OUT);
}

View File

@@ -60,7 +60,7 @@ public class ImporterNetworkNode extends NetworkNode implements IComparable, IWh
public void update() {
super.update();
if (!canUpdate()) {
if (!canUpdate() || !world.isBlockPresent(pos)) {
return;
}

View File

@@ -30,10 +30,21 @@ public abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor {
@Nullable
protected INetwork network;
// @Volatile: Mental note. At this moment world instances are retained in Minecraft (since 1.16).
// This means that during the entire server lifetime, all worlds are present and will not change their instance.
// However, due to the memory footprint of worlds and modded minecraft having the tendency to have lots of worlds,
// Forge is planning to unload (aka remove) worlds so their instances will change.
// This is problematic as this attribute will target the wrong world in that case.
// Idea: possibly change to a getter based on RegistryKey<World>?
// Another note: this attribute isn't the *real* problem. Because network nodes are in WorldSavedData in a tick handler,
// new instances of network nodes will be created when the world refreshes (causing this field to be different too).
// However, network nodes in the network graph *AREN'T* recreated when the world refreshes, causing the graph to have the incorrect instance, and even worse,
// having multiple different instances of the same network node.
protected World world;
protected BlockPos pos;
protected int ticks;
protected RedstoneMode redstoneMode = RedstoneMode.IGNORE;
private boolean redstonePowered = false;
@Nullable
protected UUID owner;
protected String version;
@@ -102,7 +113,7 @@ public abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor {
@Override
public boolean isActive() {
return redstoneMode.isEnabled(world, pos);
return redstoneMode.isEnabled(redstonePowered);
}
protected final boolean canUpdate() {
@@ -121,8 +132,16 @@ public abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor {
return 4;
}
public void setRedstonePowered(boolean redstonePowered) {
this.redstonePowered = redstonePowered;
}
@Override
public void update() {
if (ticks == 0) {
redstonePowered = world.isBlockPowered(pos);
}
++ticks;
boolean canUpdate = canUpdate();

View File

@@ -20,8 +20,14 @@ public class FluidExternalStorageProvider implements IExternalStorageProvider<Fl
@Nonnull
@Override
public IExternalStorage<FluidStack> provide(IExternalStorageContext context, Supplier<TileEntity> tile, Direction direction) {
return new FluidExternalStorage(context, () -> WorldUtils.getFluidHandler(tile.get(), direction.getOpposite()), tile.get() instanceof FluidInterfaceTile);
public IExternalStorage<FluidStack> provide(IExternalStorageContext context, TileEntity tile, Direction direction) {
return new FluidExternalStorage(context, () -> {
if (!tile.getWorld().isBlockPresent(tile.getPos())) {
return null;
}
return WorldUtils.getFluidHandler(tile, direction.getOpposite());
}, tile instanceof FluidInterfaceTile);
}
@Override

View File

@@ -29,8 +29,14 @@ public class ItemExternalStorageProvider implements IExternalStorageProvider<Ite
@Nonnull
@Override
public IExternalStorage<ItemStack> provide(IExternalStorageContext context, Supplier<TileEntity> tile, Direction direction) {
return new ItemExternalStorage(context, () -> WorldUtils.getItemHandler(tile.get(), direction.getOpposite()), tile.get() instanceof InterfaceTile);
public IExternalStorage<ItemStack> provide(IExternalStorageContext context, TileEntity tile, Direction direction) {
return new ItemExternalStorage(context, () -> {
if (!tile.getWorld().isBlockPresent(tile.getPos())) {
return null;
}
return WorldUtils.getItemHandler(tile, direction.getOpposite());
}, tile instanceof InterfaceTile);
}
@Override

View File

@@ -1,7 +1,10 @@
package com.refinedmods.refinedstorage.block;
import com.refinedmods.refinedstorage.RS;
import com.refinedmods.refinedstorage.api.network.INetwork;
import com.refinedmods.refinedstorage.api.network.NetworkType;
import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.apiimpl.network.Network;
import com.refinedmods.refinedstorage.container.ControllerContainer;
import com.refinedmods.refinedstorage.tile.ControllerTile;
import com.refinedmods.refinedstorage.util.BlockUtils;
@@ -27,6 +30,7 @@ import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.fml.network.NetworkHooks;
@@ -105,6 +109,19 @@ public class ControllerBlock extends BaseBlock {
}
}
@Override
@SuppressWarnings("deprecation")
public void neighborChanged(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {
super.neighborChanged(state, world, pos, blockIn, fromPos, isMoving);
if (!world.isRemote) {
INetwork network = API.instance().getNetworkManager((ServerWorld) world).getNetwork(pos);
if (network instanceof Network) {
((Network) network).setRedstonePowered(world.isBlockPowered(pos));
}
}
}
@Override
@SuppressWarnings("deprecation")
public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult hit) {

View File

@@ -2,6 +2,7 @@ package com.refinedmods.refinedstorage.block;
import com.refinedmods.refinedstorage.api.network.node.INetworkNode;
import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy;
import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode;
import com.refinedmods.refinedstorage.tile.NetworkNodeTile;
import net.minecraft.block.Block;
@@ -15,6 +16,7 @@ import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.items.IItemHandler;
public abstract class NetworkNodeBlock extends BaseBlock {
@@ -28,6 +30,19 @@ public abstract class NetworkNodeBlock extends BaseBlock {
}
}
@Override
@SuppressWarnings("deprecation")
public void neighborChanged(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {
super.neighborChanged(state, world, pos, blockIn, fromPos, isMoving);
if (!world.isRemote) {
INetworkNode node = API.instance().getNetworkNodeManager((ServerWorld) world).getNode(pos);
if (node instanceof NetworkNode) {
((NetworkNode) node).setRedstonePowered(world.isBlockPowered(pos));
}
}
}
@Override
@SuppressWarnings("deprecation")
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
@@ -80,7 +95,7 @@ public abstract class NetworkNodeBlock extends BaseBlock {
public boolean hasTileEntity(BlockState state) {
return true;
}
public boolean hasConnectedState() {
return false;
}

View File

@@ -12,14 +12,14 @@ public enum RedstoneMode {
private static final String NBT = "RedstoneMode";
public boolean isEnabled(World world, BlockPos pos) {
public boolean isEnabled(boolean powered) {
switch (this) {
case IGNORE:
return true;
case HIGH:
return world.isBlockPowered(pos);
return powered;
case LOW:
return !world.isBlockPowered(pos);
return !powered;
default:
return false;
}

View File

@@ -541,7 +541,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
return false;
}
return redstoneMode.isEnabled(world, pos);
return redstoneMode.isEnabled(world.isBlockPowered(pos));
}
@Override
@@ -565,7 +565,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
public void drainEnergy(int energy) {
if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() &&
type != PortableGridBlockItem.Type.CREATIVE &&
redstoneMode.isEnabled(world, pos)) {
redstoneMode.isEnabled(world.isBlockPowered(pos))) {
energyStorage.extractEnergy(energy, false);
updateState();

View File

@@ -31,7 +31,7 @@ import java.util.UUID;
public final class WorldUtils {
public static void updateBlock(@Nullable World world, BlockPos pos) {
if (world != null) {
if (world != null && world.isBlockPresent(pos)) {
BlockState state = world.getBlockState(pos);
world.notifyBlockUpdate(pos, state, state, 1 | 2);