diff --git a/src/main/java/appeng/block/crafting/AbstractCraftingUnitBlock.java b/src/main/java/appeng/block/crafting/AbstractCraftingUnitBlock.java index dec8ba807..9158d3fc4 100644 --- a/src/main/java/appeng/block/crafting/AbstractCraftingUnitBlock.java +++ b/src/main/java/appeng/block/crafting/AbstractCraftingUnitBlock.java @@ -59,7 +59,7 @@ public abstract class AbstractCraftingUnitBlock ex final BlockPos fromPos, boolean isMoving) { final CraftingTileEntity cp = this.getTileEntity(worldIn, pos); if (cp != null) { - cp.updateMultiBlock(); + cp.updateMultiBlock(fromPos); } } diff --git a/src/main/java/appeng/block/qnb/QuantumBaseBlock.java b/src/main/java/appeng/block/qnb/QuantumBaseBlock.java index 204aa8e6b..90889be47 100644 --- a/src/main/java/appeng/block/qnb/QuantumBaseBlock.java +++ b/src/main/java/appeng/block/qnb/QuantumBaseBlock.java @@ -70,7 +70,7 @@ public abstract class QuantumBaseBlock extends AEBaseTileBlock { boolean isMoving) { final SpatialPylonTileEntity tsp = this.getTileEntity(world, pos); if (tsp != null) { - tsp.neighborChanged(); + tsp.neighborChanged(fromPos); } } diff --git a/src/main/java/appeng/me/cache/SpatialPylonCache.java b/src/main/java/appeng/me/cache/SpatialPylonCache.java index 7d4eb9142..38d13fec5 100644 --- a/src/main/java/appeng/me/cache/SpatialPylonCache.java +++ b/src/main/java/appeng/me/cache/SpatialPylonCache.java @@ -82,21 +82,21 @@ public class SpatialPylonCache implements ISpatialCache { int pylonBlocks = 0; for (final SpatialPylonCluster cl : this.clusters.values()) { if (this.captureMax == null) { - this.captureMax = cl.getMax().copy(); + this.captureMax = new DimensionalCoord(cl.getWorld(), cl.getBoundsMax()); } if (this.captureMin == null) { - this.captureMin = cl.getMin().copy(); + this.captureMin = new DimensionalCoord(cl.getWorld(), cl.getBoundsMin()); } pylonBlocks += cl.tileCount(); - this.captureMin.x = Math.min(this.captureMin.x, cl.getMin().x); - this.captureMin.y = Math.min(this.captureMin.y, cl.getMin().y); - this.captureMin.z = Math.min(this.captureMin.z, cl.getMin().z); + this.captureMin.x = Math.min(this.captureMin.x, cl.getBoundsMin().getX()); + this.captureMin.y = Math.min(this.captureMin.y, cl.getBoundsMin().getY()); + this.captureMin.z = Math.min(this.captureMin.z, cl.getBoundsMin().getZ()); - this.captureMax.x = Math.max(this.captureMax.x, cl.getMax().x); - this.captureMax.y = Math.max(this.captureMax.y, cl.getMax().y); - this.captureMax.z = Math.max(this.captureMax.z, cl.getMax().z); + this.captureMax.x = Math.max(this.captureMax.x, cl.getBoundsMax().getX()); + this.captureMax.y = Math.max(this.captureMax.y, cl.getBoundsMax().getY()); + this.captureMax.z = Math.max(this.captureMax.z, cl.getBoundsMax().getZ()); } double maxPower = 0; @@ -110,28 +110,40 @@ public class SpatialPylonCache implements ISpatialCache { case X: this.isValid = this.isValid - && ((this.captureMax.y == cl.getMin().y || this.captureMin.y == cl.getMax().y) - || (this.captureMax.z == cl.getMin().z || this.captureMin.z == cl.getMax().z)) - && ((this.captureMax.y == cl.getMax().y || this.captureMin.y == cl.getMin().y) - || (this.captureMax.z == cl.getMax().z || this.captureMin.z == cl.getMin().z)); + && ((this.captureMax.y == cl.getBoundsMin().getY() + || this.captureMin.y == cl.getBoundsMax().getY()) + || (this.captureMax.z == cl.getBoundsMin().getZ() + || this.captureMin.z == cl.getBoundsMax().getZ())) + && ((this.captureMax.y == cl.getBoundsMax().getY() + || this.captureMin.y == cl.getBoundsMin().getY()) + || (this.captureMax.z == cl.getBoundsMax().getZ() + || this.captureMin.z == cl.getBoundsMin().getZ())); break; case Y: this.isValid = this.isValid - && ((this.captureMax.x == cl.getMin().x || this.captureMin.x == cl.getMax().x) - || (this.captureMax.z == cl.getMin().z || this.captureMin.z == cl.getMax().z)) - && ((this.captureMax.x == cl.getMax().x || this.captureMin.x == cl.getMin().x) - || (this.captureMax.z == cl.getMax().z || this.captureMin.z == cl.getMin().z)); + && ((this.captureMax.x == cl.getBoundsMin().getX() + || this.captureMin.x == cl.getBoundsMax().getX()) + || (this.captureMax.z == cl.getBoundsMin().getZ() + || this.captureMin.z == cl.getBoundsMax().getZ())) + && ((this.captureMax.x == cl.getBoundsMax().getX() + || this.captureMin.x == cl.getBoundsMin().getX()) + || (this.captureMax.z == cl.getBoundsMax().getZ() + || this.captureMin.z == cl.getBoundsMin().getZ())); break; case Z: this.isValid = this.isValid - && ((this.captureMax.y == cl.getMin().y || this.captureMin.y == cl.getMax().y) - || (this.captureMax.x == cl.getMin().x || this.captureMin.x == cl.getMax().x)) - && ((this.captureMax.y == cl.getMax().y || this.captureMin.y == cl.getMin().y) - || (this.captureMax.x == cl.getMax().x || this.captureMin.x == cl.getMin().x)); + && ((this.captureMax.y == cl.getBoundsMin().getY() + || this.captureMin.y == cl.getBoundsMax().getY()) + || (this.captureMax.x == cl.getBoundsMin().getX() + || this.captureMin.x == cl.getBoundsMax().getX())) + && ((this.captureMax.y == cl.getBoundsMax().getY() + || this.captureMin.y == cl.getBoundsMin().getY()) + || (this.captureMax.x == cl.getBoundsMax().getX() + || this.captureMin.x == cl.getBoundsMin().getX())); break; case UNFORMED: diff --git a/src/main/java/appeng/me/cluster/IAECluster.java b/src/main/java/appeng/me/cluster/IAECluster.java index b64b510cf..4cb34f05c 100644 --- a/src/main/java/appeng/me/cluster/IAECluster.java +++ b/src/main/java/appeng/me/cluster/IAECluster.java @@ -20,10 +20,23 @@ package appeng.me.cluster; import java.util.Iterator; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; + import appeng.api.networking.IGridHost; public interface IAECluster { + /** + * The minimum x,y,z position still within the bounds of the cluster. + */ + BlockPos getBoundsMin(); + + /** + * The maximum x,y,z position still within the bounds of the cluster. + */ + BlockPos getBoundsMax(); + void updateStatus(boolean updateGrid); void destroy(); diff --git a/src/main/java/appeng/me/cluster/MBCalculator.java b/src/main/java/appeng/me/cluster/MBCalculator.java index 93ae82060..5c6110df0 100644 --- a/src/main/java/appeng/me/cluster/MBCalculator.java +++ b/src/main/java/appeng/me/cluster/MBCalculator.java @@ -54,6 +54,32 @@ public abstract class MBCalculator { return modificationInProgress.get() != null; } + public void updateMultiblockAfterNeighborUpdate(final World world, final WorldCoord loc, BlockPos changedPos) { + boolean recheck; + + IAECluster cluster = target.getCluster(); + if (cluster != null) { + if (isWithinBounds(changedPos, cluster.getBoundsMin(), cluster.getBoundsMax())) { + // If the location is part of the current multiblock, always re-check + recheck = true; + } else { + // If the location is outside, only re-check if it would now be considered part + // of it + recheck = isValidTileAt(world, changedPos.getX(), changedPos.getY(), changedPos.getZ()); + } + } else { + // Always recheck if the tile is not part of a cluster, because the adjacent + // block could have + // previously been a valid tile, but in a wrong placement, or the other way + // around. + recheck = true; + } + + if (recheck) { + calculateMultiblock(world, loc); + } + } + public void calculateMultiblock(final World world, final WorldCoord loc) { if (Platform.isClient() || isModificationInProgress()) { return; @@ -127,6 +153,14 @@ public abstract class MBCalculator { this.disconnect(); } + private static boolean isWithinBounds(BlockPos pos, BlockPos boundsMin, BlockPos boundsMax) { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + return (x >= boundsMin.getX() && y >= boundsMin.getY() && z >= boundsMin.getZ() && x <= boundsMax.getX() + && y <= boundsMax.getY() && z <= boundsMax.getZ()); + } + private boolean isValidTileAt(final World w, final int x, final int y, final int z) { return this.isValidTile(w.getTileEntity(new BlockPos(x, y, z))); } diff --git a/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java b/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java index 460b6692f..7260e8f1e 100644 --- a/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java +++ b/src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java @@ -32,6 +32,7 @@ import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; @@ -83,8 +84,8 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { private static final String LOG_MARK_AS_COMPLETE = "Completed job for %s."; - private final WorldCoord min; - private final WorldCoord max; + private final BlockPos boundsMin; + private final BlockPos boundsMax; private final int[] usedOps = new int[3]; private final Map tasks = new HashMap<>(); // INSTANCE sate @@ -115,9 +116,9 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { private long startItemCount; private long remainingItemCount; - public CraftingCPUCluster(final WorldCoord min, final WorldCoord max) { - this.min = min; - this.max = max; + public CraftingCPUCluster(final WorldCoord boundsMin, final WorldCoord boundsMax) { + this.boundsMin = boundsMin.getBlockPos(); + this.boundsMax = boundsMax.getBlockPos(); } @Override @@ -129,6 +130,16 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU { return this.myLastLink; } + @Override + public BlockPos getBoundsMin() { + return boundsMin; + } + + @Override + public BlockPos getBoundsMax() { + return boundsMax; + } + /** * add a new Listener to the monitor, be sure to properly remove yourself when * your done. diff --git a/src/main/java/appeng/me/cluster/implementations/QuantumCluster.java b/src/main/java/appeng/me/cluster/implementations/QuantumCluster.java index 5f1528ed4..7de19f5e6 100644 --- a/src/main/java/appeng/me/cluster/implementations/QuantumCluster.java +++ b/src/main/java/appeng/me/cluster/implementations/QuantumCluster.java @@ -21,6 +21,7 @@ package appeng.me.cluster.implementations; import java.util.Iterator; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; @@ -46,8 +47,8 @@ import appeng.util.iterators.ChainedIterator; public class QuantumCluster implements ILocatable, IAECluster { - private final WorldCoord min; - private final WorldCoord max; + private final BlockPos boundsMin; + private final BlockPos boundsMax; private boolean isDestroyed = false; private boolean updateStatus = true; private QuantumBridgeTileEntity[] Ring; @@ -58,8 +59,8 @@ public class QuantumCluster implements ILocatable, IAECluster { private QuantumBridgeTileEntity center; public QuantumCluster(final WorldCoord min, final WorldCoord max) { - this.min = min; - this.max = max; + this.boundsMin = min.getBlockPos(); + this.boundsMax = max.getBlockPos(); this.setRing(new QuantumBridgeTileEntity[8]); } @@ -190,6 +191,16 @@ public class QuantumCluster implements ILocatable, IAECluster { return this.thisSide != 0; } + @Override + public BlockPos getBoundsMin() { + return boundsMin; + } + + @Override + public BlockPos getBoundsMax() { + return boundsMax; + } + @Override public boolean isDestroyed() { return isDestroyed; diff --git a/src/main/java/appeng/me/cluster/implementations/SpatialPylonCalculator.java b/src/main/java/appeng/me/cluster/implementations/SpatialPylonCalculator.java index 3ebef2058..43c3cce90 100644 --- a/src/main/java/appeng/me/cluster/implementations/SpatialPylonCalculator.java +++ b/src/main/java/appeng/me/cluster/implementations/SpatialPylonCalculator.java @@ -22,7 +22,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import appeng.api.util.DimensionalCoord; import appeng.api.util.WorldCoord; import appeng.me.cluster.IAECluster; import appeng.me.cluster.IAEMultiBlock; @@ -47,8 +46,7 @@ public class SpatialPylonCalculator extends MBCalculator { @Override public IAECluster createCluster(final World w, final WorldCoord min, final WorldCoord max) { - return new SpatialPylonCluster(new DimensionalCoord(w, min.x, min.y, min.z), - new DimensionalCoord(w, max.x, max.y, max.z)); + return new SpatialPylonCluster(w, min.getBlockPos(), max.getBlockPos()); } @Override diff --git a/src/main/java/appeng/me/cluster/implementations/SpatialPylonCluster.java b/src/main/java/appeng/me/cluster/implementations/SpatialPylonCluster.java index c4f3611f6..2d3ef3ee4 100644 --- a/src/main/java/appeng/me/cluster/implementations/SpatialPylonCluster.java +++ b/src/main/java/appeng/me/cluster/implementations/SpatialPylonCluster.java @@ -22,31 +22,35 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + import appeng.api.networking.IGridHost; -import appeng.api.util.DimensionalCoord; import appeng.me.cluster.IAECluster; import appeng.me.cluster.MBCalculator; import appeng.tile.spatial.SpatialPylonTileEntity; public class SpatialPylonCluster implements IAECluster { - private final DimensionalCoord min; - private final DimensionalCoord max; + private final World world; + private final BlockPos boundsMin; + private final BlockPos boundsMax; private final List line = new ArrayList<>(); private boolean isDestroyed = false; private Axis currentAxis = Axis.UNFORMED; private boolean isValid; - public SpatialPylonCluster(final DimensionalCoord min, final DimensionalCoord max) { - this.min = min.copy(); - this.max = max.copy(); + public SpatialPylonCluster(final World world, final BlockPos boundsMin, final BlockPos boundsMax) { + this.world = world; + this.boundsMin = boundsMin.toImmutable(); + this.boundsMax = boundsMax.toImmutable(); - if (this.getMin().x != this.getMax().x) { + if (this.getBoundsMin().getX() != this.getBoundsMax().getX()) { this.setCurrentAxis(Axis.X); - } else if (this.getMin().y != this.getMax().y) { + } else if (this.getBoundsMin().getY() != this.getBoundsMax().getY()) { this.setCurrentAxis(Axis.Y); - } else if (this.getMin().z != this.getMax().z) { + } else if (this.getBoundsMin().getZ() != this.getBoundsMax().getZ()) { this.setCurrentAxis(Axis.Z); } else { this.setCurrentAxis(Axis.UNFORMED); @@ -108,12 +112,18 @@ public class SpatialPylonCluster implements IAECluster { this.isValid = isValid; } - public DimensionalCoord getMax() { - return this.max; + public World getWorld() { + return world; } - public DimensionalCoord getMin() { - return this.min; + @Override + public BlockPos getBoundsMax() { + return this.boundsMax; + } + + @Override + public BlockPos getBoundsMin() { + return this.boundsMin; } List getLine() { diff --git a/src/main/java/appeng/tile/crafting/CraftingTileEntity.java b/src/main/java/appeng/tile/crafting/CraftingTileEntity.java index 69f90421c..af79e04f3 100644 --- a/src/main/java/appeng/tile/crafting/CraftingTileEntity.java +++ b/src/main/java/appeng/tile/crafting/CraftingTileEntity.java @@ -121,11 +121,11 @@ public class CraftingTileEntity extends AENetworkTileEntity implements IAEMultiB public void onReady() { super.onReady(); this.getProxy().setVisualRepresentation(this.getItemFromTile(this)); - this.updateMultiBlock(); + this.calc.calculateMultiblock(world, getLocation()); } - public void updateMultiBlock() { - this.calc.calculateMultiblock(this.world, this.getLocation()); + public void updateMultiBlock(BlockPos changedPos) { + this.calc.updateMultiblockAfterNeighborUpdate(this.world, this.getLocation(), changedPos); } public void updateStatus(final CraftingCPUCluster c) { diff --git a/src/main/java/appeng/tile/qnb/QuantumBridgeTileEntity.java b/src/main/java/appeng/tile/qnb/QuantumBridgeTileEntity.java index c79320a59..84d357600 100644 --- a/src/main/java/appeng/tile/qnb/QuantumBridgeTileEntity.java +++ b/src/main/java/appeng/tile/qnb/QuantumBridgeTileEntity.java @@ -32,6 +32,7 @@ import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.data.ModelDataMap; import net.minecraftforge.client.model.data.ModelProperty; @@ -272,8 +273,8 @@ public class QuantumBridgeTileEntity extends AENetworkInvTileEntity implements I return AECableType.DENSE_SMART; } - public void neighborUpdate() { - this.calc.calculateMultiblock(this.world, this.getLocation()); + public void neighborUpdate(BlockPos fromPos) { + this.calc.updateMultiblockAfterNeighborUpdate(this.world, this.getLocation(), fromPos); } @Override diff --git a/src/main/java/appeng/tile/spatial/SpatialPylonTileEntity.java b/src/main/java/appeng/tile/spatial/SpatialPylonTileEntity.java index 5f4441950..8324652f6 100644 --- a/src/main/java/appeng/tile/spatial/SpatialPylonTileEntity.java +++ b/src/main/java/appeng/tile/spatial/SpatialPylonTileEntity.java @@ -26,6 +26,7 @@ import javax.annotation.Nonnull; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.data.ModelDataMap; import net.minecraftforge.client.model.data.ModelProperty; @@ -87,7 +88,7 @@ public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMu @Override public void onReady() { super.onReady(); - this.neighborChanged(); + this.calc.calculateMultiblock(world, getLocation()); } @Override @@ -96,8 +97,8 @@ public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMu super.remove(); } - public void neighborChanged() { - this.calc.calculateMultiblock(this.world, this.getLocation()); + public void neighborChanged(BlockPos changedPos) { + this.calc.updateMultiblockAfterNeighborUpdate(this.world, this.getLocation(), changedPos); } @Override @@ -130,9 +131,9 @@ public class SpatialPylonTileEntity extends AENetworkTileEntity implements IAEMu this.displayBits = 0; if (this.cluster != null) { - if (this.cluster.getMin().equals(this.getLocation())) { + if (this.cluster.getBoundsMin().equals(this.getLocation())) { this.displayBits = DISPLAY_END_MIN; - } else if (this.cluster.getMax().equals(this.getLocation())) { + } else if (this.cluster.getBoundsMax().equals(this.getLocation())) { this.displayBits = DISPLAY_END_MAX; } else { this.displayBits = DISPLAY_MIDDLE;