Crash with elevator blocks when playing on a server
5t0rmr1d3r opened this issue · 12 comments
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
@josephcsible Seems related to your latest screen changes?
@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
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.
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. |
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
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/:?]
Here's the simplest way I've found to reproduce the problem, and the simplest possible stack trace:
- Connect to a dedicated server
- Place an elevator block
- Place stone against the front and back of it
- 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:?]
So here's what's going on to cause this bug:
- The client is allowed to call the Block.getStrongPower method. Among other times, this happens when placing a vanilla fence gate.
- The elevator's implementation of Block.getStrongPower calls ElevatorBlock.getRedstoneOutput.
- ElevatorBlock.getRedstoneOutput indirectly calls ElevatorTileEntity.isValidPlatformBlock.
- ElevatorTileEntity.isValidPlatformBlock uses a FakePlayer in its validity checks.
- Constructing a FakePlayer requires a WorldServer, which we try to retrieve via DimensionManager.getWorld(0).
- 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.