From 11bb97e66c4d767e8599e07e18779264fd63e254 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Mon, 24 Oct 2022 19:23:46 -0700 Subject: [PATCH] Fix incorrect handling of mustNotSave CB used the dirty flag to construct the chunk unload event, but then sets mustNotSave to the inverted value of the event after calling the event without considering that the chunk may actually be brought up to loaded status again later. Then, CB overrides the isUnsaved method of LevelChunk to additionally use mustNotSave. Thus, if the chunk is not marked dirty when unloading, the mustNotSave value will be set to true. Then, once the chunk is reloaded and edited the dirty flag will be set. However, when unloading the chunk finally, the isUnsaved method will return false due to mustNotSave being true. Thus, the chunk will never be saved. To fix these issues, no longer make mustNotSave override isUnsaved and always set the save flag for the chunk unload event. This issue started popping up recently due to the recent change to mark chunks as not dirty after saving them, which increased the chance of the save issue occurring in the first place. --- patches/server/Rewrite-chunk-system.patch | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/patches/server/Rewrite-chunk-system.patch b/patches/server/Rewrite-chunk-system.patch index 29ca5892114..b75a3145e74 100644 --- a/patches/server/Rewrite-chunk-system.patch +++ b/patches/server/Rewrite-chunk-system.patch @@ -16825,10 +16825,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void unloadCallback() { + if (!this.loadedTicketLevel) { LOGGER.error("Double calling chunk unload!", new Throwable()); } // Paper org.bukkit.Server server = this.level.getCraftServer(); +- org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(this.bukkitChunk, this.isUnsaved()); + this.chunkHolder.getEntityChunk().callEntitiesUnloadEvent(); // Paper - rewrite chunk system - org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(this.bukkitChunk, this.isUnsaved()); ++ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(this.bukkitChunk, true); // Paper - rewrite chunk system - force save to true so that mustNotSave is correctly set below server.getPluginManager().callEvent(unloadEvent); // note: saving can be prevented, but not forced if no saving is actually required + this.mustNotSave = !unloadEvent.isSaveChunk(); +@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess { + + @Override + public boolean isUnsaved() { +- return super.isUnsaved() && !this.mustNotSave; ++ return super.isUnsaved(); // Paper - rewrite chunk system - do NOT clobber the dirty flag + } + // CraftBukkit end + @@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess { }); }