diff --git a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java index 0df9032ca..560c40dea 100644 --- a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java @@ -46,7 +46,7 @@ public abstract class BlockGeneric extends Block implements public final void dropBlockAsItemWithChance( World world, BlockPos pos, IBlockState state, float chance, int fortune ) { } - + @Override public final List getDrops( IBlockAccess world, BlockPos pos, IBlockState state, int fortune ) { @@ -107,7 +107,7 @@ public abstract class BlockGeneric extends Block implements { Block.spawnAsEntity( world, pos, stack ); } - + @Override public final void breakBlock( World world, BlockPos pos, IBlockState newState ) { @@ -162,6 +162,17 @@ public abstract class BlockGeneric extends Block implements } } + @Override + public final void onNeighborChange( IBlockAccess world, BlockPos pos, BlockPos neighbour ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile instanceof TileGeneric ) + { + TileGeneric generic = (TileGeneric)tile; + generic.onNeighbourTileEntityChange( neighbour ); + } + } + @Override public final boolean isSideSolid( IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side ) { diff --git a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java index 2e86ec148..a8709b73a 100644 --- a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java @@ -95,6 +95,10 @@ public abstract class TileGeneric extends TileEntity { } + public void onNeighbourTileEntityChange( BlockPos neighbour ) + { + } + public boolean isSolidOnSide( int side ) { return true; diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java index d75959d3d..baeec3720 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java @@ -197,6 +197,12 @@ public abstract class TileComputerBase extends TileGeneric updateInput(); } + @Override + public void onNeighbourTileEntityChange( BlockPos neighbour ) + { + updateInput( neighbour ); + } + @Override public void update() { @@ -308,6 +314,21 @@ public abstract class TileComputerBase extends TileGeneric return localSide; } + private void updateSideInput( ServerComputer computer, EnumFacing dir, BlockPos offset ) + { + EnumFacing offsetSide = dir.getOpposite(); + int localDir = remapLocalSide( DirectionUtil.toLocal( this, dir ) ); + if( !isRedstoneBlockedOnSide( localDir ) ) + { + computer.setRedstoneInput( localDir, RedstoneUtil.getRedstoneOutput( worldObj, offset, offsetSide ) ); + computer.setBundledRedstoneInput( localDir, RedstoneUtil.getBundledRedstoneOutput( worldObj, offset, offsetSide ) ); + } + if( !isPeripheralBlockedOnSide( localDir ) ) + { + computer.setPeripheral( localDir, PeripheralUtil.getPeripheral( worldObj, offset, offsetSide ) ); + } + } + public void updateInput() { if( worldObj == null || worldObj.isRemote ) @@ -316,6 +337,24 @@ public abstract class TileComputerBase extends TileGeneric } // Update redstone and peripherals + ServerComputer computer = getServerComputer(); + if( computer != null ) + { + BlockPos pos = computer.getPosition(); + for( EnumFacing dir : EnumFacing.VALUES ) + { + updateSideInput( computer, dir, pos.offset( dir ) ); + } + } + } + + public void updateInput( BlockPos neighbour ) + { + if( worldObj == null || worldObj.isRemote ) + { + return; + } + ServerComputer computer = getServerComputer(); if( computer != null ) { @@ -323,16 +362,10 @@ public abstract class TileComputerBase extends TileGeneric for( EnumFacing dir : EnumFacing.VALUES ) { BlockPos offset = pos.offset( dir ); - EnumFacing offsetSide = dir.getOpposite(); - int localDir = remapLocalSide( DirectionUtil.toLocal( this, dir ) ); - if( !isRedstoneBlockedOnSide( localDir ) ) + if ( offset.equals( neighbour ) ) { - computer.setRedstoneInput( localDir, RedstoneUtil.getRedstoneOutput( worldObj, offset, offsetSide ) ); - computer.setBundledRedstoneInput( localDir, RedstoneUtil.getBundledRedstoneOutput( worldObj, offset, offsetSide ) ); - } - if( !isPeripheralBlockedOnSide( localDir ) ) - { - computer.setPeripheral( localDir, PeripheralUtil.getPeripheral( worldObj, offset, offsetSide ) ); + updateSideInput( computer, dir, offset ); + break; } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index 31f42e4e9..67acc879a 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -46,12 +46,19 @@ public class TileTurtle extends TileComputerBase public static final int INVENTORY_HEIGHT = 4; // Members - + + enum MoveState + { + NOT_MOVED, + IN_PROGRESS, + MOVED + } + private ItemStack[] m_inventory; private ItemStack[] m_previousInventory; private boolean m_inventoryChanged; private TurtleBrain m_brain; - private boolean m_moved; + private MoveState m_moveState; public TileTurtle() { @@ -59,12 +66,12 @@ public class TileTurtle extends TileComputerBase m_previousInventory = new ItemStack[ getSizeInventory() ]; m_inventoryChanged = false; m_brain = createBrain(); - m_moved = false; + m_moveState = MoveState.NOT_MOVED; } public boolean hasMoved() { - return m_moved; + return m_moveState == MoveState.MOVED; } protected TurtleBrain createBrain() @@ -276,6 +283,41 @@ public class TileTurtle extends TileComputerBase } } + @Override + public void onNeighbourChange() + { + if ( m_moveState == MoveState.NOT_MOVED ) + { + super.onNeighbourChange(); + } + } + + @Override + public void onNeighbourTileEntityChange(BlockPos neighbour) + { + if ( m_moveState == MoveState.NOT_MOVED ) + { + super.onNeighbourTileEntityChange( neighbour ); + } + } + + public void notifyMoveStart() + { + if (m_moveState == MoveState.NOT_MOVED) + { + m_moveState = MoveState.IN_PROGRESS; + } + } + + public void notifyMoveEnd() + { + // MoveState.MOVED is final + if (m_moveState == MoveState.IN_PROGRESS) + { + m_moveState = MoveState.NOT_MOVED; + } + } + @Override public void readFromNBT( NBTTagCompound nbttagcompound ) { @@ -401,7 +443,7 @@ public class TileTurtle extends TileComputerBase } // IInventory - + @Override public int getSizeInventory() { @@ -431,7 +473,7 @@ public class TileTurtle extends TileComputerBase return result; } } - + @Override public ItemStack decrStackSize( int slot, int count ) { @@ -447,13 +489,13 @@ public class TileTurtle extends TileComputerBase { return null; } - + if( stack.stackSize <= count ) { setInventorySlotContents( slot, null ); return stack; } - + ItemStack part = stack.splitStack( count ); onInventoryDefinitelyChanged(); return part; @@ -496,7 +538,7 @@ public class TileTurtle extends TileComputerBase } } } - + @Override public String getName() { @@ -550,7 +592,7 @@ public class TileTurtle extends TileComputerBase public void openInventory( EntityPlayer player ) { } - + @Override public void closeInventory( EntityPlayer player ) { @@ -561,7 +603,7 @@ public class TileTurtle extends TileComputerBase { return true; } - + @Override public void markDirty() { @@ -664,6 +706,6 @@ public class TileTurtle extends TileComputerBase m_inventoryChanged = copy.m_inventoryChanged; m_brain = copy.m_brain; m_brain.setOwner( this ); - copy.m_moved = true; + copy.m_moveState = MoveState.MOVED; } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index 1c440d06f..737f96868 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -495,6 +495,7 @@ public class TurtleBrain implements ITurtleAccess // Cache info about the old turtle (so we don't access this after we delete ourselves) World oldWorld = getWorld(); + TileTurtle oldOwner = m_owner; BlockPos oldPos = m_owner.getPos(); Block oldBlock = m_owner.getBlock(); @@ -504,36 +505,51 @@ public class TurtleBrain implements ITurtleAccess return true; } - // Create a new turtle - if( world.isBlockLoaded( pos ) && world.setBlockState( pos, oldBlock.getDefaultState(), 0 ) ) + if ( !world.isBlockLoaded( pos ) ) { - Block block = world.getBlockState( pos ).getBlock(); - if( block == oldBlock ) + return false; + } + + oldOwner.notifyMoveStart(); + + try + { + // Create a new turtle + if( world.setBlockState( pos, oldBlock.getDefaultState(), 0 ) ) { - TileEntity newTile = world.getTileEntity( pos ); - if( newTile != null && newTile instanceof TileTurtle ) + Block block = world.getBlockState( pos ).getBlock(); + if( block == oldBlock ) { - // Copy the old turtle state into the new turtle - TileTurtle newTurtle = (TileTurtle)newTile; - newTurtle.setWorldObj( world ); - newTurtle.setPos( pos ); - newTurtle.transferStateFrom( m_owner ); - newTurtle.createServerComputer().setWorld( world ); - newTurtle.createServerComputer().setPosition( pos ); + TileEntity newTile = world.getTileEntity( pos ); + if( newTile != null && newTile instanceof TileTurtle ) + { + // Copy the old turtle state into the new turtle + TileTurtle newTurtle = (TileTurtle)newTile; + newTurtle.setWorldObj( world ); + newTurtle.setPos( pos ); + newTurtle.transferStateFrom( oldOwner ); + newTurtle.createServerComputer().setWorld( world ); + newTurtle.createServerComputer().setPosition( pos ); - // Remove the old turtle - oldWorld.setBlockToAir( oldPos ); + // Remove the old turtle + oldWorld.setBlockToAir( oldPos ); - // Make sure everybody knows about it - newTurtle.updateBlock(); - newTurtle.updateInput(); - newTurtle.updateOutput(); - return true; + // Make sure everybody knows about it + newTurtle.updateBlock(); + newTurtle.updateInput(); + newTurtle.updateOutput(); + return true; + } } - } - // Something went wrong, remove the newly created turtle - world.setBlockToAir( pos ); + // Something went wrong, remove the newly created turtle + world.setBlockToAir( pos ); + } + } + finally + { + // whatever happens, unblock old turtle in case it's still in world + oldOwner.notifyMoveEnd(); } return false;