Try to handle a turtle being broken while ticked

Hopefully fixes #585. Hopefully.
This commit is contained in:
SquidDev 2020-11-28 13:13:35 +00:00
parent e2761bb315
commit 24af36743d
3 changed files with 26 additions and 12 deletions

View File

@ -257,6 +257,9 @@ public PocketServerComputer createServerComputer( final World world, IInventory
public static ServerComputer getServerComputer( @Nonnull ItemStack stack ) public static ServerComputer getServerComputer( @Nonnull ItemStack stack )
{ {
int session = getSessionID( stack );
if( session != ComputerCraft.serverComputerRegistry.getSessionID() ) return null;
int instanceID = getInstanceID( stack ); int instanceID = getInstanceID( stack );
return instanceID >= 0 ? ComputerCraft.serverComputerRegistry.get( instanceID ) : null; return instanceID >= 0 ? ComputerCraft.serverComputerRegistry.get( instanceID ) : null;
} }

View File

@ -128,6 +128,10 @@ public void update()
{ {
// Advance movement // Advance movement
updateCommands(); 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 // Advance animation

View File

@ -11,6 +11,7 @@
import dan200.computercraft.api.turtle.event.TurtleAttackEvent; import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent; import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import dan200.computercraft.shared.TurtlePermissions; 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.TurtlePlaceCommand;
import dan200.computercraft.shared.turtle.core.TurtlePlayer; import dan200.computercraft.shared.turtle.core.TurtlePlayer;
import dan200.computercraft.shared.util.DropConsumer; import dan200.computercraft.shared.util.DropConsumer;
@ -111,11 +112,14 @@ protected float getDamageMultiplier()
return 3.0f; 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 // Create a fake player, and orient it appropriately
final World world = turtle.getWorld(); World world = turtle.getWorld();
final BlockPos position = turtle.getPosition(); 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 ); final TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, position, direction );
// See if there is an entity present // See if there is an entity present
@ -143,7 +147,7 @@ private TurtleCommandResult attack( final ITurtleAccess turtle, Direction direct
} }
// Start claiming entity drops // Start claiming entity drops
DropConsumer.set( hitEntity, turtleDropConsumer( turtle ) ); DropConsumer.set( hitEntity, turtleDropConsumer( turtleTile, turtle ) );
// Attack the entity // Attack the entity
boolean attacked = false; boolean attacked = false;
@ -175,7 +179,7 @@ private TurtleCommandResult attack( final ITurtleAccess turtle, Direction direct
} }
// Stop claiming drops // Stop claiming drops
stopConsuming( turtle ); stopConsuming( turtleTile, turtle );
// Put everything we collected into the turtles inventory, then return // Put everything we collected into the turtles inventory, then return
if( attacked ) if( attacked )
@ -193,8 +197,10 @@ private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction, Turt
// Get ready to dig // Get ready to dig
World world = turtle.getWorld(); World world = turtle.getWorld();
BlockPos turtlePosition = turtle.getPosition(); 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 ) ) if( world.isAirBlock( blockPosition ) || WorldUtil.isLiquidBlock( world, blockPosition ) )
{ {
return TurtleCommandResult.failure( "Nothing to dig here" ); 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 // Consume the items the block drops
DropConsumer.set( world, blockPosition, turtleDropConsumer( turtle ) ); DropConsumer.set( world, blockPosition, turtleDropConsumer( turtleTile, turtle ) );
TileEntity tile = world.getTileEntity( blockPosition ); 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() ); state.getBlock().harvestBlock( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getHeldItemMainhand() );
} }
stopConsuming( turtle ); stopConsuming( turtleTile, turtle );
return TurtleCommandResult.success(); return TurtleCommandResult.success();
} }
private static Function<ItemStack, ItemStack> turtleDropConsumer( ITurtleAccess turtle ) private static Function<ItemStack, ItemStack> 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<ItemStack> extra = DropConsumer.clear(); List<ItemStack> extra = DropConsumer.clear();
for( ItemStack remainder : extra ) for( ItemStack remainder : extra )
{ {
WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), turtle.getDirection().getOpposite() ); WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), direction );
} }
} }
} }