RFTools

RFTools

74M Downloads

Crash with elevator blocks when playing on a server

5t0rmr1d3r opened this issue · 12 comments

commented

client crashes when looking into the direktion of a near screen with a elevator botton module.
heres the crashlog
crash-2018-01-28_18.58.48-client.txt

commented

@josephcsible Seems related to your latest screen changes?

commented

@McJty It doesn't, actually. My best guess is that DimensionManager.getWorld(0) is returning null for some reason, which is then blowing up when EntityPlayer's constructor does !worldIn.isRemote.

@5t0rmr1d3r Can you try using this build of RFTools, and post the crash log that it gives you? https://github.com/josephcsible/RFTools/releases/download/7.26%2Boverworldnull/rftools-1.12-7.26.jar

commented
commented

Yes, tomorrow is fine.

commented

Actually, I see what's going on. You don't need to run that build after all. My guess is exactly what happened. The client thread is calling a chain of functions that ends up calling one that's only supposed to get called on the server.

commented
commented

So here's the important part of the stack trace, with links and MCP names for clarity:

Frame Notes
mcjty.rftools.blocks.builder.BuilderTileEntity.getHarvester(BuilderTileEntity.java:179) DimensionManager.getWorld returns a WorldServer, so it's clearly meant to be called only on the server side.
mcjty.rftools.blocks.elevator.ElevatorTileEntity.isValidPlatformBlock(ElevatorTileEntity.java:362)
mcjty.rftools.blocks.elevator.ElevatorTileEntity.isPlatformHere(ElevatorTileEntity.java:601)
mcjty.rftools.blocks.elevator.ElevatorBlock.getRedstoneOutput(ElevatorBlock.java:61)
mcjty.lib.container.GenericBlock.getStrongPower(GenericBlock.java:107)
net.minecraft.block.state.BlockStateContainer$StateImplementation.getStrongPower(BlockStateContainer.java:417)
net.minecraft.world.World.getStrongPower(World.java:3181) This is for our elevator block, south of the solid block in question
net.minecraft.world.World.getStrongPower(World.java:3216) This was for the solid block in question, but not one of ours
net.minecraft.world.World.getRedstonePower(World.java:3249) This is interesting. Given that the above frame is getStrongPower, it's implied that shouldCheckWeakPower returned true.
net.minecraft.world.World.isBlockIndirectlyGettingPowered(World.java:3286)
mcjty.lib.container.GenericBlock.checkRedstone(GenericBlock.java:438)
mcjty.lib.container.GenericBlock.checkRedstoneIfNecessary(GenericBlock.java:446)
mcjty.lib.entity.GenericTileEntity.onLoad(GenericTileEntity.java:81) I added this call to fix newly-placed blocks not recognizing pre-existing redstone. It looks like it may be what's at fault.
net.minecraft.world.World.addTileEntity(World.java:1918)
net.minecraft.world.World.setTileEntity(World.java:2442)
net.minecraft.world.chunk.Chunk.getTileEntity(Chunk.java:799)
net.minecraft.world.World.getTileEntity(World.java:2383)
mcjty.rftools.blocks.screens.modulesclient.ElevatorButtonClientScreenModule.getLevelText(ElevatorButtonClientScreenModule.java:148) Obviously, this is meant to be client-side code.
commented

Okay, confirmed it's not screen-related. Here's the stack trace of it without a screen involved at all:

[15:34:16] [main/FATAL]: Error executing task
java.util.concurrent.ExecutionException: java.lang.NullPointerException: overworld
	at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[?:1.8.0_151]
	at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[?:1.8.0_151]
	at net.minecraft.util.Util.runTask(Util.java:54) [Util.class:?]
	at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1176) [Minecraft.class:?]
	at net.minecraft.client.Minecraft.run(Minecraft.java:441) [Minecraft.class:?]
	at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_151]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_151]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_151]
	at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_151]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_151]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_151]
	at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?]
	at GradleStart.main(GradleStart.java:26) [start/:?]
Caused by: java.lang.NullPointerException: overworld
	at mcjty.rftools.blocks.builder.BuilderTileEntity.getHarvester(BuilderTileEntity.java:182) ~[BuilderTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorTileEntity.isValidPlatformBlock(ElevatorTileEntity.java:362) ~[ElevatorTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorTileEntity.isPlatformHere(ElevatorTileEntity.java:601) ~[ElevatorTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorBlock.getRedstoneOutput(ElevatorBlock.java:79) ~[ElevatorBlock.class:?]
	at mcjty.lib.container.GenericBlock.getStrongPower(GenericBlock.java:107) ~[GenericBlock.class:?]
	at net.minecraft.block.state.BlockStateContainer$StateImplementation.getStrongPower(BlockStateContainer.java:425) ~[BlockStateContainer$StateImplementation.class:?]
	at net.minecraft.world.World.getStrongPower(World.java:3453) ~[World.class:?]
	at net.minecraft.world.World.getStrongPower(World.java:3491) ~[World.class:?]
	at net.minecraft.world.World.getRedstonePower(World.java:3524) ~[World.class:?]
	at net.minecraft.world.World.isBlockIndirectlyGettingPowered(World.java:3565) ~[World.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorBlock.checkRedstone(ElevatorBlock.java:54) ~[ElevatorBlock.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorBlock.checkRedstoneIfNecessary(ElevatorBlock.java:63) ~[ElevatorBlock.class:?]
	at mcjty.lib.entity.GenericTileEntity.onLoad(GenericTileEntity.java:81) ~[GenericTileEntity.class:?]
	at net.minecraft.world.World.addTileEntity(World.java:2090) ~[World.class:?]
	at net.minecraft.world.World.setTileEntity(World.java:2656) ~[World.class:?]
	at net.minecraft.world.chunk.Chunk.getTileEntity(Chunk.java:856) ~[Chunk.class:?]
	at net.minecraft.world.World.getTileEntity(World.java:2597) ~[World.class:?]
	at net.minecraft.client.network.NetHandlerPlayClient.handleChunkData(NetHandlerPlayClient.java:832) ~[NetHandlerPlayClient.class:?]
	at net.minecraft.network.play.server.SPacketChunkData.processPacket(SPacketChunkData.java:110) ~[SPacketChunkData.class:?]
	at net.minecraft.network.play.server.SPacketChunkData.processPacket(SPacketChunkData.java:20) ~[SPacketChunkData.class:?]
	at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:21) ~[PacketThreadUtil$1.class:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_151]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_151]
	at net.minecraft.util.Util.runTask(Util.java:53) ~[Util.class:?]
	... 15 more
commented

Here's a useful one: looking at an elevator with Waila will crash in the right circumstances:

java.lang.NullPointerException: overworld
	at mcjty.rftools.blocks.builder.BuilderTileEntity.getHarvester(BuilderTileEntity.java:182) ~[BuilderTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorTileEntity.isValidPlatformBlock(ElevatorTileEntity.java:362) ~[ElevatorTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorTileEntity.isPlatformHere(ElevatorTileEntity.java:601) ~[ElevatorTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorBlock.getRedstoneOutput(ElevatorBlock.java:79) ~[ElevatorBlock.class:?]
	at mcjty.lib.container.GenericBlock.getStrongPower(GenericBlock.java:107) ~[GenericBlock.class:?]
	at net.minecraft.block.state.BlockStateContainer$StateImplementation.getStrongPower(BlockStateContainer.java:425) ~[BlockStateContainer$StateImplementation.class:?]
	at net.minecraft.world.World.getStrongPower(World.java:3453) ~[World.class:?]
	at net.minecraft.world.World.getStrongPower(World.java:3491) ~[World.class:?]
	at net.minecraft.world.World.getRedstonePower(World.java:3524) ~[World.class:?]
	at net.minecraft.world.World.isBlockIndirectlyGettingPowered(World.java:3565) ~[World.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorBlock.checkRedstone(ElevatorBlock.java:54) ~[ElevatorBlock.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorBlock.checkRedstoneIfNecessary(ElevatorBlock.java:63) ~[ElevatorBlock.class:?]
	at mcjty.lib.entity.GenericTileEntity.onLoad(GenericTileEntity.java:81) ~[GenericTileEntity.class:?]
	at net.minecraft.world.World.addTileEntity(World.java:2090) ~[World.class:?]
	at net.minecraft.world.World.setTileEntity(World.java:2656) ~[World.class:?]
	at net.minecraft.world.chunk.Chunk.getTileEntity(Chunk.java:856) ~[Chunk.class:?]
	at net.minecraft.world.World.getTileEntity(World.java:2597) ~[World.class:?]
	at mcp.mobius.waila.api.impl.DataAccessorCommon.set(DataAccessorCommon.java:58) ~[DataAccessorCommon.class:?]
	at mcp.mobius.waila.api.impl.DataAccessorCommon.set(DataAccessorCommon.java:45) ~[DataAccessorCommon.class:?]
	at mcp.mobius.waila.overlay.WailaTickHandler.tickClient(WailaTickHandler.java:77) ~[WailaTickHandler.class:?]
	at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_9_WailaTickHandler_tickClient_ClientTickEvent.invoke(.dynamic) ~[?:?]
	at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?]
	at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:179) ~[EventBus.class:?]
	at net.minecraftforge.fml.common.FMLCommonHandler.onPreClientTick(FMLCommonHandler.java:342) ~[FMLCommonHandler.class:?]
	at net.minecraft.client.Minecraft.runTick(Minecraft.java:1833) ~[Minecraft.class:?]
	at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1186) ~[Minecraft.class:?]
	at net.minecraft.client.Minecraft.run(Minecraft.java:441) [Minecraft.class:?]
	at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_151]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_151]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_151]
	at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_151]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_151]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_151]
	at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?]
	at GradleStart.main(GradleStart.java:26) [start/:?]
commented

Here's the simplest way I've found to reproduce the problem, and the simplest possible stack trace:

  1. Connect to a dedicated server
  2. Place an elevator block
  3. Place stone against the front and back of it
  4. Place a fence gate against the back of the stone on the back

Here's the important piece of that stack trace:

	at mcjty.rftools.blocks.builder.BuilderTileEntity.getHarvester(BuilderTileEntity.java:182) ~[BuilderTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorTileEntity.isValidPlatformBlock(ElevatorTileEntity.java:362) ~[ElevatorTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorTileEntity.isPlatformHere(ElevatorTileEntity.java:601) ~[ElevatorTileEntity.class:?]
	at mcjty.rftools.blocks.elevator.ElevatorBlock.getRedstoneOutput(ElevatorBlock.java:79) ~[ElevatorBlock.class:?]
	at mcjty.lib.container.GenericBlock.getStrongPower(GenericBlock.java:107) ~[GenericBlock.class:?]
	at net.minecraft.block.state.BlockStateContainer$StateImplementation.getStrongPower(BlockStateContainer.java:425) ~[BlockStateContainer$StateImplementation.class:?]
	at net.minecraft.world.World.getStrongPower(World.java:3453) ~[World.class:?]
	at net.minecraft.world.World.getStrongPower(World.java:3483) ~[World.class:?]
	at net.minecraft.world.World.getRedstonePower(World.java:3524) ~[World.class:?]
	at net.minecraft.world.World.isBlockPowered(World.java:3537) ~[World.class:?]
	at net.minecraft.block.BlockFenceGate.getStateForPlacement(BlockFenceGate.java:140) ~[BlockFenceGate.class:?]
	at net.minecraft.block.Block.getStateForPlacement(Block.java:2454) ~[Block.class:?]
	at net.minecraft.item.ItemBlock.onItemUse(ItemBlock.java:55) ~[ItemBlock.class:?]
	at net.minecraft.item.ItemStack.onItemUse(ItemStack.java:201) ~[ItemStack.class:?]
	at net.minecraft.client.multiplayer.PlayerControllerMP.processRightClickBlock(PlayerControllerMP.java:499) ~[PlayerControllerMP.class:?]
commented

So here's what's going on to cause this bug:

  1. The client is allowed to call the Block.getStrongPower method. Among other times, this happens when placing a vanilla fence gate.
  2. The elevator's implementation of Block.getStrongPower calls ElevatorBlock.getRedstoneOutput.
  3. ElevatorBlock.getRedstoneOutput indirectly calls ElevatorTileEntity.isValidPlatformBlock.
  4. ElevatorTileEntity.isValidPlatformBlock uses a FakePlayer in its validity checks.
  5. Constructing a FakePlayer requires a WorldServer, which we try to retrieve via DimensionManager.getWorld(0).
  6. Calling DimensionManager.getWorld(0) on the client returns null, and trying to create a FakePlayer with a null WorldServer causes the NPE we're seeing.

To fix it, we need to either redo ElevatorTileEntity.isValidPlatformBlock to not require a FakePlayer, or redo ElevatorBlock.getRedstoneOutput to not call ElevatorTileEntity.isValidPlatformBlock.

commented

Looking at the implementation of isValidPlatformBlock, it's what's at fault here. Fix coming up.