FamroFexl / Circumnavigate

Finite, Tiled, Seamless World Wrapping Mod for Minecraft.
https://modrinth.com/project/circumnavigate
GNU Affero General Public License v3.0
18 stars 1 forks source link

[Bug]: Piston updates aren't sent to wrapped players. #10

Closed FamroFexl closed 16 hours ago

FamroFexl commented 1 week ago

Describe the Bug

Pistons on one side of the wrapping border aren't updated for players on the other side of the wrapping border unless another player is present in the piston's chunk.

Mod version(s) affected

1.0.2

Mod loader(s) used

Fabric

Minecraft version(s) used

1.20.4

Other mods used

No response

To Reproduce (If applicable)

Place a piston on one side of the world with a lever connected to it. Go to the other side of the world and activate it several times. You will see the piston stops responding to lever clicks client-side. Now have another player join and stand in the chunk where the piston is. If you activate the lever a few more times, you will see it is now updated properly client-side.

Additional Information

I believe this might be an issue caused by chunk loading levels not being properly updated for past-bounds chunks. However, as of yet I have been unable to track down what code needs to be changed in ChunkTracker and its sub-classes specifically.

FamroFexl commented 1 week ago

Files in @Skidamek's world-fold attempt might actually be the solution to this.

Specifically this

Skidamek commented 1 week ago

Hey yeah that might be releated... Are chunks on the opposite side of the border getting ticked if there are no other players?

FamroFexl commented 1 week ago

@Skidamek They are getting certain loading ticks in order to actually be loaded from disk or generated, but they are obviously missing another type of block ticking.

This is strange because my ticking modifications changed the parent class of chunk ticking operations (ChunkTracker) and should have affected all their sub-classes as well.

Skidamek commented 5 days ago

I would guess it's because these chunks aren't in simulation distance I mean they are loaded but ticks aren't simulated

Minecraft has view distance and simulation distance separated from each other.

I noticed this bug also when flying around with fishing rod and pulling entities from and into the border they often get stuck or lag for a moment and when you as a player also cross that border they move along.

I inspected the Chunk tracker mixin and it seems like it loads those chunks but further down the chain call there is priority queue which somehow priorities chunks to simulate, likely based on which are the closest to the player (it uses chunkpos in long) I guess due to these chunks being on the other side of the world they don't.

So I tried simulation distance slider in video settings to max 32 chunks and it seemed to just work.

Skidamek commented 5 days ago

Okay apparently this issue has very strange consequences https://youtu.be/cU-Cdxc42_Q Take a look that in the 0:22 or 1:24 i dont even cross border

Skidamek commented 5 days ago

Files in @Skidamek's world-fold attempt might actually be the solution to this.

Specifically this

tried that, it does not fix it.

FamroFexl commented 4 days ago

Apparently, there are Chunk Loading Levels, and there are Tickets. While the Chunk Loading Levels are being wrapped in ChunkTracker and SectionTracker the Tickets aren't being wrapped in DistanceManager The lack of a ticket might be causing the server to remove the entity from being tracked by the players.

Here is a partial stacktrace when an entity is untracked by the player due to the issue described in your video: (line numbers will differ but method names should be the same) java.base/java.lang.Thread.getStackTrace(Thread.java:2417) net.minecraft.server.level.ServerEntity.handler$zkd000$circumnavigate$removePairing(ServerEntity.java:1069) net.minecraft.server.level.ServerEntity.removePairing(ServerEntity.java) net.minecraft.server.level.ChunkMap$TrackedEntity.broadcastRemoved(ChunkMap.java:1356) net.minecraft.server.level.ChunkMap.removeEntity(ChunkMap.java:1196) net.minecraft.server.level.ServerChunkCache.removeEntity(ServerChunkCache.java:477) net.minecraft.server.level.ServerLevel$EntityCallbacks.onTrackingEnd(ServerLevel.java:1608) net.minecraft.server.level.ServerLevel$EntityCallbacks.onTrackingEnd(ServerLevel.java:1563) net.minecraft.world.level.entity.PersistentEntitySectionManager.stopTracking(PersistentEntitySectionManager.java:220) net.minecraft.world.level.entity.PersistentEntitySectionManager.method_31825(PersistentEntitySectionManager.java:254) net.minecraft.world.level.entity.PersistentEntitySectionManager.updateChunkStatus(PersistentEntitySectionManager.java:240) net.minecraft.world.level.entity.PersistentEntitySectionManager.updateChunkStatus(PersistentEntitySectionManager.java:226) net.minecraft.server.level.ChunkMap.onFullChunkStatusChange(ChunkMap.java:1274) net.minecraft.server.level.ChunkHolder.demoteFullChunk(ChunkHolder.java:410) net.minecraft.server.level.ChunkHolder.updateFutures(ChunkHolder.java:485 net.minecraft.server.level.DistanceManager.method_15891(DistanceManager.java:127) java.base/java.lang.Iterable.forEach(Iterable.java:75) net.minecraft.server.level.DistanceManager.runAllUpdates(DistanceManager.java:127) net.minecraft.server.level.ServerChunkCache.runDistanceManagerUpdates(ServerChunkCache.java:284) net.minecraft.server.level.ServerChunkCache.tick(ServerChunkCache.java:321) net.minecraft.server.level.ServerLevel.tick(ServerLevel.java:341) net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:948) net.minecraft.server.dedicated.DedicatedServer.tickChildren(DedicatedServer.java:283) net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:845) net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:683) net.minecraft.server.MinecraftServer.method_29739(MinecraftServer.java:270) java.base/java.lang.Thread.run(Thread.java:1570)

FamroFexl commented 4 days ago

I cannot find this bug. I've spent hours trying to track it down, but the closest thing I could come up with is cancelling the removePlayer method in the DistanceManager, which isn't a workable solution. This problem is linked to the loading level of the chunk, as I was able to print out the loading levels and view them. Somehow, the updates to the DistanceManagers playerTicketManager and tickingTicketsTracker handle the downstream effects of lowering the chunk's loading level.

Skidamek commented 2 days ago

So from what i understand is that chunks aren't just loaded around the player. When player moves DistanceManager.addPlayer and DistanceManager.removePlayer are called they add/remove chunk ticket for the new/old chunk player just entered/left and then crazy amount of abstracted recurrncy comes in ChunkTracker which basically loads 3x3 region of chunks around players chunk. Amount of abstractions makes it hard to understand, idk if it will be helpful for you but that's what I got.