ComputerCraft

ComputerCraft

21M Downloads

Exception in computer peripheral provider

SquidDev opened this issue ยท 0 comments

commented

Placing two computers next to each other and removing one causes an exception in the peripheral provider. Whilst this is caught, and so isn't a game breaking bug, it would be worth fixing at some point.

Steps to reproduce/diagnostics

  • Place two computers next to each other. We'll call these A and B.
  • Break computer B.
  • Breaking the block causes the neighbouring tiles to be updated, and so look for peripherals.
  • However, as the tile entity is not removed until after this call, the peripheral provider still finds the tile and creates a new computer, which triggers all sorts of code which assumes the blocks are still there.

Solution

There are a couple of potential solutions here:

  • Remove the tile entity before calling TileGeneric.destroy. There are a couple of other bits which might need changing because of this though.
  • Add some sanity checks within .createServerComputer and friends to ensure the current block state is valid.
  • Prevent the peripheral provider creating the computer, instead creating a proxy object which uses .getServerComputer(), falling back to the original tile's data if the computer hasn't been created yet. This should also fix some of the issues mentioned in #409. It should also prevent this fabulous stack overflow, caused by a 16x16x16 cube of computers.

I'd really appreciate people's thoughts on these. The last one is my preferred one, but it would be the most complicated to implement, so I'm not sure its worth it.

Stack trace

java.lang.IllegalArgumentException: Cannot get property PropertyDirection{name=facing, clazz=class net.minecraft.util.EnumFacing, values=[north, south, west, east]} as it does not exist in BlockStateContainer{block=minecraft:air, properties=[]}
	at net.minecraft.block.state.BlockStateContainer$StateImplementation.getValue(BlockStateContainer.java:196) ~[BlockStateContainer$StateImplementation.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputer.getDirection(TileComputer.java:90) ~[TileComputer.class:?]
	at dan200.computercraft.shared.util.DirectionUtil.toLocal(DirectionUtil.java:54) ~[DirectionUtil.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.updateSideInput(TileComputerBase.java:323) ~[TileComputerBase.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.updateInput(TileComputerBase.java:349) ~[TileComputerBase.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.createServerComputer(TileComputerBase.java:50) ~[TileComputerBase.class:?]
	at dan200.computercraft.shared.peripheral.common.DefaultPeripheralProvider.getPeripheral(DefaultPeripheralProvider.java:53) ~[DefaultPeripheralProvider.class:?]
	at dan200.computercraft.ComputerCraft.getPeripheralAt(ComputerCraft.java:659) [ComputerCraft.class:?]
	at dan200.computercraft.shared.util.PeripheralUtil.getPeripheral(PeripheralUtil.java:16) [PeripheralUtil.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.updateSideInput(TileComputerBase.java:331) [TileComputerBase.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.updateInput(TileComputerBase.java:349) [TileComputerBase.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.onNeighbourChange(TileComputerBase.java:199) [TileComputerBase.class:?]
	at dan200.computercraft.shared.common.BlockGeneric.neighborChanged(BlockGeneric.java:162) [BlockGeneric.class:?]
	at net.minecraft.block.state.BlockStateContainer$StateImplementation.neighborChanged(BlockStateContainer.java:483) [BlockStateContainer$StateImplementation.class:?]
	at net.minecraft.world.World.notifyBlockOfStateChange(World.java:584) [World.class:?]
	at dan200.computercraft.shared.util.RedstoneUtil.propogateRedstoneOutput(RedstoneUtil.java:79) [RedstoneUtil.class:?]
	at dan200.computercraft.shared.computer.blocks.TileComputerBase.destroy(TileComputerBase.java:79) [TileComputerBase.class:?]
	at dan200.computercraft.shared.common.BlockGeneric.breakBlock(BlockGeneric.java:117) [BlockGeneric.class:?]
	at net.minecraft.world.chunk.Chunk.setBlockState(Chunk.java:610) [Chunk.class:?]
	at net.minecraft.world.World.setBlockState(World.java:384) [World.class:?]
	at net.minecraft.block.Block.removedByPlayer(Block.java:1320) [Block.class:?]
	at dan200.computercraft.shared.common.BlockGeneric.removedByPlayer(BlockGeneric.java:81) [BlockGeneric.class:?]