diff --git a/helpers/DualityInterface.java b/helpers/DualityInterface.java index bb300d235..e3a1f6985 100644 --- a/helpers/DualityInterface.java +++ b/helpers/DualityInterface.java @@ -517,9 +517,7 @@ public class DualityInterface implements IGridTickable, ISegmentedInventory, ISt { TileEntity te = iHost.getTileEntity(); if ( te != null && te.getWorldObj() != null ) - { - te.getWorldObj().notifyBlocksOfNeighborChange( te.xCoord, te.yCoord, te.zCoord, Platform.air ); - } + Platform.notifyBlocksOfNeighbors( te.getWorldObj(), te.xCoord, te.yCoord, te.zCoord ); } } diff --git a/hooks/TickHandler.java b/hooks/TickHandler.java index 8d3bdfc49..fe96bff3b 100644 --- a/hooks/TickHandler.java +++ b/hooks/TickHandler.java @@ -3,8 +3,10 @@ package appeng.hooks; import java.util.Collection; import java.util.LinkedList; import java.util.Queue; +import java.util.WeakHashMap; import java.util.concurrent.Callable; +import net.minecraft.world.World; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; import appeng.api.networking.IGridNode; @@ -17,6 +19,7 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.gameevent.TickEvent.Phase; import cpw.mods.fml.common.gameevent.TickEvent.Type; +import cpw.mods.fml.common.gameevent.TickEvent.WorldTickEvent; public class TickHandler { @@ -38,7 +41,8 @@ public class TickHandler final public static TickHandler instance = new TickHandler(); - final private Queue callQueue = new LinkedList(); + final private WeakHashMap> callQueue = new WeakHashMap>(); + Queue serverQueue = new LinkedList(); final private HandlerRep server = new HandlerRep(); final private HandlerRep client = new HandlerRep(); @@ -50,9 +54,19 @@ public class TickHandler return client; } - public void addCallable(Callable c) + public void addCallable(World w, Callable c) { - callQueue.add( c ); + if ( w == null ) + serverQueue.add( c ); + else + { + Queue queue = callQueue.get( w ); + + if ( queue == null ) + callQueue.put( w, queue = new LinkedList() ); + + queue.add( c ); + } } public void addInit(AEBaseTile tile) @@ -122,6 +136,7 @@ public class TickHandler if ( ev.type == Type.SERVER && ev.phase == Phase.END ) // for no there is no reason to care about this on the // client... { + // ready tiles. HandlerRep repo = getRepo(); while (!repo.tiles.isEmpty()) { @@ -129,24 +144,37 @@ public class TickHandler bt.onReady(); } + // tick networks. for (Grid g : getRepo().networks) - { g.update(); - } - Callable c = null; - while ((c = callQueue.poll()) != null) - { - try - { - c.call(); - } - catch (Exception e) - { - AELog.error( e ); - } - } + // cross world queue. + processQueue( serverQueue ); + } + + // world synced queue(s) + if ( ev.type == Type.WORLD && ev.phase == Phase.START ) + { + processQueue( callQueue.get( ((WorldTickEvent) ev).world ) ); } } + private void processQueue(Queue queue) + { + if ( queue == null ) + return; + + Callable c = null; + while ((c = queue.poll()) != null) + { + try + { + c.call(); + } + catch (Exception e) + { + AELog.error( e ); + } + } + } } diff --git a/me/GridNode.java b/me/GridNode.java index c33008a7d..918d4968c 100644 --- a/me/GridNode.java +++ b/me/GridNode.java @@ -286,7 +286,7 @@ public class GridNode implements IGridNode, IPathItem } catch (FailedConnection e) { - TickHandler.instance.addCallable( new Callable() { + TickHandler.instance.addCallable( node.getWorld(), new Callable() { @Override public Object call() throws Exception @@ -321,7 +321,7 @@ public class GridNode implements IGridNode, IPathItem } catch (FailedConnection e) { - TickHandler.instance.addCallable( new Callable() { + TickHandler.instance.addCallable( node.getWorld(), new Callable() { @Override public Object call() throws Exception diff --git a/parts/PartPlacement.java b/parts/PartPlacement.java index aea4aa167..4f2761d6f 100644 --- a/parts/PartPlacement.java +++ b/parts/PartPlacement.java @@ -136,7 +136,7 @@ public class PartPlacement { is.add( sp.facade.getItemStack() ); host.getFacadeContainer().removeFacade( host, sp.side ); - world.notifyBlocksOfNeighborChange( x, y, z, Platform.air ); + Platform.notifyBlocksOfNeighbors( world, x, y, z ); } if ( host.isEmpty() ) diff --git a/parts/automation/PartAnnihilationPlane.java b/parts/automation/PartAnnihilationPlane.java index 386153454..a2add866b 100644 --- a/parts/automation/PartAnnihilationPlane.java +++ b/parts/automation/PartAnnihilationPlane.java @@ -312,7 +312,7 @@ public class PartAnnihilationPlane extends PartBasicState implements IGridTickab else { breaking = true; - TickHandler.instance.addCallable( this ); + TickHandler.instance.addCallable( this.tile.getWorldObj(), this ); return TickRateModulation.URGENT; } } diff --git a/parts/automation/PartLevelEmitter.java b/parts/automation/PartLevelEmitter.java index bfba6970e..1f744e6c0 100644 --- a/parts/automation/PartLevelEmitter.java +++ b/parts/automation/PartLevelEmitter.java @@ -106,8 +106,8 @@ public class PartLevelEmitter extends PartUpgradeable implements IEnergyWatcherH host.markForUpdate(); TileEntity te = host.getTile(); prevState = isLevelEmitterOn(); - te.getWorldObj().notifyBlocksOfNeighborChange( te.xCoord, te.yCoord, te.zCoord, Platform.air ); - te.getWorldObj().notifyBlocksOfNeighborChange( te.xCoord + side.offsetX, te.yCoord + side.offsetY, te.zCoord + side.offsetZ, Platform.air ); + Platform.notifyBlocksOfNeighbors( te.getWorldObj(), te.xCoord, te.yCoord, te.zCoord ); + Platform.notifyBlocksOfNeighbors( te.getWorldObj(), te.xCoord + side.offsetX, te.yCoord + side.offsetY, te.zCoord + side.offsetZ ); } } diff --git a/parts/p2p/PartP2PRedstone.java b/parts/p2p/PartP2PRedstone.java index 12d32227f..417daefcb 100644 --- a/parts/p2p/PartP2PRedstone.java +++ b/parts/p2p/PartP2PRedstone.java @@ -13,6 +13,7 @@ import appeng.api.networking.events.MENetworkChannelsChanged; import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.me.GridAccessException; +import appeng.util.Platform; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -111,15 +112,15 @@ public class PartP2PRedstone extends PartP2PTunnel int yCoord = tile.yCoord; int zCoord = tile.zCoord; - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord, worldObj.getBlock( xCoord, yCoord, zCoord ) ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord, zCoord ); // and this cause somtimes it can go thought walls. - worldObj.notifyBlocksOfNeighborChange( xCoord - 1, yCoord, zCoord, worldObj.getBlock( xCoord, yCoord, zCoord ) ); - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord - 1, zCoord, worldObj.getBlock( xCoord, yCoord, zCoord ) ); - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord - 1, worldObj.getBlock( xCoord, yCoord, zCoord ) ); - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord + 1, worldObj.getBlock( xCoord, yCoord, zCoord ) ); - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord + 1, zCoord, worldObj.getBlock( xCoord, yCoord, zCoord ) ); - worldObj.notifyBlocksOfNeighborChange( xCoord + 1, yCoord, zCoord, worldObj.getBlock( xCoord, yCoord, zCoord ) ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord - 1, yCoord, zCoord ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord - 1, zCoord ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord, zCoord - 1 ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord, zCoord + 1 ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord + 1, zCoord ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord + 1, yCoord, zCoord ); } @Override diff --git a/parts/p2p/PartP2PTunnel.java b/parts/p2p/PartP2PTunnel.java index bf61d8cc8..ba3c93697 100644 --- a/parts/p2p/PartP2PTunnel.java +++ b/parts/p2p/PartP2PTunnel.java @@ -178,7 +178,7 @@ public class PartP2PTunnel extends PartBasicState } } - tile.getWorldObj().notifyBlocksOfNeighborChange( tile.xCoord, tile.yCoord, tile.zCoord, Platform.air ); + Platform.notifyBlocksOfNeighbors( tile.getWorldObj(), tile.xCoord, tile.yCoord, tile.zCoord ); return true; } } diff --git a/parts/p2p/PartP2PTunnelME.java b/parts/p2p/PartP2PTunnelME.java index b1a4d5d4e..13de17ebb 100644 --- a/parts/p2p/PartP2PTunnelME.java +++ b/parts/p2p/PartP2PTunnelME.java @@ -125,19 +125,19 @@ public class PartP2PTunnelME extends PartP2PTunnel implements I if ( !proxy.getEnergy().isNetworkPowered() ) { connection.markDestroy(); - TickHandler.instance.addCallable( connection ); + TickHandler.instance.addCallable( tile.getWorldObj(), connection ); } else { if ( proxy.isActive() ) { connection.markCreate(); - TickHandler.instance.addCallable( connection ); + TickHandler.instance.addCallable( tile.getWorldObj(), connection ); } else { connection.markDestroy(); - TickHandler.instance.addCallable( connection ); + TickHandler.instance.addCallable( tile.getWorldObj(), connection ); } } diff --git a/tile/AEBaseTile.java b/tile/AEBaseTile.java index 88d5a30c6..acf82e0bb 100644 --- a/tile/AEBaseTile.java +++ b/tile/AEBaseTile.java @@ -259,7 +259,7 @@ public class AEBaseTile extends TileEntity implements IOrientable, ICommonTile, forward = inForward; up = inUp; markForUpdate(); - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord, Platform.air ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord, zCoord ); } public void onPlacement(ItemStack stack, EntityPlayer player, int side) diff --git a/tile/networking/TileCableBus.java b/tile/networking/TileCableBus.java index 56c1e1e7c..f65c4056c 100644 --- a/tile/networking/TileCableBus.java +++ b/tile/networking/TileCableBus.java @@ -290,7 +290,7 @@ public class TileCableBus extends AEBaseTile implements AEMultiTile, ICustomColl public void notifyNeighbors() { if ( worldObj != null && worldObj.blockExists( xCoord, yCoord, zCoord ) && !CableBusContainer.isLoading() ) - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord, Platform.air ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord, zCoord ); } @Override diff --git a/tile/spatial/TileSpatialIOPort.java b/tile/spatial/TileSpatialIOPort.java index 81c9ba7a8..841830e83 100644 --- a/tile/spatial/TileSpatialIOPort.java +++ b/tile/spatial/TileSpatialIOPort.java @@ -54,7 +54,7 @@ public class TileSpatialIOPort extends AENetworkInvTile implements Callable ItemStack cell = getStackInSlot( 0 ); if ( isSpatialCell( cell ) ) { - TickHandler.instance.addCallable( this ); + TickHandler.instance.addCallable( null, this );// this needs to be cross world sycned. } } } diff --git a/tile/storage/TileChest.java b/tile/storage/TileChest.java index d24394a6d..cd159ff79 100644 --- a/tile/storage/TileChest.java +++ b/tile/storage/TileChest.java @@ -437,7 +437,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHan // update the neighbors if ( worldObj != null ) { - worldObj.notifyBlocksOfNeighborChange( xCoord, yCoord, zCoord, Platform.air ); + Platform.notifyBlocksOfNeighbors( worldObj, xCoord, yCoord, zCoord ); markForUpdate(); } } diff --git a/util/BlockUpdate.java b/util/BlockUpdate.java new file mode 100644 index 000000000..d54b2d4ba --- /dev/null +++ b/util/BlockUpdate.java @@ -0,0 +1,27 @@ +package appeng.util; + +import java.util.concurrent.Callable; + +import net.minecraft.world.World; + +public class BlockUpdate implements Callable +{ + + final World w; + final int x, y, z; + + public BlockUpdate(World w, int x, int y, int z) { + this.w = w; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Object call() throws Exception + { + w.notifyBlocksOfNeighborChange( x, y, z, Platform.air ); + return true; + } + +} diff --git a/util/Platform.java b/util/Platform.java index cebb74f6f..cf8f0fc58 100644 --- a/util/Platform.java +++ b/util/Platform.java @@ -84,6 +84,7 @@ import appeng.core.AEConfig; import appeng.core.AELog; import appeng.core.AppEng; import appeng.core.sync.GuiBridge; +import appeng.hooks.TickHandler; import appeng.me.GridAccessException; import appeng.me.GridNode; import appeng.me.helpers.AENetworkProxy; @@ -1638,4 +1639,10 @@ public class Platform return null; } + public static void notifyBlocksOfNeighbors(World worldObj, int xCoord, int yCoord, int zCoord) + { + if ( !worldObj.isRemote ) + TickHandler.instance.addCallable( worldObj, new BlockUpdate( worldObj, xCoord, yCoord, zCoord ) ); + } + }