Fabricators-of-Create / Create

[Fabric Mod] Building Tools and Aesthetic Technology
MIT License
834 stars 188 forks source link

Cannot read field "entity" because "c" is null #548

Closed DaanSchar closed 1 year ago

DaanSchar commented 1 year ago

Describe the Bug

On a server, whenever someone loads a certain area of the world (probably where the problem entity is located), every single person's game crashes, resulting from the Exception being thrown.

Reproduction Steps

  1. Log into server
  2. Load in world
  3. crash

We are not quite sure how to replicate this error, as it has happened multiple times now unexpectidly.

Expected Result

Game should not throw exception and crash for every single player online.

Screenshots and Videos

image

Crash Report or Log

https://pastebin.com/mGy1w3Mu

Operating System

Windows 11

Mod Version

0.5.0d

Minecraft Version

1.18.2

Other Mods

https://pastebin.com/zBbV0EaM

Additional Context

The issue seems to be able to be resolved by killing all entities when the player close enough to the problematic entity loads into the world.

This crash also occured on patch 0.5.0c

TropheusJ commented 1 year ago

Can’t reproduce, please test patch G.

Zivodor commented 1 year ago

@TropheusJ I can confirm the bug is still happening on patches 0.5.0g-791 and 0.5.0g-796. The steps for replication for how I encountered the error are as follows:

  1. Create a 32x32 platform of drills pointing downwards
  2. Glue the drills together
  3. Add two 3x3x9-sized vaults to the top of the drill platform
  4. Glue the vaults and the drill platform together
  5. Add a rope pulley on top of the drill platform in the corner of the platform
  6. Add any block to the side of the rope pulley such that it hangs over the edge of the drill platform
  7. Glue the rope pulley to the block
  8. Place a rail under the overhang block
  9. Place a cart assembler under the overhang block on the rail
  10. Place a cart on the rail
  11. Power the assembler

Expected Result: The contraption is created successfully

Actual Result: The game hard crashes to the desktop with the error message 'Cannot read field "entity" because "c" is null'

Zivodor commented 1 year ago

As a follow-up, I looked into the code surrounding this area and please correct me if I am wrong, but I think this might be a race condition with the renderer and the assembly of the offending contraption. Consider the following:

The code that is erroring out is this line in the ContraptionRenderingWorld.java file:

ContraptionHandler.loadedContraptions.get(world)
                .values()
                .stream()
                .map(Reference::get)
                .filter(Objects::nonNull)
                .map(AbstractContraptionEntity::getContraption)
                .forEach(this::getRenderInfo);

when we call getRenderInfo() it performs this action which results in a null reference exception:

int entityId = c.entity.getId();

Specifically, We can conclude that the entity is getting initialized and added to the world because if it was null then the filter(Objects::nonNull) code would filter it out, but the contraption is not or has not been yet assigned. The major difference for why this doesn't happen every time for every contraption, as far as I can tell, is the size of the contraption being assembled. Tracking back to the CartAssemblerTileEntity.java and the assemble() method we see the contraption gets created on line 128

MountedContraption contraption = new MountedContraption(mode);

Then on line 130 it gets assembled.

if (!contraption.assemble(world, pos))
    return;

Finally, after it is assembled, some more actions are performed finally, on line 161 the entity is created.

OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation);

When the OrientedContraptionEntity.create() call is executed, the entity.setContraption() method is called almost immediately and inside that the onEntityCreated() call is executed if the contraption is not null, which we know it is initialized and therefore not null, and if the level is not clientside, which I cannot confirm.

If we assume that the level is not client side, then the onEntityCreated() method is called and the contraption should be successfully assigned to the entity and there should be no null reference exception, but this is not what is happening.

The gap in my knowledge right now, is that I am unsure how the entity gets registered within the world. If it works how I suspect, being that as soon as an entity is created it is registered in the world, it would mean that if the render tick is happening too fast then its possible to get an entity with no related contraption because it is still being constructed/assigned.

I am not a Minecraft mod developer, nor a java developer, but I have spent the last 10 years debugging code and fixing difficult bugs including race conditions and this has all the tell tale signs of a race condition.

As a fix, I suggest someone who is set up to debug and test this simply adds a filter before the forEach loop that filters out entities with null contraptions as they have not yet been initialized and therefore are not ready to render.

Again though, I am not a Minecraft mod developer, and my experience solely comes from my time as a software developer and I made a whole bunch of assumption here. Feel free to correct me, I just really want to build my giant-ass world eater without my world crashing and forcing me to go into the NBT data to delete the offending entity so I thought I would lend an external view to the problem as it seems this has been going on for a while.

TropheusJ commented 1 year ago

This has been a weird recurring issue that seems to be persistent for some people, but I've never been able to reproduce it. A race condition is probably the cause at this point. I haven't seen any instances of it on forge, but that makes no sense. I've been reluctant to add an extra check because I wanted to find the root cause, but if it's a race condition there's really not much to fix. Should be 1 line for the next release.

Zivodor commented 1 year ago

@TropheusJ I can also replicate it on Forge. I switched to Fabric, hoping it wouldn't continue, but I was wrong.

TropheusJ commented 1 year ago

In that case, it should be fixed on forge and then pulled into fabric. If you can get it to happen on forge again, report it there.

Zivodor commented 1 year ago

@TropheusJ I can do that, I will copy my response over to the relevant open issue,

TropheusJ commented 1 year ago

I had this occur on a server and I think I've tracked down the cause. If you install XL Packets is it fixed?

Zivodor commented 1 year ago

@TropheusJ you absolute GENIUS. Yes that fixed it. What is the source of the bug? Is it not a race condition? Also installing that packets mod greatly increased the performance of my world so thanks for that was well.

TropheusJ commented 1 year ago

Is there an issue on the Forge repo about this?

TropheusJ commented 1 year ago

PR is still waiting but a fix for the crash has been added