Skip to content

Conversation

@Dueris
Copy link

@Dueris Dueris commented Dec 25, 2025

While POI update scheduling works fine on Folia, it has a major flaw with how it works. In the region threading base patch, Folia replaces the method call BlockableEventLoop#execute with RegionizedTaskQueue#queueChunkTask. While this works fine in general gameplay, it does cause all POI updates to be scheduled to the next tick, which technically breaks vanilla behavior and also breaks a few things(videos and images bellow).

The BlockableEventLoop#execute method is as such:

    public void execute(Runnable task) {
        R runnable = this.wrapRunnable(task);
        if (this.scheduleExecutables()) {
            this.schedule(runnable);
        } else {
            this.doRunTask(runnable);
        }
    }

Essentially, it checks if it is the "main thread" or not(which no longer exists in Folia, but for this case we will assume the "main thread" is the region owning the BlockPos we are updating at), and if it is the "main thread", it will run the task immediately, otherwise, it will schedule for the next tick.

Folia breaks this logic, as it always schedules for the next tick. While in normal gameplay, this is fine, but in some occurrences this does cause issues, like bellow:
image

2025-10-15_15-44-28.1.mp4

The image and video were linked to me in DMs, and I did followup testing in a local Folia instance. This is replicatable by creating a nether portal, either in the overworld or nether, with no exit portal currently generated. Then, if you spam entities through the portal, it will spam create portals on the other end, due to the POI update being scheduled for the next tick. While this probably is unlikely to happen in survival or something, other issues may be present that haven't been caught yet, and it is probably best to restore the Vanilla functionality of POI updating.

The fix I propose in this PR just swaps scheduling for the next tick with the Consumer bellow:

   final java.util.function.Consumer<Runnable> poiProcessor = (task) -> {
       if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, pos.getX() >> 4, pos.getZ() >> 4)) {
           task.run();
       } else io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueChunkTask(this, blockPos.getX() >> 4, blockPos.getZ() >> 4, task);
   };

The consumer provided above fixes the functionality difference between Folia and Vanilla, while also fixing the issue shown above with the nether exit portal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant