Paper icon indicating copy to clipboard operation
Paper copied to clipboard

Settings worlds to not auto-save still makes them save

Open MagmaGuy opened this issue 1 year ago • 1 comments

Expected behavior

Worlds should not auto-save after doing world#setAutoSave(false);

Observed/Actual behavior

Worlds auto-save (very visible on timings)

Paper timings: https://timings.aikar.co/dev/?id=22031926125f4a879eeffb5636e58c76#timings Spigot timings for the exact same server/setup: https://timings.spigotmc.org/?url=uqiqowular

I am not 100% sure about how the Spigot timings work, whether they would show individual world saving per world or would group them up, but if it is individual this would indicate that my problem is specific to Paper.

Steps/models to reproduce

I am using this class to initialize my temporary worlds

public class WorldLoader {
    /**
     * Generates a world which does not save, does not keep spawn loaded and is a void world
     *
     * @param worldName
     * @param environment
     * @return
     */
    public static World loadVoidTemporaryWorld(String worldName, World.Environment environment) {
        //Case where the world is already loaded
        if (Bukkit.getWorld(worldName) != null) return Bukkit.getWorld(worldName);
        File folder = new File(Bukkit.getWorldContainer().getAbsolutePath());
        if (!Files.exists(Paths.get(folder.getAbsolutePath() + File.separatorChar + worldName))) {
            Logger.warn("File  " + folder.getAbsolutePath() + File.separatorChar + worldName + " does not exist!");
            return null;
        }
        Logger.info("Loading world " + worldName + " !");

        Filter filter = newFilter -> false;
        Filter previousFilter = Bukkit.getLogger().getFilter();
        Bukkit.getLogger().setFilter(filter);

        try {
            WorldCreator worldCreator = new WorldCreator(worldName);
            worldCreator.environment(environment);
            worldCreator.keepSpawnInMemory(false);
            worldCreator.generator(new VoidGenerator());
            World world = Bukkit.createWorld(worldCreator);
            if (world != null) world.setKeepSpawnInMemory(false);
            world.setDifficulty(Difficulty.HARD);
            world.setAutoSave(false);
            Bukkit.getLogger().setFilter(previousFilter);
            return world;
        } catch (Exception exception) {
            Bukkit.getLogger().setFilter(previousFilter);
            Logger.warn("Failed to load world " + worldName + " !");
            exception.printStackTrace();
        }
        return null;
    }

    private static class VoidGenerator extends ChunkGenerator {

        @Override
        public void generateSurface(WorldInfo info, Random random, int x, int z, ChunkData data) {}

        @Override
        public boolean shouldGenerateNoise() {
            return false;
        }

        @Override
        public boolean shouldGenerateBedrock() {
            return false;
        }

        @Override
        public boolean shouldGenerateCaves() {
            return false;
        }
    }
}

As you can see, pretty simple. You can use it on any non-default world to load it from the worlds folder. I have verified that the loggers messages do, in fact, run, so this is indeed how the world is being loaded, and no other plugin on my server can/would load these. Plus, the void world generator code is working perfectly fine, a big indicator that this is otherwise functional.

Plugin and Datapack List

Essentials, FreeMinecraftModels, ProtocolLib, packetevents, LibsDisguises, EliteMobs, ResourcePackManager

Paper version

Version | 1.21-97-e71c1df (MC: 1.21) (as you can see in the timings report)

Other

electroniccat told me to report it.

MagmaGuy avatar Aug 17 '24 22:08 MagmaGuy

Let me know if there's anything I can do to speed this ticket up short of submitting a fix, this has been a persistent issue for people using my plugins.

MagmaGuy avatar Sep 10 '24 01:09 MagmaGuy

I've had this issue before, and forgot to report it. Looking thru the code, I think I see the issue, In MinecraftServer#stopServer:

Image

It appears CraftWorld uses the vanilla logic for no-auto-saving. Minecraft appears to just overrides and forcefully decides to save against your wishes when the server stops. I'm assuming Mojang did this on purpose, using the no-save option to just stop auto-saving every 5 minutes, but still continuing to save when the server stops.

I guess in a sense the World.setAutoSave is kinda of correct, as it's not AUTO saving (every 5 min), but maybe another method should be added to prevent saving altogether.

ShaneBeee avatar Feb 05 '25 05:02 ShaneBeee

autosaving is not full saving, the entire point of that mechanism is to disable the periodic saving in order to allow an external program to backup the world, it prevents various things like chunks from being able to unload, and doesn't even prevent everything from saving.

The big issue with this sorta thing is that the entire data system is leaky as there was never any real considerations of mojang to having separate levels being as separate as CB and people like to think they are, but, also, there's the entire headaches over what disabling saving should and should not affect (and the fact that this is an entire set of discussions and work for such a niche usecase in which we don't have any form of mechanism for assuring that these kind of things would keep working to the degree that people would expect for read-only worlds, etc, etc)

electronicboy avatar Feb 05 '25 05:02 electronicboy

Yeah that makes sense. As I read the code I understand its just to prevent the 5 min auto save. The docs for this should maybe be detailed a smidge more explaining that?!?! I for one definitely had the wrong impression when reading it, until now.

ShaneBeee avatar Feb 05 '25 05:02 ShaneBeee

Since this is a very common misconception I'd suggest changing the JD to clarify this behavior

NonSwag avatar Feb 05 '25 09:02 NonSwag