diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java index a6258216a..f72b28a31 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java @@ -257,6 +257,9 @@ public PocketServerComputer createServerComputer( final World world, IInventory public static ServerComputer getServerComputer( @Nonnull ItemStack stack ) { + int session = getSessionID( stack ); + if( session != ComputerCraft.serverComputerRegistry.getSessionID() ) return null; + int instanceID = getInstanceID( stack ); return instanceID >= 0 ? ComputerCraft.serverComputerRegistry.get( instanceID ) : null; } 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 373d0787c..07b3dec26 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -128,6 +128,10 @@ public void update() { // Advance movement updateCommands(); + + // The block may have been broken while the command was executing (for instance, if a block explodes + // when being mined). If so, abort. + if( m_owner.isRemoved() ) return; } // Advance animation diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index e3ddec335..f76e7b377 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -11,6 +11,7 @@ import dan200.computercraft.api.turtle.event.TurtleAttackEvent; import dan200.computercraft.api.turtle.event.TurtleBlockEvent; import dan200.computercraft.shared.TurtlePermissions; +import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; import dan200.computercraft.shared.turtle.core.TurtlePlayer; import dan200.computercraft.shared.util.DropConsumer; @@ -111,11 +112,14 @@ protected float getDamageMultiplier() return 3.0f; } - private TurtleCommandResult attack( final ITurtleAccess turtle, Direction direction, TurtleSide side ) + private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side ) { // Create a fake player, and orient it appropriately - final World world = turtle.getWorld(); - final BlockPos position = turtle.getPosition(); + World world = turtle.getWorld(); + BlockPos position = turtle.getPosition(); + TileEntity turtleTile = turtle instanceof TurtleBrain ? ((TurtleBrain) turtle).getOwner() : world.getTileEntity( position ); + if( turtleTile == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." ); + final TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, position, direction ); // See if there is an entity present @@ -143,7 +147,7 @@ private TurtleCommandResult attack( final ITurtleAccess turtle, Direction direct } // Start claiming entity drops - DropConsumer.set( hitEntity, turtleDropConsumer( turtle ) ); + DropConsumer.set( hitEntity, turtleDropConsumer( turtleTile, turtle ) ); // Attack the entity boolean attacked = false; @@ -175,7 +179,7 @@ private TurtleCommandResult attack( final ITurtleAccess turtle, Direction direct } // Stop claiming drops - stopConsuming( turtle ); + stopConsuming( turtleTile, turtle ); // Put everything we collected into the turtles inventory, then return if( attacked ) @@ -193,8 +197,10 @@ private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction, Turt // Get ready to dig World world = turtle.getWorld(); BlockPos turtlePosition = turtle.getPosition(); - BlockPos blockPosition = turtlePosition.offset( direction ); + TileEntity turtleTile = turtle instanceof TurtleBrain ? ((TurtleBrain) turtle).getOwner() : world.getTileEntity( turtlePosition ); + if( turtleTile == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." ); + BlockPos blockPosition = turtlePosition.offset( direction ); if( world.isAirBlock( blockPosition ) || WorldUtil.isLiquidBlock( world, blockPosition ) ) { return TurtleCommandResult.failure( "Nothing to dig here" ); @@ -234,7 +240,7 @@ private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction, Turt } // Consume the items the block drops - DropConsumer.set( world, blockPosition, turtleDropConsumer( turtle ) ); + DropConsumer.set( world, blockPosition, turtleDropConsumer( turtleTile, turtle ) ); TileEntity tile = world.getTileEntity( blockPosition ); @@ -253,23 +259,24 @@ private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction, Turt state.getBlock().harvestBlock( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getHeldItemMainhand() ); } - stopConsuming( turtle ); + stopConsuming( turtleTile, turtle ); return TurtleCommandResult.success(); } - private static Function turtleDropConsumer( ITurtleAccess turtle ) + private static Function turtleDropConsumer( TileEntity tile, ITurtleAccess turtle ) { - return drop -> InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ); + return drop -> tile.isRemoved() ? drop : InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ); } - private static void stopConsuming( ITurtleAccess turtle ) + private static void stopConsuming( TileEntity tile, ITurtleAccess turtle ) { + Direction direction = tile.isRemoved() ? null : turtle.getDirection().getOpposite(); List extra = DropConsumer.clear(); for( ItemStack remainder : extra ) { - WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), turtle.getDirection().getOpposite() ); + WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), direction ); } } }