Implement basic create and delete world

This commit is contained in:
Ben Woo 2023-09-02 16:54:33 +08:00
parent 5dd22b5d9b
commit e1eae48bc7
No known key found for this signature in database
GPG Key ID: FB2A3645536E12C8
11 changed files with 188 additions and 97 deletions

View File

@ -129,7 +129,7 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
}
var newWorldManager = newWorldManagerProvider.get();
newWorldManager.loadAllWorlds(); // TODO: Possibly move this to constructor of WorldManager
newWorldManager.initAllWorlds(); // TODO: Possibly move this to constructor of WorldManager
//Setup economy here so vault is loaded
this.loadEconomist();

View File

@ -18,6 +18,9 @@ public class MVWorld extends OfflineWorld {
) {
super(worldName, worldConfig);
this.worldUid = worldUid;
worldConfig.setMVWorld(this);
worldConfig.load();
}
public World getBukkitWorld() {

View File

@ -13,7 +13,7 @@ public class OfflineWorld {
this.worldConfig = worldConfig;
}
public String getWorldName() {
public String getName() {
return worldName;
}

View File

@ -1,17 +1,19 @@
package com.onarandombox.MultiverseCore.worldnew;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.utils.file.FileUtils;
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig;
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigFile;
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager;
import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions;
import io.vavr.control.Option;
import jakarta.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
@ -20,23 +22,32 @@ public class WorldManager {
private final Map<String, OfflineWorld> offlineWorldsMap;
private final Map<String, MVWorld> worldsMap;
private final WorldsConfigFile worldsConfigFile;
private final WorldsConfigManager worldsConfigManager;
@Inject
WorldManager(@NotNull WorldsConfigFile worldsConfigFile) {
WorldManager(@NotNull WorldsConfigManager worldsConfigFile) {
this.offlineWorldsMap = new HashMap<>();
this.worldsMap = new HashMap<>();
this.worldsConfigFile = worldsConfigFile;
this.worldsConfigManager = worldsConfigFile;
}
public void loadAllWorlds() {
for (String worldName : worldsConfigFile.getAllWorldsInConfig()) {
public void initAllWorlds() {
populateOfflineWorlds();
worldsConfigManager.getAllWorldsInConfig().forEach(worldName -> {
Logging.fine("Loading world: " + worldName);
loadWorld(worldName);
}
});
saveWorldsConfig();
}
private void populateOfflineWorlds() {
// TODO: Check for worlds that are removed after config reload
worldsConfigManager.getAllWorldConfigs().forEach(worldConfig -> {
OfflineWorld offlineWorld = new OfflineWorld(worldConfig.getWorldName(), worldConfig);
offlineWorldsMap.put(worldConfig.getWorldName(), offlineWorld);
});
}
/**
* Creates a new world.
*
@ -62,7 +73,7 @@ public class WorldManager {
}
// Our multiverse world
WorldConfig worldConfig = worldsConfigFile.getWorldConfig(options.worldName());
WorldConfig worldConfig = worldsConfigManager.addWorldConfig(options.worldName());
worldConfig.setEnvironment(options.environment());
worldConfig.setGenerator(options.generator());
worldConfig.setSeed(world.getSeed());
@ -76,25 +87,44 @@ public class WorldManager {
saveWorldsConfig();
}
public void loadWorld(String worldName) {
WorldConfig worldConfig = worldsConfigFile.getWorldConfig(worldName);
public void loadWorld(@NotNull String worldName) {
// TODO: Implement logic
}
public void unloadWorld() {
public void unloadWorld(@NotNull MVWorld world) {
// TODO: Implement logic
}
public void removeWorld(String worldName) {
public void removeWorld(@NotNull MVWorld world) {
// TODO: Implement logic
worldsConfigFile.deleteWorldConfigSection(worldName);
worldsConfigManager.deleteWorldConfig(world.getName());
saveWorldsConfig();
}
public void deleteWorld(String worldName) {
// TODO: Implement logic
worldsConfigFile.deleteWorldConfigSection(worldName);
public void deleteWorld(@NotNull MVWorld world) {
World bukkitWorld = world.getBukkitWorld();
File worldFolder = bukkitWorld.getWorldFolder();
// Unload world
// TODO: removePlayersFromWorld?
if (!Bukkit.unloadWorld(bukkitWorld, true)) {
Logging.severe("Failed to unload world: " + world.getName());
return;
}
if (Bukkit.getWorld(world.getName()) != null) {
Logging.severe("World still loaded: " + world.getName());
return;
}
worldsMap.remove(world.getName());
// Remove world from config
offlineWorldsMap.remove(world.getName());
worldsConfigManager.deleteWorldConfig(world.getName());
saveWorldsConfig();
// Erase world files from disk
// TODO: Config options to keep certain files
FileUtils.deleteFolder(worldFolder);
}
public Option<OfflineWorld> getOfflineWorld(@NotNull String worldName) {
@ -106,6 +136,6 @@ public class WorldManager {
}
public void saveWorldsConfig() {
worldsConfigFile.save();
worldsConfigManager.save();
}
}

View File

@ -3,6 +3,7 @@ package com.onarandombox.MultiverseCore.worldnew.config;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.configuration.handle.ConfigurationSectionHandle;
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
import com.onarandombox.MultiverseCore.worldnew.MVWorld;
import io.vavr.control.Try;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
@ -14,17 +15,28 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class WorldConfig {
private final String worldName;
private final WorldConfigNodes configNodes;
private final ConfigurationSectionHandle configHandle;
public WorldConfig(@NotNull final ConfigurationSection configSection) {
public WorldConfig(@NotNull String worldName, @NotNull final ConfigurationSection configSection) {
this.worldName = worldName;
this.configNodes = new WorldConfigNodes();
// TODO: Config migration and version
this.configHandle = ConfigurationSectionHandle.builder(configSection)
.logger(Logging.getLogger())
.nodes(configNodes.getNodes())
.build();
this.configHandle.load();
load();
}
public boolean load() {
return configHandle.load();
}
public String getWorldName() {
return worldName;
}
public Try<Object> getProperty(String name) {
@ -194,4 +206,12 @@ public class WorldConfig {
public void setWorldBlacklist(List<String> worldBlacklist) {
configHandle.set(configNodes.WORLD_BLACKLIST, worldBlacklist);
}
public void setMVWorld(@NotNull MVWorld world) {
configNodes.setMVWorld(world);
}
public void unloadMVWorld() {
configNodes.unloadMVWorld();
}
}

View File

@ -4,15 +4,18 @@ import com.onarandombox.MultiverseCore.configuration.node.ConfigNode;
import com.onarandombox.MultiverseCore.configuration.node.Node;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
import com.onarandombox.MultiverseCore.worldnew.MVWorld;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class WorldConfigNodes {
private final NodeGroup nodes = new NodeGroup();
private MVWorld world = null;
WorldConfigNodes() {
}
@ -126,6 +129,14 @@ public class WorldConfigNodes {
.name("world-blacklist")
.build());
public void setMVWorld(@NotNull MVWorld world) {
this.world = world;
}
public void unloadMVWorld() {
this.world = null;
}
// TODO: Migrate color and style into alias
// TODO: spawning
// TODO: entryfee

View File

@ -1,60 +0,0 @@
package com.onarandombox.MultiverseCore.worldnew.config;
import com.onarandombox.MultiverseCore.MultiverseCore;
import jakarta.inject.Inject;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
@Service
public class WorldsConfigFile {
private static final String CONFIG_FILENAME = "worlds2.yml";
private final File worldConfigFile;
private YamlConfiguration worldConfig;
@Inject
public WorldsConfigFile(@NotNull MultiverseCore core) {
worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
load();
}
public void load() {
// TODO: Migration from old worlds.yml
worldConfig = YamlConfiguration.loadConfiguration(worldConfigFile);
}
public boolean isLoaded() {
return worldConfig != null;
}
public void save() {
try {
worldConfig.save(worldConfigFile);
} catch (IOException e) {
e.printStackTrace();
}
}
public Collection<String> getAllWorldsInConfig() {
return worldConfig.getKeys(false);
}
public ConfigurationSection getWorldConfigSection(String worldName) {
return worldConfig.isConfigurationSection(worldName)
? worldConfig.getConfigurationSection(worldName) : worldConfig.createSection(worldName);
}
public WorldConfig getWorldConfig(String worldName) {
return new WorldConfig(getWorldConfigSection(worldName));
}
public void deleteWorldConfigSection(String worldName) {
worldConfig.set(worldName, null);
}
}

View File

@ -0,0 +1,81 @@
package com.onarandombox.MultiverseCore.worldnew.config;
import com.onarandombox.MultiverseCore.MultiverseCore;
import jakarta.inject.Inject;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Service
public class WorldsConfigManager {
private static final String CONFIG_FILENAME = "worlds2.yml";
private final Map<String, WorldConfig> worldConfigMap;
private final File worldConfigFile;
private YamlConfiguration worldsConfig;
@Inject
public WorldsConfigManager(@NotNull MultiverseCore core) {
worldConfigMap = new HashMap<>();
worldConfigFile = core.getDataFolder().toPath().resolve(CONFIG_FILENAME).toFile();
load();
}
private void load() {
// TODO: Migration from old worlds.yml
worldsConfig = YamlConfiguration.loadConfiguration(worldConfigFile);
for (String worldName : getAllWorldsInConfig()) {
worldConfigMap.put(worldName, new WorldConfig(worldName, getWorldConfigSection(worldName)));
}
}
public boolean isLoaded() {
return worldsConfig != null;
}
public void save() {
try {
worldsConfig.save(worldConfigFile);
} catch (IOException e) {
e.printStackTrace();
}
}
public Collection<String> getAllWorldsInConfig() {
return worldsConfig.getKeys(false);
}
public Collection<WorldConfig> getAllWorldConfigs() {
return worldConfigMap.values();
}
public WorldConfig getWorldConfig(String worldName) {
return worldConfigMap.get(worldName);
}
public WorldConfig addWorldConfig(String worldName) {
if (worldConfigMap.containsKey(worldName)) {
throw new IllegalArgumentException("WorldConfig for world " + worldName + " already exists.");
}
WorldConfig worldConfig = new WorldConfig(worldName, getWorldConfigSection(worldName));
worldConfigMap.put(worldName, worldConfig);
return worldConfig;
}
public void deleteWorldConfig(String worldName) {
worldConfigMap.remove(worldName);
worldsConfig.set(worldName, null);
}
private ConfigurationSection getWorldConfigSection(String worldName) {
return worldsConfig.isConfigurationSection(worldName)
? worldsConfig.getConfigurationSection(worldName) : worldsConfig.createSection(worldName);
}
}

View File

@ -1,7 +1,6 @@
package org.mvplugins.multiverse.core.world
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigFile
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.mvplugins.multiverse.core.TestWithMockBukkit
@ -12,9 +11,9 @@ import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertNotNull
class WorldConfigFileTest : TestWithMockBukkit() {
class WorldConfigMangerTest : TestWithMockBukkit() {
private lateinit var worldConfigFile : WorldsConfigFile
private lateinit var worldConfigFile : WorldsConfigManager
@BeforeTest
fun setUp() {
@ -22,8 +21,8 @@ class WorldConfigFileTest : TestWithMockBukkit() {
assertNotNull(defaultConfig)
File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig)
worldConfigFile = WorldsConfigFile(multiverseCore)
worldConfigFile.load()
worldConfigFile =
WorldsConfigManager(multiverseCore)
}
@Test
@ -38,7 +37,7 @@ class WorldConfigFileTest : TestWithMockBukkit() {
@Test
fun `Add a new world to config`() {
val worldConfig = worldConfigFile.getWorldConfig("newworld")
val worldConfig = worldConfigFile.addWorldConfig("newworld")
worldConfigFile.save()
compareConfigFile("worlds2.yml", "/newworld_worlds.yml")
}
@ -54,7 +53,7 @@ class WorldConfigFileTest : TestWithMockBukkit() {
@Test
fun `Delete world section from config`() {
worldConfigFile.deleteWorldConfigSection("world")
worldConfigFile.deleteWorldConfig("world")
worldConfigFile.save()
compareConfigFile("worlds2.yml", "/delete_worlds.yml")
}

View File

@ -1,7 +1,7 @@
package org.mvplugins.multiverse.core.world
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigFile
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager
import org.mvplugins.multiverse.core.TestWithMockBukkit
import java.io.File
import java.nio.file.Path
@ -14,7 +14,7 @@ import kotlin.test.assertTrue
class WorldConfigTest : TestWithMockBukkit() {
private lateinit var worldConfigFile : WorldsConfigFile
private lateinit var worldConfigFile : WorldsConfigManager
private lateinit var worldConfig : WorldConfig
@BeforeTest
@ -23,8 +23,8 @@ class WorldConfigTest : TestWithMockBukkit() {
assertNotNull(defaultConfig)
File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig)
worldConfigFile = WorldsConfigFile(multiverseCore)
worldConfigFile.load()
worldConfigFile =
WorldsConfigManager(multiverseCore)
worldConfig = worldConfigFile.getWorldConfig("world")
}

View File

@ -1,5 +1,6 @@
package org.mvplugins.multiverse.core.world
import com.onarandombox.MultiverseCore.worldnew.MVWorld
import com.onarandombox.MultiverseCore.worldnew.WorldManager
import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions
import org.bukkit.World
@ -8,16 +9,22 @@ import org.mvplugins.multiverse.core.TestWithMockBukkit
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
class WorldManagerTest : TestWithMockBukkit() {
private lateinit var worldManager: WorldManager
private lateinit var world: MVWorld
@BeforeTest
fun setUp() {
worldManager = multiverseCore.getService(WorldManager::class.java).takeIf { it != null } ?: run {
throw IllegalStateException("WorldManager is not available as a service") }
worldManager.createWorld(CreateWorldOptions.worldName("world"))
world = worldManager.getMVWorld("world").get()
assertNotNull(world)
}
@Test
@ -32,7 +39,7 @@ class WorldManagerTest : TestWithMockBukkit() {
val world = worldManager.getMVWorld("world_nether").get()
assertNotNull(world)
assertEquals("world_nether", world.worldName)
assertEquals("world_nether", world.name)
assertEquals(World.Environment.NETHER, world.getProperty("environment").get())
assertEquals("", world.getProperty("generator").get())
assertEquals(1234L, world.getProperty("seed").get())
@ -40,7 +47,7 @@ class WorldManagerTest : TestWithMockBukkit() {
@Test
fun `Delete world`() {
worldManager.deleteWorld("world")
// TODO: When logic is implemented, check that the world is removed
worldManager.deleteWorld(world)
assertFalse(worldManager.getMVWorld("world").isDefined)
}
}