From 155f32c00f2bb7fdc1bab2eabc81cbbd12d5be65 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Tue, 27 Apr 2021 23:44:24 +0800 Subject: [PATCH] Add ability to keep gamerules on world regen. --- .../MultiverseCore/MultiverseCore.java | 14 +++- .../onarandombox/MultiverseCore/api/Core.java | 30 ++++++-- .../MultiverseCore/api/MVWorldManager.java | 21 ++++- .../MultiverseCore/commands/RegenCommand.java | 15 ++-- .../MultiverseCore/utils/WorldManager.java | 77 ++++++++++++++++--- 5 files changed, 128 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java index 5ca3083b..bc39f40e 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java +++ b/src/main/java/com/onarandombox/MultiverseCore/MultiverseCore.java @@ -1131,12 +1131,22 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core { /** * {@inheritDoc} - * @deprecated This is deprecated! + * @deprecated This is deprecated! Do not use! */ @Override @Deprecated public Boolean regenWorld(String name, Boolean useNewSeed, Boolean randomSeed, String seed) { - return this.worldManager.regenWorld(name, useNewSeed, randomSeed, seed); + return this.worldManager.regenWorld(name, useNewSeed, randomSeed, seed, false); + } + + /** + * {@inheritDoc} + * @deprecated This is deprecated! Do not use! + */ + @Override + @Deprecated + public Boolean regenWorld(String name, Boolean useNewSeed, Boolean randomSeed, String seed, Boolean keepGameRules) { + return this.worldManager.regenWorld(name, useNewSeed, randomSeed, seed, keepGameRules); } /** diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java index 85ac5934..5f66cddb 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/Core.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/Core.java @@ -126,20 +126,38 @@ public interface Core { AnchorManager getAnchorManager(); /** - * Used by queued commands to regenerate a world on a delay. + * Previously used by queued commands to regenerate a world on a delay. + * Do not use api method for any other purpose. * - * @param name Name of the world to regenerate - * @param useNewSeed If a new seed should be used - * @param randomSeed IF the new seed should be random - * @param seed The seed of the world. + * @param name Name of the world to regenerate + * @param useNewSeed If a new seed should be used + * @param randomSeed If the new seed should be random + * @param seed The seed of the world. * * @return True if success, false if fail. * - * @deprecated Use {@link MVWorldManager#regenWorld(String, boolean, boolean, String)} instead. + * @deprecated Use {@link MVWorldManager#regenWorld(String, boolean, boolean, String, boolean)} instead. */ @Deprecated Boolean regenWorld(String name, Boolean useNewSeed, Boolean randomSeed, String seed); + /** + * Used by queued commands to regenerate a world on a delay. + * Do not use api method for any other purpose. + * + * @param name Name of the world to regenerate + * @param useNewSeed If a new seed should be used + * @param randomSeed If the new seed should be random + * @param seed The seed of the world. + * @param keepGameRules If GameRules should be kept on world regen. + * + * @return True if success, false if fail. + * + * @deprecated Use {@link MVWorldManager#regenWorld(String, boolean, boolean, String, boolean)} instead. + */ + @Deprecated + Boolean regenWorld(String name, Boolean useNewSeed, Boolean randomSeed, String seed, Boolean keepGameRules); + /** * Decrements the number of plugins that have specifically hooked into core. */ diff --git a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java index ce9b7263..599ce7cb 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/api/MVWorldManager.java @@ -313,15 +313,28 @@ public interface MVWorldManager { /** * Regenerates a world. * - * @param name Name of the world to regenerate - * @param useNewSeed If a new seed should be used - * @param randomSeed IF the new seed should be random - * @param seed The seed of the world. + * @param name Name of the world to regenerate + * @param useNewSeed If a new seed should be used + * @param randomSeed If the new seed should be random + * @param seed The seed of the world. * * @return True if success, false if fail. */ boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed); + /** + * Regenerates a world. + * + * @param name Name of the world to regenerate + * @param useNewSeed If a new seed should be used + * @param randomSeed If the new seed should be random + * @param seed The seed of the world. + * @param keepGameRules If GameRules should be kept on world regen. + * + * @return True if success, false if fail. + */ + boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed, boolean keepGameRules); + boolean isKeepingSpawnInMemory(World world); /** diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java index a7bee95e..4efe7ad5 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/RegenCommand.java @@ -9,12 +9,12 @@ package com.onarandombox.MultiverseCore.commands; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand; +import com.pneumaticraft.commandhandler.CommandHandler; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.permissions.PermissionDefault; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.List; /** @@ -25,8 +25,8 @@ public class RegenCommand extends MultiverseCommand { public RegenCommand(MultiverseCore plugin) { super(plugin); this.setName("Regenerates a World"); - this.setCommandUsage("/mv regen" + ChatColor.GREEN + " {WORLD}" + ChatColor.GOLD + " [-s [SEED]]"); - this.setArgRange(1, 3); + this.setCommandUsage("/mv regen" + ChatColor.GREEN + " {WORLD}" + ChatColor.GOLD + " [-s [SEED]] [--keep-gamerules]"); + this.setArgRange(1, 4); this.addKey("mvregen"); this.addKey("mv regen"); this.addCommandExample("You can use the -s with no args to get a new seed:"); @@ -43,10 +43,10 @@ public class RegenCommand extends MultiverseCommand { boolean useseed = (!(args.size() == 1)); boolean randomseed = (args.size() == 2 && args.get(1).equalsIgnoreCase("-s")); String seed = (args.size() == 3) ? args.get(2) : ""; - + boolean keepGamerules = CommandHandler.hasFlag("--keep-gamerules", args); this.plugin.getCommandQueueManager().addToQueue(new QueuedCommand( sender, - doWorldRegen(sender, worldName, useseed, randomseed, seed), + doWorldRegen(sender, worldName, useseed, randomseed, seed, keepGamerules), String.format("Are you sure you want to regen '%s'? You cannot undo this action.", worldName) )); } @@ -55,10 +55,11 @@ public class RegenCommand extends MultiverseCommand { @NotNull String worldName, boolean useSeed, boolean randomSeed, - @NotNull String seed) { + @NotNull String seed, + boolean keepGamerules) { return () -> { - if (this.plugin.getMVWorldManager().regenWorld(worldName, useSeed, randomSeed, seed)) { + if (this.plugin.getMVWorldManager().regenWorld(worldName, useSeed, randomSeed, seed, keepGamerules)) { sender.sendMessage(ChatColor.GREEN + "World Regenerated!"); return; } diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java index 2fc68747..0b2ab070 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java @@ -18,6 +18,7 @@ import com.onarandombox.MultiverseCore.api.SafeTTeleporter; import com.onarandombox.MultiverseCore.api.WorldPurger; import com.onarandombox.MultiverseCore.event.MVWorldDeleteEvent; import org.bukkit.Bukkit; +import org.bukkit.GameRule; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.World.Environment; @@ -896,12 +897,23 @@ public class WorldManager implements MVWorldManager { */ @Override public boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed) { + return regenWorld(name, useNewSeed, randomSeed, seed, false); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean regenWorld(String name, boolean useNewSeed, boolean randomSeed, String seed, boolean keepGameRules) { MultiverseWorld world = this.getMVWorld(name); - if (world == null) + if (world == null) { + Logging.warning("Unable to regen a world that does not exist!"); return false; + } List ps = world.getCBWorld().getPlayers(); + // Apply new seed if needed. if (useNewSeed) { long theSeed; @@ -917,19 +929,64 @@ public class WorldManager implements MVWorldManager { world.setSeed(theSeed); } + WorldType type = world.getWorldType(); - if (this.deleteWorld(name, false, false)) { - this.doLoad(name, true, type); - SafeTTeleporter teleporter = this.plugin.getSafeTTeleporter(); - Location newSpawn = world.getSpawnLocation(); - // Send all players that were in the old world, BACK to it! - for (Player p : ps) { - teleporter.safelyTeleport(null, p, newSpawn, true); + // Save current GameRules if needed. + Map, Object> gameRuleMap = null; + if (keepGameRules) { + gameRuleMap = new HashMap<>(GameRule.values().length); + World CBWorld = world.getCBWorld(); + for (GameRule gameRule : GameRule.values()) { + // Only save if not default value. + Object value = CBWorld.getGameRuleValue(gameRule); + if (value != CBWorld.getGameRuleDefault(gameRule)) { + gameRuleMap.put(gameRule, value); + } } - return true; } - return false; + + // Do the regen. + if (!this.deleteWorld(name, false, false)) { + Logging.severe("Unable to regen world as world cannot be deleted."); + return false; + } + if (!this.doLoad(name, true, type)) { + Logging.severe("Unable to regen world as world cannot be loaded."); + return false; + } + + // Get new MultiverseWorld reference. + world = this.getMVWorld(name); + + // Load back GameRules if needed. + if (keepGameRules) { + Logging.fine("Restoring previous world's GameRules..."); + World CBWorld = world.getCBWorld(); + for (Map.Entry, Object> gameRuleEntry : gameRuleMap.entrySet()) { + if (!setGameRuleValue(CBWorld, gameRuleEntry.getKey(), gameRuleEntry.getValue())) { + Logging.warning("Unable to set GameRule '%s' to '%s' on regen world.", + gameRuleEntry.getKey().getName(), gameRuleEntry.getValue()); + } + } + } + + // Send all players that were in the old world, BACK to it! + SafeTTeleporter teleporter = this.plugin.getSafeTTeleporter(); + Location newSpawn = world.getSpawnLocation(); + for (Player p : ps) { + teleporter.safelyTeleport(null, p, newSpawn, true); + } + + return true; + } + + private boolean setGameRuleValue(World world, GameRule gameRule, Object value) { + try { + return world.setGameRule(gameRule, (T) value); + } catch (Exception e) { + return false; + } } /**