Closed supersimple33 closed 5 months ago
I'm having some trouble tracking this one down but it seems that in the setRemoved
override of WireBlockEntitys
sometime between calling the super where it set the entity isRemoved()=true
and getting new entities via this.world.getBlockEntity(pos)
in the WireNetworkImpl the entities are forgetting that they are removed.
I spent some time digging into this and believe that I found the root cause.
I was able to reproduce the issue with as few as 2 wires. The same issue is also present in the pipe network code. The issue does not occur if no wires or pipes are placed before the world is closed, even if wires/pipes are present in the loaded world. I was unable to reproduce the issue during chunk unloading by moving far away, it only seems to occur when chunks are unloaded to be saved on world close.
On world shutdown the following occurs:
setRemoved
on all contained block entitiesWireBlockEntity
calls into its network to remove itselfWireNetworkImpl
removes the wire. Networks of size 1 terminate hereWireBlockEntities
are created at the same positions in the newly loaded chunk objectWireNetworkImpl
determines new network groups from adjacent wires but is now getting the new entities and not the originalWireNetworkImpl
objects are created for each new wire grouping. The newly created wires get networks assigned to themWireBlockEntity
objects do not get the new parent, so they call into the original (now removed) WireNetworkImpl
and trigger the errorAdding a check along the lines of if (adjacentWire.getNetwork() == null) continue
to the network removal code prevents the new wire entities from getting networks created/assigned and prevents the infinite loop from occuring.
From what I can tell, when the world is loaded and there are wires it does not create wire networks. This seems like a bug in and of itself, although it's possible that machines/power sources lazily create the networks as needed (I didn't look at this). When the wires in the world do not have networks they do not call into networks to be removed, which preempts the above process.
My best guess for this not causing the issue is that the cleanup order of the chunk and its contained objects differs in this scenario as opposed to world exit. I tried my best to dig through the decompiled stacktraces as chunks were unloaded, but have been unable to confirm this theory. That said, if it isn't broken don't fix it.
I am not sure if this is possible, and it honestly seems like it would cause more problems than solutions, but if chunks are not loaded when queried by the network, then we would not get the infinite loop. We would only want to utilize this method when recomputing the network after block removal, in all other use cases we need to load chunks in order to be fully correct.
Wire
references in WireNetworkImpl
and query from local stateEssentially the first solution, but instead of finding some way to query Level
without creating chunks we change WireNetworkImpl.wires
from List<BlockPos
to Map<BlockPos, Wire>
and query that when remapping networks due to removed wires. WireNetworkImpl.addWire
would also need to be updated to only use the local state when removing wires, and still use the Level.getBlockEntity
otherwise.
If we go this route it would be nice to implement the above functionality in a generic base class that can be used by all types of networks, as this issue effects both power and fluids, and eventually any other network types as well.
This is my first contribution and first time actually working on a mod, so I may have overlooked a more correct solution. Any suggestions are welcome.
Mod Loader
Fabric
Version Information
ac33404a
Reconfirmed in 13285bb
Log or Crash Report
[TIME][Server thread/WARN] (Galacticraft) Tried to remove wire from removed network!
Reproduction steps
When using certain wire configurations (typically just a bunch of wires like sometimes a 5x5 square of wires will cause the loop but not every time) the game can end up in an infinite loop where it repeats the error message
Tried to remove wire from removed network!
in the console forever.