Skip to content

Commit 156ec79

Browse files
authored
Merge pull request #3308 from Multiverse/fix/world-name-dot
Fix v4 config migration when world name contains dot
2 parents 539d5c4 + 2b95c62 commit 156ec79

File tree

4 files changed

+151
-11
lines changed

4 files changed

+151
-11
lines changed

src/main/java/org/mvplugins/multiverse/core/world/WorldsConfigManager.java

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,24 +84,34 @@ private void migrateRemoveOldConfigSerializable() {
8484
Path oldWorldConfig = worldConfigFile.toPath().getParent().resolve(CONFIG_FILENAME + ".old");
8585
Files.copy(worldConfigFile.toPath(), oldWorldConfig, COPY_ATTRIBUTES);
8686

87-
return configData.replace("==: MVWorld", "")
87+
return configData.replace("==: MVWorld", "w@: world")
8888
.replace("==: MVSpawnSettings", "")
8989
.replace("==: MVSpawnSubSettings", "")
9090
.replace("==: MVEntryFee", "");
9191
})
9292
.andThenTry(configData -> Files.writeString(worldConfigFile.toPath(), configData))
9393
.andThenTry(() -> {
9494
YamlConfiguration config = YamlConfiguration.loadConfiguration(worldConfigFile);
95-
List<ConfigurationSection> worlds = config.getConfigurationSection("worlds")
96-
.getKeys(false)
97-
.stream()
98-
.map(worldName -> config.getConfigurationSection("worlds." + worldName))
99-
.toList();
95+
96+
ConfigurationSection worldsSection = config.getConfigurationSection("worlds");
97+
if (worldsSection == null) {
98+
worldsSection = config.createSection("worlds");
99+
}
100+
101+
List<String> worldNames = getOldConfigWorldNames(worldsSection);
102+
103+
Map<String, ConfigurationSection> worldConfigMap = new HashMap<>();
104+
for (String worldName : worldNames) {
105+
ConfigurationSection worldSection = worldsSection.getConfigurationSection(worldName);
106+
if (worldSection != null) {
107+
worldConfigMap.put(worldName, worldSection);
108+
}
109+
}
100110

101111
config.set("worlds", null);
102112

103-
for (ConfigurationSection world : worlds) {
104-
config.createSection(world.getName(), world.getValues(true));
113+
for (Map.Entry<String, ConfigurationSection> entry : worldConfigMap.entrySet()) {
114+
config.set(encodeWorldName(entry.getKey()), entry.getValue());
105115
}
106116
config.save(worldConfigFile);
107117
})
@@ -115,6 +125,35 @@ private void migrateRemoveOldConfigSerializable() {
115125
});
116126
}
117127

128+
private @NotNull List<String> getOldConfigWorldNames(ConfigurationSection worldsSection) {
129+
List<String> worldNames = new ArrayList<>();
130+
recursiveGetOldConfigWorldNames(worldsSection, worldNames);
131+
return worldNames;
132+
}
133+
134+
private void recursiveGetOldConfigWorldNames(ConfigurationSection section, List<String> worldNames) {
135+
Set<String> keys = section.getKeys(false);
136+
if (keys.isEmpty()) {
137+
// No keys in this section, nothing to do
138+
return;
139+
}
140+
141+
if (keys.contains("w@")) {
142+
// this is the world data section already, get path without the "worlds." prefix
143+
worldNames.add(section.getCurrentPath().substring(7));
144+
return;
145+
}
146+
147+
for (String key : keys) {
148+
ConfigurationSection dataSection = section.getConfigurationSection(key);
149+
if (dataSection == null) {
150+
// Something is wrong with the config, skip this key
151+
continue;
152+
}
153+
recursiveGetOldConfigWorldNames(dataSection, worldNames);
154+
}
155+
}
156+
118157
/**
119158
* Parses the worlds.yml file and creates a WorldConfig for each world in the file if it doesn't already exist.
120159
*

src/test/java/org/mvplugins/multiverse/core/world/WorldConfigMangerTest.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class WorldConfigMangerTest : TestWithMockBukkit() {
4949
assertEquals(MVEconomist.VAULT_ECONOMY_MATERIAL, endWorldConfig.entryFeeCurrency)
5050
assertEquals(0.0, endWorldConfig.entryFeeAmount)
5151

52-
val worldConfig = worldConfigManager.getWorldConfig("world").orNull
52+
val worldConfig = worldConfigManager.getWorldConfig("world.a.b").orNull
5353
assertNotNull(worldConfig)
5454

5555
assertEquals(-5176596003035866649, worldConfig.seed)
@@ -58,6 +58,9 @@ class WorldConfigMangerTest : TestWithMockBukkit() {
5858
assertEquals(Material.DIRT, worldConfig.entryFeeCurrency)
5959
assertEquals(5.0, worldConfig.entryFeeAmount)
6060

61+
val world2Config = worldConfigManager.getWorldConfig("world.a.c").orNull
62+
assertNotNull(world2Config)
63+
6164
assertConfigEquals("/worlds/migrated_worlds.yml", "worlds.yml")
6265
}
6366

src/test/resources/worlds/migrated_worlds.yml

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ world_the_end:
4646
tick-rate: -1
4747
world-blacklist: []
4848
version: 1.2
49-
world:
49+
world[dot]a[dot]b:
5050
adjust-spawn: true
5151
alias: ''
5252
allow-advancement-grant: true
@@ -95,3 +95,52 @@ world:
9595
world-blacklist:
9696
- test
9797
version: 1.2
98+
world[dot]a[dot]c:
99+
adjust-spawn: true
100+
alias: ''
101+
allow-advancement-grant: true
102+
allow-flight: false
103+
allow-weather: true
104+
anchor-respawn: true
105+
auto-heal: true
106+
auto-load: true
107+
bed-respawn: true
108+
difficulty: normal
109+
entry-fee:
110+
enabled: true
111+
amount: 5.0
112+
currency: DIRT
113+
environment: normal
114+
gamemode: survival
115+
biome: ''
116+
generator: ''
117+
hidden: false
118+
hunger: true
119+
keep-spawn-in-memory: true
120+
player-limit: -1
121+
portal-form: all
122+
pvp: true
123+
respawn-world: ''
124+
scale: 1.0
125+
seed: -5176596003035866649
126+
spawn-location:
127+
==: MVSpawnLocation
128+
x: -64.0
129+
y: 64.0
130+
z: 48.0
131+
pitch: 0.0
132+
yaw: 0.0
133+
spawning:
134+
animal:
135+
exceptions: [ ]
136+
spawn: true
137+
spawn-limit: -1
138+
tick-rate: -1
139+
monster:
140+
exceptions: [ ]
141+
spawn: true
142+
spawn-limit: -1
143+
tick-rate: -1
144+
world-blacklist:
145+
- test
146+
version: 1.2

src/test/resources/worlds/old_worlds.yml

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ worlds:
4646
generator: 'null'
4747
playerLimit: '-1'
4848
allowFlight: 'true'
49-
world:
49+
world.a.b:
5050
==: MVWorld
5151
hidden: 'false'
5252
alias: ''
@@ -95,3 +95,52 @@ worlds:
9595
generator: 'null'
9696
playerLimit: '-1'
9797
allowFlight: 'false'
98+
world.a.c:
99+
==: MVWorld
100+
hidden: 'false'
101+
alias: ''
102+
color: WHITE
103+
style: NORMAL
104+
pvp: 'true'
105+
scale: '1.0'
106+
respawnWorld: ''
107+
allowWeather: 'true'
108+
difficulty: NORMAL
109+
spawning:
110+
==: MVSpawnSettings
111+
animals:
112+
==: MVSpawnSubSettings
113+
spawn: 'true'
114+
spawnrate: '-1'
115+
exceptions: []
116+
monsters:
117+
==: MVSpawnSubSettings
118+
spawn: 'true'
119+
spawnrate: '-1'
120+
exceptions: []
121+
entryfee:
122+
==: MVEntryFee
123+
amount: '5.0'
124+
currency: 'DIRT'
125+
hunger: 'true'
126+
autoHeal: 'true'
127+
adjustSpawn: 'true'
128+
portalForm: ALL
129+
gameMode: SURVIVAL
130+
keepSpawnInMemory: 'true'
131+
spawnLocation:
132+
==: MVSpawnLocation
133+
x: -64.0
134+
y: 64.0
135+
z: 48.0
136+
pitch: 0.0
137+
yaw: 0.0
138+
autoLoad: 'true'
139+
bedRespawn: 'true'
140+
worldBlacklist:
141+
- test
142+
environment: NORMAL
143+
seed: '-5176596003035866649'
144+
generator: 'null'
145+
playerLimit: '-1'
146+
allowFlight: 'false'

0 commit comments

Comments
 (0)