mirror of
https://github.com/Multiverse/Multiverse-Core.git
synced 2025-01-25 09:41:23 +01:00
Improve world config management with parsing of new and removed worlds on reload
This commit is contained in:
parent
b4617c1c1f
commit
5c7c9ba465
@ -30,6 +30,7 @@ import io.vavr.control.Try;
|
|||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Provider;
|
import jakarta.inject.Provider;
|
||||||
import me.main__.util.SerializationConfig.SerializationConfig;
|
import me.main__.util.SerializationConfig.SerializationConfig;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
@ -115,7 +116,10 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
|
|||||||
Logging.setShowingConfig(shouldShowConfig());
|
Logging.setShowingConfig(shouldShowConfig());
|
||||||
|
|
||||||
// Initialize the worlds
|
// Initialize the worlds
|
||||||
worldManagerProvider.get().initAllWorlds();
|
worldManagerProvider.get().initAllWorlds().onFailure(e -> {
|
||||||
|
Logging.severe("Failed to initialize worlds");
|
||||||
|
e.printStackTrace();
|
||||||
|
});
|
||||||
|
|
||||||
// Setup economy here so vault is loaded
|
// Setup economy here so vault is loaded
|
||||||
loadEconomist();
|
loadEconomist();
|
||||||
|
@ -52,7 +52,7 @@ public class ReloadCommand extends MultiverseCommand {
|
|||||||
try {
|
try {
|
||||||
// TODO: Make this all Try<Void>
|
// TODO: Make this all Try<Void>
|
||||||
this.config.load().getOrElseThrow(e -> new RuntimeException("Failed to load config", e));
|
this.config.load().getOrElseThrow(e -> new RuntimeException("Failed to load config", e));
|
||||||
this.worldManager.initAllWorlds();
|
this.worldManager.initAllWorlds().getOrElseThrow(e -> new RuntimeException("Failed to init worlds", e));
|
||||||
this.anchorManager.loadAnchors();
|
this.anchorManager.loadAnchors();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -93,37 +93,40 @@ public class WorldManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all worlds from the worlds config.
|
* Loads all worlds from the worlds config.
|
||||||
|
*
|
||||||
|
* @return The result of the load.
|
||||||
*/
|
*/
|
||||||
public void initAllWorlds() {
|
public Try<Void> initAllWorlds() {
|
||||||
if (!populateWorldFromConfig()) {
|
return populateWorldFromConfig().andThenTry(() -> {
|
||||||
return;
|
loadDefaultWorlds();
|
||||||
}
|
autoLoadWorlds();
|
||||||
loadDefaultWorlds();
|
saveWorldsConfig();
|
||||||
autoLoadWorlds();
|
});
|
||||||
saveWorldsConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate worlds from the worlds config.
|
* Populate world map from the worlds.yml config.
|
||||||
|
*
|
||||||
|
* @return The result of the world map population.
|
||||||
*/
|
*/
|
||||||
private boolean populateWorldFromConfig() {
|
private Try<Void> populateWorldFromConfig() {
|
||||||
Try<Void> load = worldsConfigManager.load();
|
return worldsConfigManager.load().mapTry(result -> {
|
||||||
if (load.isFailure()) {
|
var newWorldConfigs = result._1();
|
||||||
Logging.severe("Failed to load worlds config: " + load.getCause().getMessage());
|
var removedWorlds = result._2();
|
||||||
load.getCause().printStackTrace();
|
|
||||||
return false;
|
newWorldConfigs.forEach(worldConfig -> getWorld(worldConfig.getWorldName())
|
||||||
}
|
|
||||||
worldsConfigManager.getAllWorldConfigs().forEach(worldConfig -> {
|
|
||||||
getLoadedWorld(worldConfig.getWorldName())
|
|
||||||
.peek(loadedWorld -> loadedWorld.setWorldConfig(worldConfig));
|
|
||||||
getWorld(worldConfig.getWorldName())
|
|
||||||
.peek(unloadedWorld -> unloadedWorld.setWorldConfig(worldConfig))
|
.peek(unloadedWorld -> unloadedWorld.setWorldConfig(worldConfig))
|
||||||
.onEmpty(() -> {
|
.onEmpty(() -> {
|
||||||
MultiverseWorld mvWorld = new MultiverseWorld(worldConfig.getWorldName(), worldConfig);
|
MultiverseWorld mvWorld = new MultiverseWorld(worldConfig.getWorldName(), worldConfig);
|
||||||
worldsMap.put(mvWorld.getName(), mvWorld);
|
worldsMap.put(mvWorld.getName(), mvWorld);
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
removedWorlds.forEach(worldName -> removeWorld(worldName)
|
||||||
|
.onFailure(failure -> Logging.severe("Failed to unload world %s: %s", worldName, failure))
|
||||||
|
.onSuccess(success -> Logging.fine("Unloaded world %s as it was removed from config", worldName)));
|
||||||
|
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -361,7 +364,7 @@ public class WorldManager {
|
|||||||
replace("{world}").with(world.getName()));
|
replace("{world}").with(world.getName()));
|
||||||
},
|
},
|
||||||
mvWorld -> {
|
mvWorld -> {
|
||||||
Logging.fine("Removed MVWorld from map: " + world.getName());
|
Logging.fine("Removed MultiverseWorld from map: " + world.getName());
|
||||||
mvWorld.getWorldConfig().deferenceMVWorld();
|
mvWorld.getWorldConfig().deferenceMVWorld();
|
||||||
return Result.success(UnloadWorldResult.Success.UNLOADED,
|
return Result.success(UnloadWorldResult.Success.UNLOADED,
|
||||||
replace("{world}").with(world.getName()));
|
replace("{world}").with(world.getName()));
|
||||||
|
@ -38,6 +38,10 @@ public final class WorldConfig {
|
|||||||
return configHandle.load();
|
return configHandle.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Try<Void> load(ConfigurationSection section) {
|
||||||
|
return configHandle.load(section);
|
||||||
|
}
|
||||||
|
|
||||||
public String getWorldName() {
|
public String getWorldName() {
|
||||||
return worldName;
|
return worldName;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,30 @@
|
|||||||
package com.onarandombox.MultiverseCore.worldnew.config;
|
package com.onarandombox.MultiverseCore.worldnew.config;
|
||||||
|
|
||||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||||
|
import io.vavr.Tuple2;
|
||||||
import io.vavr.control.Try;
|
import io.vavr.control.Try;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jvnet.hk2.annotations.Service;
|
import org.jvnet.hk2.annotations.Service;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the worlds.yml file.
|
||||||
|
*/
|
||||||
@Service
|
@Service
|
||||||
public final class WorldsConfigManager {
|
public final class WorldsConfigManager {
|
||||||
private static final String CONFIG_FILENAME = "worlds2.yml";
|
private static final String CONFIG_FILENAME = "worlds2.yml"; // TODO: Rename to worlds.yml
|
||||||
|
|
||||||
private final Map<String, WorldConfig> worldConfigMap;
|
private final Map<String, WorldConfig> worldConfigMap;
|
||||||
private final File worldConfigFile;
|
private final File worldConfigFile;
|
||||||
@ -28,46 +36,88 @@ public final class WorldsConfigManager {
|
|||||||
worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
|
worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Try<Void> load() {
|
/**
|
||||||
worldConfigMap.clear();
|
* Loads the worlds.yml file and creates a WorldConfig for each world in the file if it doesn't already exist.
|
||||||
|
*
|
||||||
return Try.run(() -> {
|
* @return A tuple containing a list of the new WorldConfigs added and a list of the worlds removed from the config.
|
||||||
if (!worldConfigFile.exists()) {
|
*/
|
||||||
worldConfigFile.createNewFile();
|
public Try<Tuple2<List<WorldConfig>, List<String>>> load() {
|
||||||
}
|
return Try.of(() -> {
|
||||||
worldsConfig = new YamlConfiguration();
|
loadWorldYmlFile();
|
||||||
worldsConfig.load(worldConfigFile);
|
return parseNewAndRemovedWorlds();
|
||||||
}).andThenTry(() -> {
|
|
||||||
for (String worldName : getAllWorldsInConfig()) {
|
|
||||||
worldConfigMap.put(worldName, new WorldConfig(worldName, getWorldConfigSection(worldName)));
|
|
||||||
}
|
|
||||||
}).onFailure(e -> {
|
|
||||||
worldsConfig = null;
|
|
||||||
worldConfigMap.clear();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadWorldYmlFile() throws IOException, InvalidConfigurationException {
|
||||||
|
if (!worldConfigFile.exists() && !worldConfigFile.createNewFile()) {
|
||||||
|
throw new IllegalStateException("Could not create worlds.yml config file");
|
||||||
|
}
|
||||||
|
|
||||||
|
worldsConfig = new YamlConfiguration();
|
||||||
|
worldsConfig.load(worldConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tuple2<List<WorldConfig>, List<String>> parseNewAndRemovedWorlds() {
|
||||||
|
Set<String> allWorldsInConfig = worldsConfig.getKeys(false);
|
||||||
|
List<WorldConfig> newWorldsAdded = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String worldName : allWorldsInConfig) {
|
||||||
|
WorldConfig worldConfig = getWorldConfig(worldName);
|
||||||
|
if (worldConfig == null) {
|
||||||
|
WorldConfig newWorldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName));
|
||||||
|
worldConfigMap.put(worldName, newWorldConfig);
|
||||||
|
newWorldsAdded.add(newWorldConfig);
|
||||||
|
} else {
|
||||||
|
worldConfig.load(getWorldConfigSection(worldName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> worldsRemoved = worldConfigMap.keySet().stream()
|
||||||
|
.filter(worldName -> !allWorldsInConfig.contains(worldName))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (String s : worldsRemoved) {
|
||||||
|
worldConfigMap.remove(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Tuple2<>(newWorldsAdded, worldsRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the worlds.yml file has been loaded.
|
||||||
|
*
|
||||||
|
* @return Whether the worlds.yml file has been loaded.
|
||||||
|
*/
|
||||||
public boolean isLoaded() {
|
public boolean isLoaded() {
|
||||||
return worldsConfig != null;
|
return worldsConfig != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the worlds.yml file.
|
||||||
|
*
|
||||||
|
* @return Whether the save was successful or the error that occurred.
|
||||||
|
*/
|
||||||
public Try<Void> save() {
|
public Try<Void> save() {
|
||||||
return Try.run(() -> worldsConfig.save(worldConfigFile));
|
return Try.run(() -> worldsConfig.save(worldConfigFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getAllWorldsInConfig() {
|
/**
|
||||||
return worldsConfig.getKeys(false);
|
* Gets the {@link WorldConfig} instance of all worlds in the worlds.yml file.
|
||||||
}
|
*
|
||||||
|
* @param worldName The name of the world to check.
|
||||||
public Collection<WorldConfig> getAllWorldConfigs() {
|
* @return Whether the worlds.yml file contains the given world.
|
||||||
return worldConfigMap.values();
|
*/
|
||||||
}
|
public @Nullable WorldConfig getWorldConfig(@NotNull String worldName) {
|
||||||
|
|
||||||
public WorldConfig getWorldConfig(String worldName) {
|
|
||||||
return worldConfigMap.get(worldName);
|
return worldConfigMap.get(worldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorldConfig addWorldConfig(String worldName) {
|
/**
|
||||||
|
* Add a new world to the worlds.yml file. If a world with the given name already exists, an exception is thrown.
|
||||||
|
*
|
||||||
|
* @param worldName The name of the world to add.
|
||||||
|
* @return The newly created {@link WorldConfig} instance.
|
||||||
|
*/
|
||||||
|
public @NotNull WorldConfig addWorldConfig(@NotNull String worldName) {
|
||||||
if (worldConfigMap.containsKey(worldName)) {
|
if (worldConfigMap.containsKey(worldName)) {
|
||||||
throw new IllegalArgumentException("WorldConfig for world " + worldName + " already exists.");
|
throw new IllegalArgumentException("WorldConfig for world " + worldName + " already exists.");
|
||||||
}
|
}
|
||||||
@ -76,7 +126,12 @@ public final class WorldsConfigManager {
|
|||||||
return worldConfig;
|
return worldConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteWorldConfig(String worldName) {
|
/**
|
||||||
|
* Deletes the world config for the given world.
|
||||||
|
*
|
||||||
|
* @param worldName The name of the world to delete.
|
||||||
|
*/
|
||||||
|
public void deleteWorldConfig(@NotNull String worldName) {
|
||||||
worldConfigMap.remove(worldName);
|
worldConfigMap.remove(worldName);
|
||||||
worldsConfig.set(worldName, null);
|
worldsConfig.set(worldName, null);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,8 @@ class WorldConfigMangerTest : TestWithMockBukkit() {
|
|||||||
@Test
|
@Test
|
||||||
fun `Updating existing world properties`() {
|
fun `Updating existing world properties`() {
|
||||||
val worldConfig = worldConfigManager.getWorldConfig("world")
|
val worldConfig = worldConfigManager.getWorldConfig("world")
|
||||||
|
assertNotNull(worldConfig)
|
||||||
|
|
||||||
worldConfig.setProperty("adjust-spawn", true)
|
worldConfig.setProperty("adjust-spawn", true)
|
||||||
worldConfig.setProperty("alias", "newalias")
|
worldConfig.setProperty("alias", "newalias")
|
||||||
worldConfig.setProperty("spawn-location", SpawnLocation(-64.0, 64.0, 48.0))
|
worldConfig.setProperty("spawn-location", SpawnLocation(-64.0, 64.0, 48.0))
|
||||||
|
@ -29,7 +29,8 @@ class WorldConfigTest : TestWithMockBukkit() {
|
|||||||
throw IllegalStateException("WorldsConfigManager is not available as a service") }
|
throw IllegalStateException("WorldsConfigManager is not available as a service") }
|
||||||
|
|
||||||
assertTrue(worldConfigManager.load().isSuccess)
|
assertTrue(worldConfigManager.load().isSuccess)
|
||||||
worldConfig = worldConfigManager.getWorldConfig("world")
|
worldConfig = worldConfigManager.getWorldConfig("world").takeIf { it != null } ?: run {
|
||||||
|
throw IllegalStateException("WorldConfig for world is not available") }
|
||||||
assertNotNull(worldConfig);
|
assertNotNull(worldConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user