001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.setup; 020 021import com.plotsquared.core.PlotSquared; 022import com.plotsquared.core.configuration.caption.Caption; 023import com.plotsquared.core.configuration.caption.TranslatableCaption; 024import com.plotsquared.core.events.TeleportCause; 025import com.plotsquared.core.generator.GeneratorWrapper; 026import com.plotsquared.core.player.MetaDataAccess; 027import com.plotsquared.core.player.PlayerMetaDataKeys; 028import com.plotsquared.core.player.PlotPlayer; 029import com.plotsquared.core.plot.PlotArea; 030import com.plotsquared.core.plot.PlotAreaTerrainType; 031import com.plotsquared.core.plot.PlotAreaType; 032import com.plotsquared.core.plot.PlotId; 033import com.plotsquared.core.util.SetupUtils; 034import com.plotsquared.core.util.StringMan; 035import net.kyori.adventure.text.Component; 036import net.kyori.adventure.text.minimessage.tag.Tag; 037import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 038import org.checkerframework.checker.nullness.qual.NonNull; 039import org.checkerframework.checker.nullness.qual.Nullable; 040 041import java.util.Arrays; 042import java.util.Collection; 043import java.util.Collections; 044import java.util.Optional; 045import java.util.stream.Collectors; 046 047public enum CommonSetupSteps implements SetupStep { 048 CHOOSE_GENERATOR(TranslatableCaption.of("setup.setup_init")) { 049 @Override 050 public SetupStep handleInput(PlotPlayer<?> plotPlayer, PlotAreaBuilder builder, String arg) { 051 if (!SetupUtils.generators.containsKey(arg)) { 052 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_world_generator_error")); 053 return this; // invalid input -> same setup step 054 } 055 builder.generatorName(arg); 056 return CommonSetupSteps.CHOOSE_PLOT_AREA_TYPE; // proceed with next step 057 } 058 059 060 @Override 061 public Collection<String> getSuggestions() { 062 return Collections.unmodifiableSet(SetupUtils.generators.keySet()); 063 } 064 065 @Nullable 066 @Override 067 public String getDefaultValue() { 068 return PlotSquared.platform().pluginName(); 069 } 070 }, 071 CHOOSE_PLOT_AREA_TYPE(PlotAreaType.class, TranslatableCaption.of("setup.setup_world_type")) { 072 @Override 073 public SetupStep handleInput(PlotPlayer<?> plotPlayer, PlotAreaBuilder builder, String arg) { 074 Optional<PlotAreaType> plotAreaType = PlotAreaType.fromString(arg); 075 if (!plotAreaType.isPresent()) { 076 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_world_type_error")); 077 return this; 078 } 079 builder.plotAreaType(plotAreaType.get()); 080 GeneratorWrapper<?> gen = SetupUtils.generators.get(builder.generatorName()); 081 if (builder.plotAreaType() == PlotAreaType.NORMAL) { 082 if (builder.settingsNodesWrapper() == null) { 083 builder.plotManager(builder.generatorName()); 084 builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); 085 SetupUtils.generators.get(builder.plotManager()).getPlotGenerator() 086 .processAreaSetup(builder); 087 } 088 return builder.settingsNodesWrapper().getFirstStep(); 089 } else { 090 if (gen.isFull()) { 091 builder.plotManager(builder.generatorName()); 092 builder.generatorName(null); 093 builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); 094 SetupUtils.generators.get(builder.plotManager()).getPlotGenerator() 095 .processAreaSetup(builder); 096 } else { 097 builder.plotManager(PlotSquared.platform().pluginName()); 098 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_world_generator_error")); 099 builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); 100 // TODO why is processSetup not called here? 101 } 102 if (builder.plotAreaType() == PlotAreaType.PARTIAL) { 103 return CHOOSE_AREA_ID; 104 } else { 105 return CHOOSE_TERRAIN_TYPE; 106 } 107 } 108 } 109 110 @Nullable 111 @Override 112 public String getDefaultValue() { 113 return PlotAreaType.NORMAL.toString(); 114 } 115 }, 116 CHOOSE_AREA_ID(TranslatableCaption.of("setup.setup_area_name")) { 117 @Override 118 public SetupStep handleInput(PlotPlayer<?> plotPlayer, PlotAreaBuilder builder, String argument) { 119 if (!StringMan.isAlphanumericUnd(argument)) { 120 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_area_non_alphanumerical")); 121 return this; 122 } 123 for (PlotArea area : PlotSquared.get().getPlotAreaManager().getAllPlotAreas()) { 124 if (area.getId() != null && area.getId().equalsIgnoreCase(argument)) { 125 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_area_invalid_id")); 126 return this; 127 } 128 } 129 builder.areaName(argument); 130 return CHOOSE_MINIMUM_PLOT_ID; 131 } 132 133 @Nullable 134 @Override 135 public String getDefaultValue() { 136 return null; 137 } 138 }, 139 CHOOSE_MINIMUM_PLOT_ID(TranslatableCaption.of("setup.setup_area_min_plot_id")) { 140 @Override 141 public SetupStep handleInput(PlotPlayer<?> plotPlayer, PlotAreaBuilder builder, String argument) { 142 try { 143 builder.minimumId(PlotId.fromString(argument)); 144 } catch (IllegalArgumentException ignored) { 145 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_area_min_plot_id_error")); 146 return this; 147 } catch (IllegalStateException ignored) { 148 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_area_plot_id_greater_than_minimum")); 149 return this; 150 } 151 return CHOOSE_MAXIMUM_PLOT_ID; 152 } 153 154 @Override 155 public String getDefaultValue() { 156 return "0;0"; 157 } 158 }, 159 CHOOSE_MAXIMUM_PLOT_ID(TranslatableCaption.of("setup.setup_area_max_plot_id")) { 160 @Override 161 public SetupStep handleInput(PlotPlayer<?> plotPlayer, PlotAreaBuilder builder, String argument) { 162 try { 163 builder.maximumId(PlotId.fromString(argument)); 164 } catch (IllegalArgumentException ignored) { 165 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_area_max_plot_id_error")); 166 return this; 167 } catch (IllegalStateException ignored) { 168 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_area_plot_id_greater_than_minimum")); 169 return this; 170 } 171 return CHOOSE_TERRAIN_TYPE; 172 } 173 174 @Override 175 public String getDefaultValue() { 176 return "0;0"; 177 } 178 }, 179 CHOOSE_TERRAIN_TYPE(PlotAreaTerrainType.class, TranslatableCaption.of("setup.setup_partial_area")) { 180 @Override 181 public SetupStep handleInput(PlotPlayer<?> plotPlayer, PlotAreaBuilder builder, String argument) { 182 Optional<PlotAreaTerrainType> optTerrain; 183 if (!(optTerrain = PlotAreaTerrainType.fromString(argument)) 184 .isPresent()) { 185 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_partial_area_error")); 186 return this; 187 } 188 builder.terrainType(optTerrain.get()); 189 if (builder.settingsNodesWrapper() == null) { 190 builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); 191 } 192 SettingsNodesWrapper wrapper = builder.settingsNodesWrapper(); 193 return wrapper.getFirstStep(); 194 } 195 196 @Nullable 197 @Override 198 public String getDefaultValue() { 199 return PlotAreaTerrainType.NONE.toString(); 200 } 201 }, 202 CHOOSE_WORLD_NAME(TranslatableCaption.of("setup.setup_world_name")) { 203 @Override 204 public SetupStep handleInput(PlotPlayer<?> plotPlayer, PlotAreaBuilder builder, String argument) { 205 if (!isValidWorldName(argument)) { 206 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_world_name_format")); 207 return this; 208 } 209 if (PlotSquared.platform().worldUtil().isWorld(argument)) { 210 if (PlotSquared.get().getPlotAreaManager().hasPlotArea(argument)) { 211 plotPlayer.sendMessage( 212 TranslatableCaption.of("setup.setup_world_taken"), 213 TagResolver.resolver("value", Tag.inserting(Component.text(argument))) 214 ); 215 return this; 216 } 217 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_world_apply_plotsquared")); 218 } 219 builder.worldName(argument); 220 try (final MetaDataAccess<SetupProcess> setupAccess = plotPlayer.accessTemporaryMetaData( 221 PlayerMetaDataKeys.TEMPORARY_SETUP)) { 222 setupAccess.remove(); 223 } 224 String world; 225 if (builder.setupManager() == null) { 226 world = PlotSquared.platform().injector().getInstance(SetupUtils.class).setupWorld(builder); 227 } else { 228 world = builder.setupManager().setupWorld(builder); 229 } 230 try { 231 plotPlayer.teleport(PlotSquared.platform().worldUtil().getSpawn(world), TeleportCause.COMMAND_SETUP); 232 } catch (Exception e) { 233 plotPlayer.sendMessage(TranslatableCaption.of("errors.error_console")); 234 e.printStackTrace(); 235 } 236 plotPlayer.sendMessage(TranslatableCaption.of("setup.setup_finished")); 237 return null; 238 } 239 240 @Nullable 241 @Override 242 public String getDefaultValue() { 243 return null; 244 } 245 }; 246 247 @NonNull 248 private final Collection<String> suggestions; 249 private final Caption description; 250 251 /** 252 * @param suggestions the input suggestions for this step 253 * @param description the caption describing this step 254 */ 255 CommonSetupSteps(@NonNull Collection<String> suggestions, @NonNull Caption description) { 256 this.suggestions = suggestions; 257 this.description = description; 258 } 259 260 CommonSetupSteps(@NonNull Caption description) { 261 this.description = description; 262 this.suggestions = Collections.emptyList(); 263 } 264 265 <E extends Enum<E>> CommonSetupSteps(@NonNull Class<E> argumentType, Caption description) { 266 this(enumToStrings(argumentType), description); 267 } 268 269 private static <E extends Enum<E>> Collection<String> enumToStrings(Class<E> type) { 270 return Arrays.stream(type.getEnumConstants()).map(e -> e.toString().toLowerCase()).collect(Collectors.toList()); 271 } 272 273 private static SettingsNodesWrapper wrap(String plotManager) { 274 return new SettingsNodesWrapper(SetupUtils.generators.get(plotManager).getPlotGenerator() 275 .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) 276 .getSettingNodes(), CHOOSE_WORLD_NAME); 277 } 278 279 private static boolean isValidWorldName(String s) { 280 return s 281 .chars() 282 .allMatch((i) -> i == 95 || i == 45 || i >= 97 && i <= 122 || i >= 65 && i <= 90 || i >= 48 && i <= 57 || i == 46); 283 } 284 285 @Override 286 public void announce(PlotPlayer<?> plotPlayer) { 287 plotPlayer.sendMessage(this.description); 288 } 289 290 public @NonNull Collection<String> getSuggestions() { 291 return this.suggestions; 292 } 293}