diff --git a/src/main/java/org/mvplugins/multiverse/core/world/WorldsConfigManager.java b/src/main/java/org/mvplugins/multiverse/core/world/WorldsConfigManager.java index b54796bad..5d25dcea3 100644 --- a/src/main/java/org/mvplugins/multiverse/core/world/WorldsConfigManager.java +++ b/src/main/java/org/mvplugins/multiverse/core/world/WorldsConfigManager.java @@ -121,7 +121,11 @@ private void migrateRemoveOldConfigSerializable() { * @return A tuple containing a list of the new WorldConfigs added and a list of the worlds removed from the config. */ private NewAndRemovedWorlds parseNewAndRemovedWorlds() { - Set allWorldsInConfig = worldsConfig.getKeys(false); + List allWorldsInConfig = worldsConfig.getKeys(false) + .stream() + .map(this::decodeWorldName) + .toList(); + List newWorldsAdded = new ArrayList<>(); for (String worldName : allWorldsInConfig) { @@ -174,7 +178,7 @@ public Try save() { worldConfig.save().onFailure(e -> { throw new RuntimeException("Failed to save world config: " + worldName, e); }); - worldsConfig.set(worldName, worldConfig.getConfigurationSection()); + worldsConfig.set(encodeWorldName(worldName), worldConfig.getConfigurationSection()); }); worldsConfig.save(worldConfigFile); }).onFailure(e -> { @@ -214,7 +218,7 @@ public Try save() { */ public void deleteWorldConfig(@NotNull String worldName) { worldConfigMap.remove(worldName); - worldsConfig.set(worldName, null); + worldsConfig.set(encodeWorldName(worldName), null); } /** @@ -225,11 +229,23 @@ public void deleteWorldConfig(@NotNull String worldName) { * @return The {@link ConfigurationSection} for the given world. */ private ConfigurationSection getWorldConfigSection(String worldName) { + worldName = encodeWorldName(worldName); return worldsConfig.isConfigurationSection(worldName) ? worldsConfig.getConfigurationSection(worldName) : worldsConfig.createSection(worldName); } + /** + * Dot is a special character in YAML that causes sub-path issues. + */ + private String encodeWorldName(String worldName) { + return worldName.replace(".", "[dot]"); + } + + private String decodeWorldName(String worldName) { + return worldName.replace("[dot]", "."); + } + private static final class ConfigMigratedException extends RuntimeException { private ConfigMigratedException() { super("Config migrated"); diff --git a/src/test/java/org/mvplugins/multiverse/core/world/WorldConfigMangerTest.kt b/src/test/java/org/mvplugins/multiverse/core/world/WorldConfigMangerTest.kt index dfd24127f..6af67ce2f 100644 --- a/src/test/java/org/mvplugins/multiverse/core/world/WorldConfigMangerTest.kt +++ b/src/test/java/org/mvplugins/multiverse/core/world/WorldConfigMangerTest.kt @@ -63,11 +63,16 @@ class WorldConfigMangerTest : TestWithMockBukkit() { @Test fun `Add a new world to config`() { - val worldConfig = worldConfigManager.addWorldConfig("newworld") + val worldConfig = worldConfigManager.addWorldConfig("new.world") assertNotNull(worldConfig) - assertEquals("newworld", worldConfig.worldName) + assertEquals("new.world", worldConfig.worldName) assertTrue(worldConfigManager.save().isSuccess) assertConfigEquals("/worlds/newworld_worlds.yml", "worlds.yml") + + // Make sure the world still can be loaded after save + assertTrue(worldConfigManager.load().isSuccess) + assertEquals("new.world", worldConfigManager.getWorldConfig("new.world").orNull?.worldName) + assertConfigEquals("/worlds/newworld_worlds.yml", "worlds.yml") } @Test diff --git a/src/test/resources/worlds/newworld_worlds.yml b/src/test/resources/worlds/newworld_worlds.yml index 639c90061..c7d0e6683 100644 --- a/src/test/resources/worlds/newworld_worlds.yml +++ b/src/test/resources/worlds/newworld_worlds.yml @@ -74,7 +74,7 @@ world_nether: spawning: {} world-blacklist: [] version: 1.2 -newworld: +new[dot]world: adjust-spawn: false alias: '' allow-advancement-grant: true