Merge pull request #2984 from Multiverse/worlds-config

Worlds config
This commit is contained in:
Ben Woo 2023-08-31 23:27:10 +08:00 committed by GitHub
commit d1ff487a00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 719 additions and 5 deletions

View File

@ -25,6 +25,7 @@ import com.onarandombox.MultiverseCore.placeholders.MultiverseCorePlaceholders;
import com.onarandombox.MultiverseCore.utils.TestingMode;
import com.onarandombox.MultiverseCore.utils.metrics.MetricsConfigurator;
import com.onarandombox.MultiverseCore.world.WorldProperties;
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
import io.vavr.control.Try;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
@ -58,6 +59,8 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
@Inject
private Provider<MVWorldManager> worldManagerProvider;
@Inject
private Provider<WorldManager> newWorldManagerProvider;
@Inject
private Provider<AnchorManager> anchorManagerProvider;
@Inject
private Provider<MVCommandManager> commandManagerProvider;
@ -125,6 +128,9 @@ public class MultiverseCore extends JavaPlugin implements MVCore {
config.setFirstSpawnLocation(firstSpawnWorld.getName());
}
var newWorldManager = newWorldManagerProvider.get();
newWorldManager.loadAllWorlds(); // TODO: Possibly move this to constructor of WorldManager
//Setup economy here so vault is loaded
this.loadEconomist();

View File

@ -23,7 +23,6 @@ abstract class FileConfigHandle<C extends FileConfiguration> extends GenericConf
protected final @NotNull Path configPath;
protected final @NotNull File configFile;
protected FileConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @Nullable NodeGroup nodes, @Nullable ConfigMigrator migrator) {
super(logger, nodes, migrator);
this.configPath = configPath;

View File

@ -3,7 +3,9 @@ package com.onarandombox.MultiverseCore.configuration.handle;
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
import com.onarandombox.MultiverseCore.configuration.node.ConfigNodeNotFoundException;
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
import com.onarandombox.MultiverseCore.configuration.node.NodeSerializer;
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
import io.vavr.control.Option;
import io.vavr.control.Try;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.Plugin;
@ -58,7 +60,7 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
nodes.forEach(node -> {
if (node instanceof ValueNode valueNode) {
set(valueNode, config.getObject(valueNode.getPath(), valueNode.getType(), valueNode.getDefaultValue()));
set(valueNode, get(valueNode));
}
});
}
@ -81,7 +83,10 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
* @return The value of the node.
*/
public <T> T get(@NotNull ValueNode<T> node) {
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
if (node.getSerializer() == null) {
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
}
return node.getSerializer().deserialize(config.get(node.getPath(), node.getDefaultValue()), node.getType());
}
/**
@ -108,7 +113,12 @@ public abstract class GenericConfigHandle<C extends ConfigurationSection> {
public <T> Try<Void> set(@NotNull ValueNode<T> node, T value) {
return node.validate(value).map(ignore -> {
T oldValue = get(node);
config.set(node.getPath(), value);
if (node.getSerializer() != null) {
var serialized = node.getSerializer().serialize(value, node.getType());
config.set(node.getPath(), serialized);
} else {
config.set(node.getPath(), value);
}
node.onSetValue(oldValue, get(node));
return null;
});

View File

@ -32,6 +32,7 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
protected final @Nullable String name;
protected final @NotNull Class<T> type;
protected final @Nullable T defaultValue;
protected final @Nullable NodeSerializer<T> serializer;
protected final @Nullable Function<T, Try<Void>> validator;
protected final @Nullable BiConsumer<T, T> onSetValue;
@ -41,6 +42,7 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
@Nullable String name,
@NotNull Class<T> type,
@Nullable T defaultValue,
@Nullable NodeSerializer<T> serializer,
@Nullable Function<T, Try<Void>> validator,
@Nullable BiConsumer<T, T> onSetValue
) {
@ -48,6 +50,7 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
this.name = name;
this.type = type;
this.defaultValue = defaultValue;
this.serializer = serializer;
this.validator = validator;
this.onSetValue = onSetValue;
}
@ -76,6 +79,10 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
return defaultValue;
}
public @Nullable NodeSerializer<T> getSerializer() {
return serializer;
}
/**
* {@inheritDoc}
*/
@ -104,10 +111,12 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
* @param <B> The type of the builder.
*/
public static class Builder<T, B extends ConfigNode.Builder<T, B>> extends ConfigHeaderNode.Builder<B> {
private static final NodeSerializer<?> ENUM_NODE_SERIALIZER = new EnumNodeSerializer<>();
protected @Nullable String name;
protected @NotNull final Class<T> type;
protected @Nullable T defaultValue;
protected @Nullable NodeSerializer<T> serializer;
protected @Nullable Function<T, Try<Void>> validator;
protected @Nullable BiConsumer<T, T> onSetValue;
@ -121,6 +130,9 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
super(path);
this.name = path;
this.type = type;
if (type.isEnum()) {
this.serializer = (NodeSerializer<T>) ENUM_NODE_SERIALIZER;
}
}
/**
@ -145,6 +157,11 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
return (B) this;
}
public @NotNull B serializer(@NotNull NodeSerializer<T> serializer) {
this.serializer = serializer;
return (B) this;
}
public @NotNull B validator(@NotNull Function<T, Try<Void>> validator) {
this.validator = validator;
return (B) this;
@ -166,7 +183,7 @@ public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
*/
@Override
public @NotNull ConfigNode<T> build() {
return new ConfigNode<>(path, comments.toArray(new String[0]), name, type, defaultValue, validator, onSetValue);
return new ConfigNode<>(path, comments.toArray(new String[0]), name, type, defaultValue, serializer, validator, onSetValue);
}
}
}

View File

@ -0,0 +1,16 @@
package com.onarandombox.MultiverseCore.configuration.node;
import com.dumptruckman.minecraft.util.Logging;
public class EnumNodeSerializer<T extends Enum<T>> implements NodeSerializer<T> {
@Override
public T deserialize(Object object, Class<T> type) {
return Enum.valueOf(type, object.toString().toUpperCase());
}
@Override
public Object serialize(T object, Class<T> type) {
return object.toString();
}
}

View File

@ -0,0 +1,6 @@
package com.onarandombox.MultiverseCore.configuration.node;
public interface NodeSerializer<T> {
T deserialize(Object object, Class<T> type);
Object serialize(T object, Class<T> type);
}

View File

@ -28,6 +28,13 @@ public interface ValueNode<T> extends Node {
*/
@Nullable T getDefaultValue();
/**
* Gets the serializer for this node.
*
* @return The serializer for this node.
*/
@Nullable NodeSerializer<T> getSerializer();
/**
* Validates the value of this node.
*

View File

@ -0,0 +1,71 @@
package com.onarandombox.MultiverseCore.worldnew;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig;
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigFile;
import jakarta.inject.Inject;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import java.util.List;
@Service
public class WorldManager {
private final WorldsConfigFile worldsConfigFile;
@Inject
WorldManager(@NotNull WorldsConfigFile worldsConfigFile) {
this.worldsConfigFile = worldsConfigFile;
this.worldsConfigFile.load();
}
public void loadAllWorlds() {
for (String worldName : worldsConfigFile.getAllWorldsInConfig()) {
Logging.fine("Loading world: " + worldName);
loadWorld(worldName);
}
saveWorldsConfig();
}
public void addWorld(String worldName) {
ConfigurationSection worldConfigSection = worldsConfigFile.getWorldConfigSection(worldName);
WorldConfig worldConfig = new WorldConfig(worldConfigSection);
//todo
saveWorldsConfig();
}
public void loadWorld(String worldName) {
ConfigurationSection worldConfigSection = worldsConfigFile.getWorldConfigSection(worldName);
WorldConfig worldConfig = new WorldConfig(worldConfigSection);
//todo
}
public void unloadWorld() {
//todo
}
public void removeWorld(String worldName) {
//todo
worldsConfigFile.deleteWorldConfigSection(worldName);
saveWorldsConfig();
}
public void deleteWorld(String worldName) {
//todo
worldsConfigFile.deleteWorldConfigSection(worldName);
saveWorldsConfig();
}
public void getMVWorld(String worldName) {
//todo
}
public void getUnloadedWorld(String worldName) {
//todo
}
public void saveWorldsConfig() {
worldsConfigFile.save();
}
}

View File

@ -0,0 +1,57 @@
package com.onarandombox.MultiverseCore.worldnew.config;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.configuration.handle.ConfigurationSectionHandle;
import io.vavr.control.Try;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class WorldConfig {
private final WorldConfigNodes configNodes;
private final ConfigurationSectionHandle configHandle;
public WorldConfig(@NotNull final ConfigurationSection configSection) {
this.configNodes = new WorldConfigNodes();
//todo: Config migration and version
this.configHandle = ConfigurationSectionHandle.builder(configSection)
.logger(Logging.getLogger())
.nodes(configNodes.getNodes())
.build();
this.configHandle.load();
}
public Try<Object> getProperty(String name) {
return configHandle.get(name);
}
public Try<Void> setProperty(String name, Object value) {
return configHandle.set(name, value);
}
public void setAlias(String alias) {
configHandle.set(configNodes.ALIAS, alias);
}
public @Nullable String getAlias() {
return configHandle.get(configNodes.ALIAS);
}
public void setHidden(boolean hidden) {
configHandle.set(configNodes.HIDDEN, hidden);
}
public boolean isHidden() {
return configHandle.get(configNodes.HIDDEN);
}
public List<String> getWorldBlacklist() {
return (List<String>) configHandle.get(configNodes.WORLD_BLACKLIST);
}
public void setWorldBlacklist(List<String> worldBlacklist) {
configHandle.set(configNodes.WORLD_BLACKLIST, worldBlacklist);
}
}

View File

@ -0,0 +1,134 @@
package com.onarandombox.MultiverseCore.worldnew.config;
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 org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.World;
import java.util.ArrayList;
import java.util.List;
public class WorldConfigNodes {
private final NodeGroup nodes = new NodeGroup();
WorldConfigNodes() {
}
public NodeGroup getNodes() {
return nodes;
}
private <N extends Node> N node(N node) {
nodes.add(node);
return node;
}
public final ConfigNode<Boolean> ADJUST_SPAWN = node(ConfigNode.builder("adjust-spawn", Boolean.class)
.defaultValue(false)
.name("adjust-spawn")
.build());
public final ConfigNode<String> ALIAS = node(ConfigNode.builder("alias", String.class)
.defaultValue("")
.name("alias")
.build());
public final ConfigNode<Boolean> ALLOW_FLIGHT = node(ConfigNode.builder("allow-flight", Boolean.class)
.defaultValue(false)
.name("allow-flight")
.build());
public final ConfigNode<Boolean> ALLOW_WEATHER = node(ConfigNode.builder("allow-weather", Boolean.class)
.defaultValue(true)
.name("allow-weather")
.build());
public final ConfigNode<Boolean> AUTO_HEAL = node(ConfigNode.builder("auto-heal", Boolean.class)
.defaultValue(true)
.name("auto-heal")
.build());
public final ConfigNode<Boolean> AUTO_LOAD = node(ConfigNode.builder("auto-load", Boolean.class)
.defaultValue(true)
.name("auto-load")
.build());
public final ConfigNode<Difficulty> DIFFICULTY = node(ConfigNode.builder("difficulty", Difficulty.class)
.defaultValue(Difficulty.NORMAL)
.name("difficulty")
.build());
public final ConfigNode<World.Environment> ENVIRONMENT = node(ConfigNode.builder("environment", World.Environment.class)
.defaultValue(World.Environment.NORMAL)
.name("environment")
.build());
public final ConfigNode<GameMode> GAMEMODE = node(ConfigNode.builder("gamemode", GameMode.class)
.defaultValue(GameMode.SURVIVAL)
.name("gamemode")
.build());
public final ConfigNode<String> GENERATOR = node(ConfigNode.builder("generator", String.class)
.defaultValue("")
.name("generator")
.build());
public final ConfigNode<Boolean> HIDDEN = node(ConfigNode.builder("hidden", Boolean.class)
.defaultValue(false)
.name("hidden")
.build());
public final ConfigNode<Boolean> HUNGER = node(ConfigNode.builder("hunger", Boolean.class)
.defaultValue(true)
.name("hunger")
.build());
public final ConfigNode<Boolean> KEEP_SPAWN_IN_MEMORY = node(ConfigNode.builder("keep-spawn-in-memory", Boolean.class)
.defaultValue(true)
.name("keep-spawn-in-memory")
.build());
public final ConfigNode<Integer> PLAYER_LIMIT = node(ConfigNode.builder("player-limit", Integer.class)
.defaultValue(-1)
.name("player-limit")
.build());
public final ConfigNode<AllowedPortalType> PORTAL_FORM = node(ConfigNode.builder("portal-form", AllowedPortalType.class)
.defaultValue(AllowedPortalType.ALL)
.name("portal-form")
.build());
public final ConfigNode<Boolean> PVP = node(ConfigNode.builder("pvp", Boolean.class)
.defaultValue(true)
.name("pvp")
.build());
public final ConfigNode<String> RESPAWN_WORLD = node(ConfigNode.builder("respawn-world", String.class)
.defaultValue("")
.name("respawn-world")
.build());
public final ConfigNode<Double> SCALE = node(ConfigNode.builder("scale", Double.class)
.defaultValue(1.0)
.name("scale")
.build());
public final ConfigNode<String> SEED = node(ConfigNode.builder("seed", String.class)
.defaultValue("")
.name("seed")
.build());
public final ConfigNode<List> WORLD_BLACKLIST = node(ConfigNode.builder("world-blacklist", List.class)
.defaultValue(new ArrayList<>())
.name("world-blacklist")
.build());
//todo: color and style
//todo: spawning
//todo: entryfee
//todo: spawnLocation
//todo: worldBlacklist
}

View File

@ -0,0 +1,55 @@
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();
}
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 void deleteWorldConfigSection(String worldName) {
worldConfig.set(worldName, null);
}
}

View File

@ -0,0 +1,69 @@
package org.mvplugins.multiverse.core.world
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigFile
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.mvplugins.multiverse.core.TestWithMockBukkit
import java.io.File
import java.nio.file.Path
import kotlin.io.path.absolutePathString
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertNotNull
class WorldConfigFileTest : TestWithMockBukkit() {
private lateinit var worldConfigFile : WorldsConfigFile
@BeforeTest
fun setUp() {
val defaultConfig = getResourceAsText("/default_worlds.yml")
assertNotNull(defaultConfig)
File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig)
worldConfigFile = WorldsConfigFile(multiverseCore)
worldConfigFile.load()
}
@Test
fun `World config is loaded`() {
assertTrue(worldConfigFile.isLoaded)
}
@Test
fun `Old world config is migrated`() {
// TODO: When logic is implemented, check that the old config is migrated
}
@Test
fun `Add a new world to config`() {
val worldConfig = WorldConfig(worldConfigFile.getWorldConfigSection("newworld"))
worldConfigFile.save()
compareConfigFile("worlds2.yml", "/newworld_worlds.yml")
}
@Test
fun `Updating existing world properties`() {
val worldConfig = WorldConfig(worldConfigFile.getWorldConfigSection("world"))
worldConfig.setProperty("adjust-spawn", true)
worldConfig.setProperty("alias", "newalias")
worldConfigFile.save()
compareConfigFile("worlds2.yml", "/properties_worlds.yml")
}
@Test
fun `Delete world section from config`() {
worldConfigFile.deleteWorldConfigSection("world")
worldConfigFile.save()
compareConfigFile("worlds2.yml", "/delete_worlds.yml")
}
private fun compareConfigFile(configPath: String, comparePath: String) {
// TODO: Map keys may not guaranteed order. Potentially look at Hamkrest and assertThat.
val config = multiverseCore.dataFolder.toPath().resolve(configPath).toFile().readText()
val configCompare = getResourceAsText(comparePath)
assertNotNull(configCompare)
assertEquals(configCompare, config)
}
}

View File

@ -0,0 +1,70 @@
package org.mvplugins.multiverse.core.world
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigFile
import org.mvplugins.multiverse.core.TestWithMockBukkit
import java.io.File
import java.nio.file.Path
import kotlin.io.path.absolutePathString
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class WorldConfigTest : TestWithMockBukkit() {
private lateinit var worldConfigFile : WorldsConfigFile
private lateinit var worldConfig : WorldConfig
@BeforeTest
fun setUp() {
val defaultConfig = getResourceAsText("/default_worlds.yml")
assertNotNull(defaultConfig)
File(Path.of(multiverseCore.dataFolder.absolutePath, "worlds2.yml").absolutePathString()).writeText(defaultConfig)
worldConfigFile = WorldsConfigFile(multiverseCore)
worldConfigFile.load()
worldConfig = WorldConfig(worldConfigFile.getWorldConfigSection("world"))
}
@Test
fun `Getting existing world property with getProperty returns expected value`() {
assertEquals("my world", worldConfig.getProperty("alias").get())
assertEquals(false, worldConfig.getProperty("hidden").get())
}
@Test
fun `Getting non-existing world property with getProperty returns null`() {
assertTrue(worldConfig.getProperty("invalid-property").isFailure)
assertTrue(worldConfig.getProperty("version").isFailure)
}
@Test
fun `Getting existing world property by getter returns expected value`() {
assertEquals("my world", worldConfig.alias)
assertEquals(false, worldConfig.isHidden)
}
@Test
fun `Updating an existing world property with setProperty reflects the changes in getProperty`() {
assertTrue(worldConfig.setProperty("adjust-spawn", true).isSuccess)
assertEquals(true, worldConfig.getProperty("adjust-spawn").get())
assertTrue(worldConfig.setProperty("alias", "abc").isSuccess)
assertEquals("abc", worldConfig.getProperty("alias").get())
assertTrue(worldConfig.setProperty("scale", 2.0).isSuccess)
assertEquals(2.0, worldConfig.getProperty("scale").get())
val blacklists = listOf("a", "b", "c")
assertTrue(worldConfig.setProperty("world-blacklist", blacklists).isSuccess)
assertEquals(blacklists, worldConfig.getProperty("world-blacklist").get())
}
@Test
fun `Updating a non-existing property with setProperty returns false`() {
assertTrue(worldConfig.setProperty("invalid-property", false).isFailure)
assertTrue(worldConfig.setProperty("version", 1.1).isFailure)
}
}

View File

@ -0,0 +1,29 @@
package org.mvplugins.multiverse.core.world
import com.onarandombox.MultiverseCore.worldnew.WorldManager
import org.mvplugins.multiverse.core.TestWithMockBukkit
import kotlin.test.BeforeTest
import kotlin.test.Test
class WorldManagerTest : TestWithMockBukkit() {
private lateinit var worldManager: WorldManager
@BeforeTest
fun setUp() {
worldManager = multiverseCore.getService(WorldManager::class.java).takeIf { it != null } ?: run {
throw IllegalStateException("WorldManager is not available as a service") }
}
@Test
fun `Add world`() {
worldManager.addWorld("world")
// TODO: When logic is implemented, check that the world is added
}
@Test
fun `Delete world`() {
worldManager.deleteWorld("world")
// TODO: When logic is implemented, check that the world is removed
}
}

View File

@ -0,0 +1,42 @@
world:
adjust-spawn: false
alias: my world
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NORMAL
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []
world_nether:
adjust-spawn: false
alias: ''
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NETHER
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []

View File

@ -0,0 +1,21 @@
world_nether:
adjust-spawn: false
alias: ''
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NETHER
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []

View File

@ -0,0 +1,63 @@
world:
adjust-spawn: false
alias: my world
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NORMAL
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []
world_nether:
adjust-spawn: false
alias: ''
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NETHER
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []
newworld:
adjust-spawn: false
alias: ''
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NORMAL
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []

View File

@ -0,0 +1,42 @@
world:
adjust-spawn: true
alias: newalias
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NORMAL
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []
world_nether:
adjust-spawn: false
alias: ''
allow-flight: false
allow-weather: true
auto-heal: true
auto-load: true
difficulty: NORMAL
environment: NETHER
gamemode: SURVIVAL
generator: ''
hidden: false
hunger: true
keep-spawn-in-memory: true
player-limit: -1
portal-form: ALL
pvp: true
respawn-world: ''
scale: 1.0
seed: ''
world-blacklist: []