diff --git a/Core/src/main/java/com/plotsquared/core/command/Setup.java b/Core/src/main/java/com/plotsquared/core/command/Setup.java index c01f604f9..97aa5350e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Setup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Setup.java @@ -29,6 +29,7 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.configuration.ConfigurationUtil; +import com.plotsquared.core.configuration.StaticCaption; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.player.PlotPlayer; @@ -38,6 +39,8 @@ import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.plot.message.PlotMessage; +import com.plotsquared.core.setup.SetupProcess; +import com.plotsquared.core.setup.SetupStep; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; @@ -91,6 +94,42 @@ public class Setup extends SubCommand { } @Override public boolean onCommand(PlotPlayer player, String[] args) { + SetupProcess process = player.getMeta("setup"); + if (process == null) { + if (args.length > 0) { + // TODO use old behaviour? + MainUtil.sendMessage(player, "Use /plot setup to start the setup"); + return true; + } + process = new SetupProcess(); + player.setMeta("setup", process); + SetupUtils.manager.updateGenerators(); + com.plotsquared.core.setup.SetupStep step = process.getCurrentStep(); + // TODO generalize? + step.announce(player); + displayGenerators(player); + return true; + } + if (args.length == 1) { + if ("back".equalsIgnoreCase(args[0])) { + process.back(); + process.getCurrentStep().announce(player); + } else if ("cancel".equalsIgnoreCase(args[0])) { + player.deleteMeta("setup"); + } else { + process.handleInput(player, args[0]); + } + return true; + } else { + process.getCurrentStep().announce(player); + // TODO return only + if (true) { + return true; + } + } + + + // going through setup SetupObject object = player.getMeta("setup"); if (object == null) { @@ -354,7 +393,7 @@ public class Setup extends SubCommand { } - private static final class StepPickGenerator extends SetupStep { + /*private static final class StepPickGenerator extends SetupStep { @Getter private String generator; @@ -481,6 +520,6 @@ public class Setup extends SubCommand { } } - } + }*/ } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 26515db06..778423635 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -319,6 +319,7 @@ public enum Captions implements Caption { REMOVED_GRANTED_PLOT("$2You used %s0 plot grant(s), you've got $1%s1 $2left", "Economy"), // // + SETUP_NOT_STARTED("$7No setup started. Use $2/plot setup $7to start a setup process.", "Setup"), SETUP_INIT("$1Usage: $2/plot setup ", "Setup"), SETUP_STEP("$3[$1Step %s0$3] $1%s1 $2- $1Expecting: $2%s2 $1Default: $2%s3", "Setup"), SETUP_INVALID_ARG("$2%s0 is not a valid argument for step %s1. To cancel setup use: $1/plot setup cancel", "Setup"), @@ -357,6 +358,11 @@ public enum Captions implements Caption { SETUP_AREA_MAX_PLOT_ID_ERROR("$7You must choose a valid maximum Plot Id!", "Setup"), SETUP_AREA_PLOT_ID_GREATER_THAN_MINIMUM("$7The max PlotId must be greater than the minimum!", "Setup"), // + // + PLOT_AREA_TYPE_NORMAL("Standard plot generation", "PlotAreaType"), + PLOT_AREA_TYPE_AUGMENTED("Plot generation with vanilla terrain", "PlotAreaType"), + PLOT_AREA_TYPE_PARTIAL("Vanilla with clusters of plots", "PlotAreaType"), + // // SCHEMATIC_TOO_LARGE("$2The plot is too large for this action!", "Schematics"), SCHEMATIC_MISSING_ARG("$2You need to specify an argument. Possible values: $1save$2, $1paste $2, $1exportall$2, $1list", "Schematics"), diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java index 0908b250c..34869d15f 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -4,13 +4,17 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Caption; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.ConfigurationNode; +import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; +import com.plotsquared.core.util.WorldUtil; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,7 +28,7 @@ import java.util.stream.Collectors; import static com.plotsquared.core.util.MainUtil.sendMessage; public enum CommonSetupSteps implements SetupStep { - GENERATOR(Captions.SETUP_INIT) { + CHOOSE_GENERATOR(Captions.SETUP_INIT) { @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { if (!SetupUtils.generators.containsKey(arg)) { @@ -38,18 +42,19 @@ public enum CommonSetupSteps implements SetupStep { } builder.generatorName(arg); sendMessage(plotPlayer, Captions.SETUP_WORLD_TYPE); - return CommonSetupSteps.PLOT_AREA_TYPE; // proceed with next step + return CommonSetupSteps.CHOOSE_PLOT_AREA_TYPE; // proceed with next step } - @Override public @NotNull Collection getSuggestions() { + @NotNull @Override public Collection getSuggestions() { return Collections.unmodifiableSet(SetupUtils.generators.keySet()); } - @Override @Nullable public String getDefaultValue() { + @Nullable @Override public String getDefaultValue() { return PlotSquared.imp().getPluginName(); } }, - PLOT_AREA_TYPE(PlotAreaType.class, Captions.SETUP_WORLD_TYPE) { + CHOOSE_PLOT_AREA_TYPE(PlotAreaType.class, Captions.SETUP_WORLD_TYPE) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { boolean withNormal = SetupUtils.generators.get(builder.generatorName()).isFull(); Optional plotAreaType = PlotAreaType.fromString(arg); @@ -78,7 +83,7 @@ public enum CommonSetupSteps implements SetupStep { if (!builder.settingsNodesWrapper().hasNext()) { // MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME); // object.setup_index = 0; TODO what did that do? - return WORLD_NAME; // skip + return CHOOSE_WORLD_NAME; // skip } SettingsNodeStep next = builder.settingsNodesWrapper().next(); ConfigurationNode step = next.getConfigurationNode(); @@ -105,7 +110,7 @@ public enum CommonSetupSteps implements SetupStep { return null; } else { // MainUtil.sendMessage(plotPlayer, Captions.SETUP_PARTIAL_AREA); - return TERRAIN_TYPE; + return CHOOSE_TERRAIN_TYPE; } } } @@ -114,19 +119,116 @@ public enum CommonSetupSteps implements SetupStep { return PlotAreaType.NORMAL.toString(); // TODO toLowerCase here? } }, - TERRAIN_TYPE(PlotAreaTerrainType.class, Captions.SETUP_PARTIAL_AREA) { - @Override - public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { - return null; + CHOOSE_AREA_ID(Captions.SETUP_AREA_NAME) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + if (!StringMan.isAlphanumericUnd(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_NON_ALPHANUMERICAL); + return this; + } + for (PlotArea area : PlotSquared.get().getPlotAreas()) { + if (area.getId() != null && area.getId().equalsIgnoreCase(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_INVALID_ID); + return this; + } + } + builder.areaName(argument); + return CHOOSE_MINIMUM_PLOT_ID; } - @Override - public @Nullable String getDefaultValue() { + @Nullable @Override public String getDefaultValue() { + return null; + } + }, + CHOOSE_MINIMUM_PLOT_ID(Captions.SETUP_AREA_MIN_PLOT_ID) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + try { + builder.minimumId(PlotId.fromString(argument)); + } catch (IllegalArgumentException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_MIN_PLOT_ID_ERROR); + return this; + } catch (IllegalStateException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_PLOT_ID_GREATER_THAN_MINIMUM); + return this; + } + return CHOOSE_MAXIMUM_PLOT_ID; + } + + @Override public String getDefaultValue() { + return "0;0"; + } + }, + CHOOSE_MAXIMUM_PLOT_ID(Captions.SETUP_AREA_MAX_PLOT_ID) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + try { + builder.maximumId(PlotId.fromString(argument)); + } catch (IllegalArgumentException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_MAX_PLOT_ID_ERROR); + return this; + } catch (IllegalStateException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_PLOT_ID_GREATER_THAN_MINIMUM); + return this; + } + return CHOOSE_TERRAIN_TYPE; + } + + @Override public String getDefaultValue() { + return "0;0"; + } + }, + CHOOSE_TERRAIN_TYPE(PlotAreaTerrainType.class, Captions.SETUP_PARTIAL_AREA) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + Optional optTerrain; + if (!(optTerrain = PlotAreaTerrainType.fromString(argument)) + .isPresent()) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_PARTIAL_AREA_ERROR, Captions.SETUP_PARTIAL_AREA); + return this; + } + builder.terrainType(optTerrain.get()); + if (builder.settingsNodesWrapper() == null) { + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + } + SettingsNodesWrapper wrapper = builder.settingsNodesWrapper(); + // TODO return CHOOSE_WORLD_NAME if !hasNext + return wrapper.hasNext() ? wrapper.next() : wrapper.getAfterwards(); + } + + @Nullable @Override public String getDefaultValue() { return PlotAreaTerrainType.NONE.toString(); // TODO toLowerCase here? } }, - WORLD_NAME(Captions.SETUP_WORLD_NAME) { + CHOOSE_WORLD_NAME(Captions.SETUP_WORLD_NAME) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + if (!isValidWorldName(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME_FORMAT + argument); + return this; + } + if (WorldUtil.IMP.isWorld(argument)) { + if (PlotSquared.get().hasPlotArea(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME_TAKEN); + return this; + } + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_APPLY_PLOTSQUARED); + } + builder.worldName(argument); + plotPlayer.deleteMeta("setup"); + String world; + if (builder.setupManager() == null) { + world = SetupUtils.manager.setupWorld(builder); + } else { + world = builder.setupManager().setupWorld(builder); + } + try { + plotPlayer.teleport(WorldUtil.IMP.getSpawn(world), TeleportCause.COMMAND); + } catch (Exception e) { + plotPlayer.sendMessage("&cAn error occurred. See console for more information"); + e.printStackTrace(); + } + sendMessage(plotPlayer, Captions.SETUP_FINISHED, builder.worldName()); return null; } @@ -143,21 +245,24 @@ public enum CommonSetupSteps implements SetupStep { * @param suggestions the input suggestions for this step * @param description the caption describing this step */ - CommonSetupSteps(@NotNull Collection suggestions, Caption description) { + CommonSetupSteps(@NotNull Collection suggestions, @NotNull Caption description) { this.suggestions = suggestions; this.description = description; } - CommonSetupSteps(Caption description) { + CommonSetupSteps(@NotNull Caption description) { this.description = description; this.suggestions = Collections.emptyList(); } - > CommonSetupSteps(Class argumentType, Caption description) { + > CommonSetupSteps(@NotNull Class argumentType, Caption description) { this(enumToStrings(argumentType), description); } - + @Override + public void announce(PlotPlayer plotPlayer) { + MainUtil.sendMessage(plotPlayer, this.description); + } private static > Collection enumToStrings(Class type) { return Arrays.stream(type.getEnumConstants()).map(e -> e.toString().toLowerCase()).collect(Collectors.toList()); @@ -166,11 +271,12 @@ public enum CommonSetupSteps implements SetupStep { private static SettingsNodesWrapper wrap(String plotManager) { return new SettingsNodesWrapper(SetupUtils.generators.get(plotManager).getPlotGenerator() .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) - .getSettingNodes()); + .getSettingNodes(), CHOOSE_WORLD_NAME); } - @Override - public void announce(PlotPlayer plotPlayer) { - MainUtil.sendMessage(plotPlayer, this.description); + private static boolean isValidWorldName(String s) { + return s.chars().allMatch((i) -> { + return i == 95 || i == 45 || i >= 97 && i <= 122 || i >= 48 && i <= 57 || i == 46; + }); } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java index fe4f755c1..956a5f847 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java +++ b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java @@ -3,6 +3,8 @@ package com.plotsquared.core.setup; import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotId; +import com.plotsquared.core.util.SetupUtils; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; @@ -15,6 +17,25 @@ public class PlotAreaBuilder { @Getter @Setter private PlotAreaTerrainType terrainType; @Getter @Setter private String worldName; @Getter @Setter private String areaName; + @Getter private PlotId minimumId; + @Getter private PlotId maximumId; @Getter @Setter private SettingsNodesWrapper settingsNodesWrapper; + @Getter @Setter private SetupUtils setupManager; + + public void minimumId(PlotId minimumId) { + if (this.maximumId != null + && (minimumId.getX() >= this.maximumId.getX() || minimumId.getY() >= this.maximumId.getY())) { + throw new IllegalStateException("minId >= maxId"); + } + this.minimumId = minimumId; + } + + public void maximumId(PlotId maximumId) { + if (this.minimumId != null + && (this.minimumId.getX() <= maximumId.getX() || this.minimumId.getY() <= maximumId.getY())) { + throw new IllegalStateException("maxId <= minId"); + } + this.maximumId = maximumId; + } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java index ffcb43cc5..b4f4a94c5 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -25,7 +25,7 @@ public class SettingsNodeStep implements SetupStep { if (this.configurationNode.isValid(argument)) { this.configurationNode.setValue(argument); } - return wrapper.next(); + return this.wrapper.hasNext() ? wrapper.next() : wrapper.getAfterwards(); } @NotNull @Override public Collection getSuggestions() { diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java index 896419ddb..a967d8ea1 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -1,13 +1,16 @@ package com.plotsquared.core.setup; import com.plotsquared.core.configuration.ConfigurationNode; +import lombok.Getter; public class SettingsNodesWrapper { - private final ConfigurationNode[] settingsNodes; + @Getter private final ConfigurationNode[] settingsNodes; + @Getter private final SetupStep afterwards; private int current; - public SettingsNodesWrapper(ConfigurationNode[] settingsNodes) { + public SettingsNodesWrapper(ConfigurationNode[] settingsNodes, SetupStep afterwards) { this.settingsNodes = settingsNodes; + this.afterwards = afterwards; this.current = 0; } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java index 721f427ec..0086189ce 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java @@ -2,18 +2,17 @@ package com.plotsquared.core.setup; import com.plotsquared.core.player.PlotPlayer; -import java.util.ArrayDeque; -import java.util.Queue; +import java.util.Stack; public class SetupProcess { private final PlotAreaBuilder builder; - private final Queue history; + private final Stack history; private SetupStep current; public SetupProcess() { this.builder = new PlotAreaBuilder(); - this.history = new ArrayDeque<>(); - this.current = CommonSetupSteps.GENERATOR; + this.history = new Stack<>(); + this.current = CommonSetupSteps.CHOOSE_GENERATOR; } public SetupStep getCurrentStep() { @@ -21,14 +20,19 @@ public class SetupProcess { } public void handleInput(PlotPlayer plotPlayer, String argument) { + SetupStep previous = this.current; // TODO null check? this.current = this.current.handleInput(plotPlayer, this.builder, argument); + // push previous step into history + if (this.current != previous && this.current != null) { + this.history.push(previous); + } } public void back() { if (!this.history.isEmpty()) { this.current.onBack(this.builder); - this.current = this.history.poll(); + this.current = this.history.pop(); } } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java index ef7908cf9..787c4ac03 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java @@ -16,7 +16,7 @@ public interface SetupStep { * @param argument the argument given as input * @return the next step if input was valid, this setup step otherwise */ - SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument); + SetupStep handleInput(final PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument); @NotNull Collection getSuggestions(); diff --git a/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java b/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java index 477c99715..73e6ccfaa 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java +++ b/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java @@ -28,6 +28,7 @@ package com.plotsquared.core.util; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.SetupObject; +import com.plotsquared.core.setup.PlotAreaBuilder; import java.util.HashMap; @@ -43,5 +44,7 @@ public abstract class SetupUtils { public abstract String setupWorld(final SetupObject object); + public abstract String setupWorld(final PlotAreaBuilder builder); + public abstract void unload(String world, boolean save); }