diff --git a/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java b/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java index c936245b3..cd3d524a8 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java @@ -28,9 +28,11 @@ package com.plotsquared.core.configuration; import com.plotsquared.core.plot.BlockBucket; import com.plotsquared.core.util.StringMan; import com.sk89q.worldedit.world.block.BlockState; +import lombok.Getter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -38,19 +40,26 @@ import java.util.List; */ public class ConfigurationNode { - private final String constant; + @Getter private final String constant; private final Object defaultValue; - private final String description; + @Getter private final String description; private final ConfigurationUtil.SettingValue type; + @Getter private final Collection suggestions; private Object value; public ConfigurationNode(String constant, Object defaultValue, String description, ConfigurationUtil.SettingValue type) { + this(constant, defaultValue, description, type, new ArrayList<>()); + } + + public ConfigurationNode(String constant, Object defaultValue, String description, + ConfigurationUtil.SettingValue type, Collection suggestions) { this.constant = constant; this.defaultValue = defaultValue; this.description = description; this.value = defaultValue; this.type = type; + this.suggestions = suggestions; } public ConfigurationUtil.SettingValue getType() { @@ -97,18 +106,10 @@ public class ConfigurationNode { return this.value; } - public String getConstant() { - return this.constant; - } - public Object getDefaultValue() { if (this.defaultValue instanceof Object[]) { return StringMan.join((Object[]) this.defaultValue, ","); } return this.defaultValue; } - - public String getDescription() { - return this.description; - } } diff --git a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java index 915f22940..b2e1278ab 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java +++ b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java @@ -30,6 +30,7 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.queue.ScopedLocalBlockQueue; +import com.plotsquared.core.setup.SetupProcess; /** * This class allows for implementation independent world generation. @@ -74,9 +75,18 @@ public abstract class IndependentPlotGenerator { * * @param setup */ + @Deprecated public void processSetup(SetupObject setup) { } + /** + * If any additional setup options need to be changed before world creation. + * - e.g. If setup doesn't support some standard options + * + * @param setupProcess the setup process to modify + */ + public void processSetup(SetupProcess setupProcess) { } + /** * It is preferred for the PlotArea object to do most of the initialization necessary. * diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java b/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java index 60c9fc7f0..9ed4cb0f0 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java @@ -25,6 +25,10 @@ */ package com.plotsquared.core.plot; +import com.plotsquared.core.configuration.Caption; +import com.plotsquared.core.configuration.Captions; +import lombok.Getter; + import java.util.Map; import java.util.Optional; import java.util.function.Function; @@ -32,11 +36,23 @@ import java.util.stream.Collectors; import java.util.stream.Stream; public enum PlotAreaType { - NORMAL, AUGMENTED, PARTIAL; + NORMAL(Captions.PLOT_AREA_TYPE_NORMAL), + AUGMENTED(Captions.PLOT_AREA_TYPE_AUGMENTED), + PARTIAL(Captions.PLOT_AREA_TYPE_PARTIAL); + + @Getter private final Caption description; private static final Map types = Stream.of(values()) .collect(Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity())); + PlotAreaType(Caption description) { + this.description = description; + } + + public static Map getDescriptionMap() { + return Stream.of(values()).collect(Collectors.toMap(e -> e, PlotAreaType::getDescription)); + } + public static Optional fromString(String typeName) { return Optional.ofNullable(types.get(typeName.toLowerCase())); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java b/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java index 8ac5d5cb0..bfca8fe5e 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java +++ b/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java @@ -28,6 +28,10 @@ package com.plotsquared.core.plot; import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.util.SetupUtils; +/** + * @deprecated will be removed in v6 + */ +@Deprecated public class SetupObject { /** diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java new file mode 100644 index 000000000..0908b250c --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -0,0 +1,176 @@ +package com.plotsquared.core.setup; + +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.generator.GeneratorWrapper; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.PlotAreaTerrainType; +import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.SetupUtils; +import com.plotsquared.core.util.StringMan; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.plotsquared.core.util.MainUtil.sendMessage; + +public enum CommonSetupSteps implements SetupStep { + GENERATOR(Captions.SETUP_INIT) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { + if (!SetupUtils.generators.containsKey(arg)) { + String prefix = "\n&8 - &7"; + sendMessage(plotPlayer, Captions.SETUP_WORLD_GENERATOR_ERROR + prefix + StringMan + .join(SetupUtils.generators.keySet(), prefix) + .replaceAll(PlotSquared.imp().getPluginName(), + "&2" + PlotSquared.imp().getPluginName())); + sendMessage(plotPlayer, Captions.SETUP_INIT); + return this; // invalid input -> same setup step + } + builder.generatorName(arg); + sendMessage(plotPlayer, Captions.SETUP_WORLD_TYPE); + return CommonSetupSteps.PLOT_AREA_TYPE; // proceed with next step + } + + @Override public @NotNull Collection getSuggestions() { + return Collections.unmodifiableSet(SetupUtils.generators.keySet()); + } + + @Override @Nullable public String getDefaultValue() { + return PlotSquared.imp().getPluginName(); + } + }, + 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); + if (!plotAreaType.isPresent()) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_TYPE_ERROR); + PlotAreaType.getDescriptionMap().forEach((type, caption) -> { + if (!withNormal && type == PlotAreaType.NORMAL) { + return; // skip + } + String color = type == PlotAreaType.NORMAL ? "&2" : "&7"; + MainUtil.sendMessage(plotPlayer, "&8 - " + color + type + + " &8-&7 " + caption.getTranslated()); + }); + return this; + } + builder.plotAreaType(plotAreaType.get()); + // object.type = plotAreaType.get(); + GeneratorWrapper gen = SetupUtils.generators.get(builder.generatorName()); + if (builder.plotAreaType() == PlotAreaType.NORMAL) { + if (builder.settingsNodesWrapper() == null) { + builder.plotManager(builder.generatorName()); + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() + // .processSetup(process); + } + if (!builder.settingsNodesWrapper().hasNext()) { + // MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME); + // object.setup_index = 0; TODO what did that do? + return WORLD_NAME; // skip + } + SettingsNodeStep next = builder.settingsNodesWrapper().next(); + ConfigurationNode step = next.getConfigurationNode(); + sendMessage(plotPlayer, Captions.SETUP_STEP, next.getId() + 1, + step.getDescription(), step.getType().getType(), + String.valueOf(step.getDefaultValue())); + return next; + } else { + if (gen.isFull()) { + builder.plotManager(builder.generatorName()); + builder.generatorName(null); + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() + // .processSetup(process); + } else { + builder.plotManager(PlotSquared.imp().getPluginName()); + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WRONG_GENERATOR); + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + // TODO why is processSetup not called here? + } + if (builder.plotAreaType() == PlotAreaType.PARTIAL) { + // MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_NAME); + // TODO return step area id + return null; + } else { + // MainUtil.sendMessage(plotPlayer, Captions.SETUP_PARTIAL_AREA); + return TERRAIN_TYPE; + } + } + } + + @Nullable @Override public String getDefaultValue() { + 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; + } + + @Override + public @Nullable String getDefaultValue() { + return PlotAreaTerrainType.NONE.toString(); // TODO toLowerCase here? + } + }, + WORLD_NAME(Captions.SETUP_WORLD_NAME) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + return null; + } + + @Nullable @Override public String getDefaultValue() { + return null; + } + }; + + @Getter @NotNull private final Collection suggestions; + private final Caption description; + + /** + * + * @param suggestions the input suggestions for this step + * @param description the caption describing this step + */ + CommonSetupSteps(@NotNull Collection suggestions, Caption description) { + this.suggestions = suggestions; + this.description = description; + } + + CommonSetupSteps(Caption description) { + this.description = description; + this.suggestions = Collections.emptyList(); + } + + > CommonSetupSteps(Class argumentType, Caption description) { + this(enumToStrings(argumentType), description); + } + + + + private static > Collection enumToStrings(Class type) { + return Arrays.stream(type.getEnumConstants()).map(e -> e.toString().toLowerCase()).collect(Collectors.toList()); + } + + private static SettingsNodesWrapper wrap(String plotManager) { + return new SettingsNodesWrapper(SetupUtils.generators.get(plotManager).getPlotGenerator() + .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) + .getSettingNodes()); + } + + @Override + public void announce(PlotPlayer plotPlayer) { + MainUtil.sendMessage(plotPlayer, this.description); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java new file mode 100644 index 000000000..fe4f755c1 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java @@ -0,0 +1,20 @@ +package com.plotsquared.core.setup; + + +import com.plotsquared.core.plot.PlotAreaTerrainType; +import com.plotsquared.core.plot.PlotAreaType; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Accessors(fluent = true) +public class PlotAreaBuilder { + @Getter @Setter private String generatorName; + @Getter @Setter private String plotManager; + @Getter @Setter private PlotAreaType plotAreaType; + @Getter @Setter private PlotAreaTerrainType terrainType; + @Getter @Setter private String worldName; + @Getter @Setter private String areaName; + @Getter @Setter private SettingsNodesWrapper settingsNodesWrapper; + +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java new file mode 100644 index 000000000..ffcb43cc5 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -0,0 +1,45 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.configuration.Captions; +import com.plotsquared.core.configuration.ConfigurationNode; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.util.MainUtil; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class SettingsNodeStep implements SetupStep { + @Getter private final ConfigurationNode configurationNode; + @Getter private final int id; + private final SettingsNodesWrapper wrapper; + + public SettingsNodeStep(ConfigurationNode configurationNode, int id, SettingsNodesWrapper wrapper) { + this.configurationNode = configurationNode; + this.id = id; + this.wrapper = wrapper; + } + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + if (this.configurationNode.isValid(argument)) { + this.configurationNode.setValue(argument); + } + return wrapper.next(); + } + + @NotNull @Override public Collection getSuggestions() { + return this.configurationNode.getSuggestions(); + } + + @Nullable @Override public String getDefaultValue() { + return String.valueOf(this.configurationNode.getDefaultValue()); + } + + @Override + public void announce(PlotPlayer plotPlayer) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_STEP, this.getId() + 1, + this.configurationNode.getDescription(), this.configurationNode.getType().getType(), + String.valueOf(this.configurationNode.getDefaultValue())); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java new file mode 100644 index 000000000..896419ddb --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -0,0 +1,27 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.configuration.ConfigurationNode; + +public class SettingsNodesWrapper { + private final ConfigurationNode[] settingsNodes; + private int current; + + public SettingsNodesWrapper(ConfigurationNode[] settingsNodes) { + this.settingsNodes = settingsNodes; + this.current = 0; + } + + + public SettingsNodeStep next() { + if (this.settingsNodes.length <= this.current) { + throw new IllegalStateException("No step left"); + } else { + int temp = this.current; + this.current++; + return new SettingsNodeStep(this.settingsNodes[temp], temp, this); + } + } + public boolean hasNext() { + return this.current < this.settingsNodes.length; + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java new file mode 100644 index 000000000..721f427ec --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java @@ -0,0 +1,34 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.player.PlotPlayer; + +import java.util.ArrayDeque; +import java.util.Queue; + +public class SetupProcess { + private final PlotAreaBuilder builder; + private final Queue history; + private SetupStep current; + + public SetupProcess() { + this.builder = new PlotAreaBuilder(); + this.history = new ArrayDeque<>(); + this.current = CommonSetupSteps.GENERATOR; + } + + public SetupStep getCurrentStep() { + return this.current; + } + + public void handleInput(PlotPlayer plotPlayer, String argument) { + // TODO null check? + this.current = this.current.handleInput(plotPlayer, this.builder, argument); + } + + public void back() { + if (!this.history.isEmpty()) { + this.current.onBack(this.builder); + this.current = this.history.poll(); + } + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java new file mode 100644 index 000000000..ef7908cf9 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java @@ -0,0 +1,40 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.player.PlotPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public interface SetupStep { + + /** + * Handles the input for this setup step. + * + * @param plotPlayer the plot player executing the command + * @param builder the plot area builder to work on + * @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); + + @NotNull Collection getSuggestions(); + + @Nullable String getDefaultValue(); + + /** + * Announces this step to the player. + * + * @param plotPlayer the player to announce this step to. + */ + void announce(PlotPlayer plotPlayer); + + /** + * This method is called when the SetupProcess reverts to a previous step. + * + * @param builder the builder associated with the setup process. + */ + default void onBack(PlotAreaBuilder builder) { + + } +}