Behavior Fixes
This page is a rough overview of what Canvas does to fix certain behavior mechanics in Vanilla, which can cause minor gameplay bugs and issues during runtime.
Vanilla Ender Pearl Behavior
Section titled “Vanilla Ender Pearl Behavior”Vanilla ender pearl behavior is defined as when a player leaves, the in-flight pearls in the server that the player owns will be unloaded along with the player and saved to their player data. On join, the player loads the in-flight pearls back in. Folia removes this functionality entirely, since the system is technically not region-threading safe. There was a previous attempt by Canvas to fix this, however it was deemed unsafe. Currently, Canvas contains a new rewritten system for storing these in-flight pearls.
The new system makes it so that ONLY on leave it will save the pearls to a server-wide concurrent map of UUID -> Pearls. This is then saved to pearls.dat in
the root folder of the server. When the player leaves, all pearls are added to the map on their owning region before being discarded for UNLOADED_WITH_PLAYER.
On the global tick, the server will attempt to write to disk for autosave(same time interval as maps for autosave), with the save-all command, and on
shutdown it will write to disk. This is all done through the utility IO pool. On join, each pearl is decoded, and then using Canvas utilities, spawns
the pearl in on join, and then clears the current list in the save data associated with the player UUID, since we just spawned all of them, none of them need
to be in the save data anymore.
This makes this significantly more region threading safe, given everything is now scheduled properly, and saved properly, on the correct context, in a more efficient and safe manner.
"": { Data: { // player UUID a4804847-858e-3278-941e-ab3175b15a81: [ { world: "minecraft:overworld" data: { // Pearl entity data } uuid: b679858f-af33-48ea-9323-509219dc6189 }, { world: "minecraft:overworld" data: { // Pearl entity data } uuid: de1c429f-3f7c-4d02-8c9c-495ff94c0367 }, ] }}End Credits
Section titled “End Credits”The end credits were disabled by Folia due to Folias rewrite of respawning logic. Folias respawning logic contains the method:
private void respawn(java.util.function.Consumer<ServerPlayer> respawnComplete, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason reason, boolean alive)This method contains all logic for respawning a player with region threading. Canvas essentially splits this method into the method and the “finalizer”.
The finalizer is a Runnable that adds the player back to the world. Vanilla, when showing the end credits, removes the player from the world and
waits on the packet ServerboundClientCommandPacket with the action, PERFORM_RESPAWN. If the player is in the end credits when this packet
is received, the player has told the server they have exited the credits and is awaiting to be added back to the world. We split this method into its
finalizer so we can replicate this process. We store the Runnable in the new field canvas$exitEndCreditsCallback in ServerPlayer, and is called
when we receive this packet. When the player enters the end portal, we check if they have already seen the credits, and if they have we immediately
run respawn and ignore storing the finalizer and just run it. If they haven’t, we store the finalizer after removing the player from the world and
then send a ClientboundGameEventPacket with the game event WIN_GAME, to tell the client to display the end credits.
When the packet is received, we redirect the packet to the global region thread, because if we queue this packet as a task like normal, this packet will not be run because the player isn’t owned by any region, and as a result isn’t being ticked. Once the finalizer is run, the player is scheduled to respawn back at their respawn location.
Minor Issues
Section titled “Minor Issues”- Fixes Folia#421
- Fixes max player count being offset by -1 in Folia
- Fixes a few technical Vanilla mechanics