mirror of
https://github.com/Multiverse/Multiverse-Core.git
synced 2025-01-25 09:41:23 +01:00
Implement basic clone command
This commit is contained in:
parent
f056dcdbc9
commit
af2fc7c630
@ -4,15 +4,15 @@ import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
import co.aikar.commands.annotation.Conditions;
|
||||
import co.aikar.commands.annotation.Description;
|
||||
import co.aikar.commands.annotation.Single;
|
||||
import co.aikar.commands.annotation.Subcommand;
|
||||
import co.aikar.commands.annotation.Syntax;
|
||||
import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
import com.onarandombox.MultiverseCore.utils.MVCorei18n;
|
||||
import com.onarandombox.MultiverseCore.worldnew.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.WorldManager;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
@ -21,10 +21,10 @@ import org.jvnet.hk2.annotations.Service;
|
||||
@CommandAlias("mv")
|
||||
public class CloneCommand extends MultiverseCommand {
|
||||
|
||||
private final MVWorldManager worldManager;
|
||||
private final WorldManager worldManager;
|
||||
|
||||
@Inject
|
||||
public CloneCommand(@NotNull MVCommandManager commandManager, @NotNull MVWorldManager worldManager) {
|
||||
public CloneCommand(@NotNull MVCommandManager commandManager, @NotNull WorldManager worldManager) {
|
||||
super(commandManager);
|
||||
this.worldManager = worldManager;
|
||||
}
|
||||
@ -36,26 +36,17 @@ public class CloneCommand extends MultiverseCommand {
|
||||
@Description("{@@mv-core.clone.description}")
|
||||
public void onCloneCommand(CommandIssuer issuer,
|
||||
|
||||
@Conditions("worldname:scope=both")
|
||||
@Syntax("<world>")
|
||||
@Description("{@@mv-core.clone.world.description}")
|
||||
String worldName,
|
||||
MVWorld world,
|
||||
|
||||
@Single
|
||||
@Conditions("worldname:scope=new")
|
||||
@Syntax("<new world name>")
|
||||
@Description("{@@mv-core.clone.newWorld.description}")
|
||||
String newWorldName
|
||||
) {
|
||||
issuer.sendInfo(MVCorei18n.CLONE_CLONING,
|
||||
"{world}", worldName,
|
||||
"{newWorld}", newWorldName);
|
||||
|
||||
if (!this.worldManager.cloneWorld(worldName, newWorldName)) {
|
||||
issuer.sendError(MVCorei18n.CLONE_FAILED);
|
||||
return;
|
||||
}
|
||||
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS,
|
||||
"{world}", newWorldName);
|
||||
issuer.sendInfo(MVCorei18n.CLONE_CLONING, "{world}", world.getName(), "{newWorld}", newWorldName);
|
||||
worldManager.cloneWorld(world, newWorldName);
|
||||
issuer.sendInfo(MVCorei18n.CLONE_SUCCESS, "{world}", newWorldName);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class OfflineWorld {
|
||||
@ -32,6 +33,10 @@ public class OfflineWorld {
|
||||
return worldConfig.hasMVWorld();
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames() {
|
||||
return worldConfig.getConfigurablePropertyNames();
|
||||
}
|
||||
|
||||
public Try<Object> getProperty(String name) {
|
||||
return worldConfig.getProperty(name);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import com.onarandombox.MultiverseCore.utils.result.Result;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.WorldConfig;
|
||||
import com.onarandombox.MultiverseCore.worldnew.config.WorldsConfigManager;
|
||||
import com.onarandombox.MultiverseCore.worldnew.generators.GeneratorProvider;
|
||||
import com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.GameRulesStore;
|
||||
import com.onarandombox.MultiverseCore.worldnew.helpers.FilesManipulator;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.CreateWorldOptions;
|
||||
import com.onarandombox.MultiverseCore.worldnew.options.ImportWorldOptions;
|
||||
@ -39,12 +40,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.onarandombox.MultiverseCore.utils.message.MessageReplacement.replace;
|
||||
import static com.onarandombox.MultiverseCore.worldnew.helpers.DataStore.*;
|
||||
|
||||
/**
|
||||
* This manager contains all the world managing functions that your heart desires!
|
||||
*/
|
||||
@Service
|
||||
public class WorldManager {
|
||||
private static final List<String> CLONE_IGNORE_FILES = Arrays.asList("uid.dat", "session.dat");
|
||||
|
||||
private final Map<String, OfflineWorld> offlineWorldsMap;
|
||||
private final Map<String, MVWorld> worldsMap;
|
||||
@ -132,9 +135,7 @@ public class WorldManager {
|
||||
if (isMVWorld(world) || !world.getAutoLoad()) {
|
||||
return;
|
||||
}
|
||||
loadWorld(world).onFailure((failure) -> {
|
||||
Logging.severe("Failed to load world %s: %s", world.getName(), failure);
|
||||
});
|
||||
loadWorld(world).onFailure((failure) -> Logging.severe("Failed to load world %s: %s", world.getName(), failure));
|
||||
});
|
||||
}
|
||||
|
||||
@ -461,6 +462,52 @@ public class WorldManager {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones an existing multiverse world.
|
||||
*
|
||||
* @param world The multiverse world to clone.
|
||||
* @param newWorldName The name of the new world.
|
||||
*/
|
||||
public void cloneWorld(@NotNull MVWorld world, @NotNull String newWorldName) {
|
||||
if (!worldNameChecker.isValidWorldName(newWorldName)) {
|
||||
Logging.severe("Invalid world name: " + newWorldName);
|
||||
return;
|
||||
}
|
||||
if (isOfflineWorld(newWorldName)) {
|
||||
Logging.severe("World already exist offline: " + newWorldName);
|
||||
return;
|
||||
}
|
||||
if (isMVWorld(newWorldName)) {
|
||||
Logging.severe("World already loaded: " + newWorldName);
|
||||
return;
|
||||
}
|
||||
if (worldNameChecker.isValidWorldFolder(newWorldName)) {
|
||||
Logging.severe("World folder already exist: " + newWorldName);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Configure option on whether to copy these
|
||||
GameRulesStore gameRulesStore = GameRulesStore.createAndCopyFrom(world);
|
||||
WorldConfigStore worldConfigStore = WorldConfigStore.createAndCopyFrom(world);
|
||||
|
||||
File worldFolder = world.getBukkitWorld().map(World::getWorldFolder).getOrNull(); // TODO: Check null?
|
||||
File newWorldFolder = new File(Bukkit.getWorldContainer(), newWorldName);
|
||||
FileUtils.copyFolder(worldFolder, newWorldFolder, CLONE_IGNORE_FILES);
|
||||
|
||||
// TODO: Error handling
|
||||
importWorld(ImportWorldOptions.worldName(newWorldName)
|
||||
.environment(world.getEnvironment())
|
||||
.generator(world.getGenerator())
|
||||
);
|
||||
|
||||
// TODO: Error handling
|
||||
getMVWorld(newWorldName).peek(newWorld -> {
|
||||
gameRulesStore.pasteTo(newWorld);
|
||||
worldConfigStore.pasteTo(newWorld);
|
||||
saveWorldsConfig();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bukkit world.
|
||||
*
|
||||
|
@ -2,6 +2,7 @@ package com.onarandombox.MultiverseCore.worldnew.config;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.handle.ConfigurationSectionHandle;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.world.configuration.AllowedPortalType;
|
||||
import com.onarandombox.MultiverseCore.worldnew.MVWorld;
|
||||
import io.vavr.control.Try;
|
||||
@ -14,6 +15,7 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class WorldConfig {
|
||||
@ -41,6 +43,10 @@ public class WorldConfig {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
public Collection<String> getConfigurablePropertyNames() {
|
||||
return configNodes.getNodes().getNames();
|
||||
}
|
||||
|
||||
public Try<Object> getProperty(String name) {
|
||||
return configHandle.get(name);
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
package com.onarandombox.MultiverseCore.worldnew.helpers;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.worldnew.MVWorld;
|
||||
import com.onarandombox.MultiverseCore.worldnew.OfflineWorld;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public interface DataStore<T> {
|
||||
DataStore<T> copyFrom(T object);
|
||||
DataStore<T> pasteTo(T object);
|
||||
|
||||
class GameRulesStore implements DataStore<MVWorld> {
|
||||
public static GameRulesStore createAndCopyFrom(MVWorld world) {
|
||||
return new GameRulesStore().copyFrom(world);
|
||||
}
|
||||
|
||||
private Map<GameRule<?>, Object> gameRuleMap;
|
||||
|
||||
public GameRulesStore copyFrom(MVWorld world) {
|
||||
this.gameRuleMap = new HashMap<>();
|
||||
world.getBukkitWorld().peek(bukkitWorld -> {
|
||||
Arrays.stream(GameRule.values()).forEach(gameRule -> {
|
||||
Object value = bukkitWorld.getGameRuleValue(gameRule);
|
||||
gameRuleMap.put(gameRule, value);
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameRulesStore pasteTo(MVWorld world) {
|
||||
if (gameRuleMap == null) {
|
||||
return this;
|
||||
}
|
||||
world.getBukkitWorld().peek(bukkitWorld -> {
|
||||
gameRuleMap.forEach((gameRule, value) -> {
|
||||
if (!setGameRuleValue(bukkitWorld, gameRule, value)) {
|
||||
Logging.warning("Failed to set game rule " + gameRule.getName() + " to " + value);
|
||||
}
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
private <T> boolean setGameRuleValue(World world, GameRule<T> gameRule, Object value) {
|
||||
try {
|
||||
return world.setGameRule(gameRule, (T) value);
|
||||
} catch (Exception e) {
|
||||
Logging.fine(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WorldConfigStore implements DataStore<OfflineWorld> {
|
||||
public static WorldConfigStore createAndCopyFrom(OfflineWorld world) {
|
||||
return new WorldConfigStore().copyFrom(world);
|
||||
}
|
||||
|
||||
private Map<String, Object> configMap;
|
||||
|
||||
@Override
|
||||
public WorldConfigStore copyFrom(OfflineWorld world) {
|
||||
this.configMap = new HashMap<>();
|
||||
world.getConfigurablePropertyNames().forEach(name -> {
|
||||
world.getProperty(name).peek(value -> configMap.put(name, value)).onFailure(e -> {
|
||||
Logging.warning("Failed to get property " + name + " from world " + world.getName() + ": " + e.getMessage());
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldConfigStore pasteTo(OfflineWorld world) {
|
||||
if (configMap == null) {
|
||||
return this;
|
||||
}
|
||||
configMap.forEach((name, value) -> {
|
||||
world.setProperty(name, value).onFailure(e -> {
|
||||
Logging.warning("Failed to set property %s to %s for world %s: %s",
|
||||
name, value, world.getName(), e.getMessage());
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user