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.plot.world; 020 021import com.plotsquared.core.PlotSquared; 022import com.plotsquared.core.configuration.ConfigurationNode; 023import com.plotsquared.core.configuration.ConfigurationSection; 024import com.plotsquared.core.configuration.ConfigurationUtil; 025import com.plotsquared.core.configuration.caption.TranslatableCaption; 026import com.plotsquared.core.configuration.file.YamlConfiguration; 027import com.plotsquared.core.generator.GridPlotWorld; 028import com.plotsquared.core.generator.SingleWorldGenerator; 029import com.plotsquared.core.inject.annotations.WorldConfig; 030import com.plotsquared.core.listener.PlotListener; 031import com.plotsquared.core.location.BlockLoc; 032import com.plotsquared.core.location.Location; 033import com.plotsquared.core.plot.Plot; 034import com.plotsquared.core.plot.PlotAreaType; 035import com.plotsquared.core.plot.PlotId; 036import com.plotsquared.core.plot.PlotManager; 037import com.plotsquared.core.plot.PlotSettings; 038import com.plotsquared.core.plot.flag.FlagContainer; 039import com.plotsquared.core.queue.GlobalBlockQueue; 040import com.plotsquared.core.setup.PlotAreaBuilder; 041import com.plotsquared.core.setup.SettingsNodesWrapper; 042import com.plotsquared.core.util.EventDispatcher; 043import com.plotsquared.core.util.task.TaskManager; 044import org.checkerframework.checker.nullness.qual.NonNull; 045import org.checkerframework.checker.nullness.qual.Nullable; 046 047import java.io.File; 048import java.io.IOException; 049import java.nio.file.Files; 050 051public class SinglePlotArea extends GridPlotWorld { 052 053 @SuppressWarnings({"unused", "FieldCanBeLocal"}) 054 private final EventDispatcher eventDispatcher; 055 @SuppressWarnings({"unused", "FieldCanBeLocal"}) 056 private final PlotListener plotListener; 057 public boolean VOID = false; 058 059 public SinglePlotArea( 060 final @NonNull PlotAreaManager plotAreaManager, 061 final @NonNull EventDispatcher eventDispatcher, 062 final @NonNull PlotListener plotListener, 063 @WorldConfig final @NonNull YamlConfiguration worldConfiguration, 064 final @NonNull GlobalBlockQueue globalBlockQueue 065 ) { 066 super("*", null, new SingleWorldGenerator(plotAreaManager), null, null, 067 worldConfiguration, globalBlockQueue 068 ); 069 this.eventDispatcher = eventDispatcher; 070 this.plotListener = plotListener; 071 this.setAllowSigns(false); 072 this.setDefaultHome(new BlockLoc(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE)); 073 } 074 075 /** 076 * Returns true if the given string matches the naming system used to identify single plot worlds 077 * e.g. -1_5 represents plot id *;-1;5. "*" being the plot area name given to single plot world 078 * {@link com.plotsquared.core.plot.PlotArea}. 079 * 080 * @since 6.1.4 081 */ 082 public static boolean isSinglePlotWorld(String worldName) { 083 int len = worldName.length(); 084 int separator = 0; 085 for (int i = 0; i < len; i++) { 086 switch (worldName.charAt(i)) { 087 case '_': 088 separator++; 089 break; 090 case '-': 091 case '0': 092 case '1': 093 case '2': 094 case '3': 095 case '4': 096 case '5': 097 case '6': 098 case '7': 099 case '8': 100 case '9': 101 break; 102 default: 103 return false; 104 } 105 } 106 return separator == 1; 107 } 108 109 @NonNull 110 @Override 111 protected PlotManager createManager() { 112 return new SinglePlotManager(this); 113 } 114 115 @Override 116 public void loadConfiguration(ConfigurationSection config) { 117 VOID = config.getBoolean("void", false); 118 } 119 120 @Override 121 public void saveConfiguration(ConfigurationSection config) { 122 super.saveConfiguration(config); 123 } 124 125 public void loadWorld(final PlotId id) { 126 String worldName = id.toUnderscoreSeparatedString(); 127 if (PlotSquared.platform().worldUtil().isWorld(worldName)) { 128 return; 129 } 130 PlotAreaBuilder builder = PlotAreaBuilder.newBuilder() 131 .plotManager("PlotSquared:single") 132 .generatorName("PlotSquared:single") 133 .plotAreaType(getType()) 134 .terrainType(getTerrain()) 135 .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)) 136 .worldName(worldName); 137 138 File container = PlotSquared.platform().worldContainer(); 139 File destination = new File(container, worldName); 140 141 {// convert old 142 File oldFile = new File(container, id.toCommaSeparatedString()); 143 if (oldFile.exists()) { 144 oldFile.renameTo(destination); 145 } else { 146 oldFile = new File(container, id.toSeparatedString(".")); 147 if (oldFile.exists()) { 148 oldFile.renameTo(destination); 149 } 150 } 151 } 152 // Duplicate 0;0 153 if (builder.plotAreaType() != PlotAreaType.NORMAL) { 154 if (!destination.exists()) { 155 File src = new File(container, "0_0"); 156 if (src.exists()) { 157 if (!destination.exists()) { 158 destination.mkdirs(); 159 } 160 File levelDat = new File(src, "level.dat"); 161 if (levelDat.exists()) { 162 try { 163 Files.copy( 164 levelDat.toPath(), 165 new File(destination, levelDat.getName()).toPath() 166 ); 167 File data = new File(src, "data"); 168 if (data.exists()) { 169 File dataDest = new File(destination, "data"); 170 dataDest.mkdirs(); 171 for (File file : data.listFiles()) { 172 Files.copy( 173 file.toPath(), 174 new File(dataDest, file.getName()).toPath() 175 ); 176 } 177 } 178 } catch (IOException exception) { 179 exception.printStackTrace(); 180 } 181 } 182 } 183 } 184 } 185 186 try { 187 TaskManager.getPlatformImplementation().sync(() -> { 188 final String name = id.toUnderscoreSeparatedString(); 189 if (!PlotSquared.platform().worldUtil().isWorld(name)) { 190 PlotSquared.platform().setupUtils().setupWorld(builder); 191 } 192 return null; 193 }); 194 } catch (final Exception e) { 195 e.printStackTrace(); 196 } 197 198 // String worldName = plot.getWorldName(); 199 // World world = Bukkit.getWorld(worldName); 200 // if (world != null) { 201 // return world; 202 // } 203 // WorldCreator wc = new WorldCreator(worldName); 204 // wc.generator("PlotSquared:single"); 205 // wc.environment(World.Environment.NORMAL); 206 // wc.type(WorldType.FLAT); 207 // return AsyncWorld.create(wc); 208 } 209 210 211 @Override 212 public ConfigurationNode[] getSettingNodes() { 213 return new ConfigurationNode[]{ 214 new ConfigurationNode( 215 "void", 216 this.VOID, 217 TranslatableCaption.of("setup.singleplotarea_void_world"), 218 ConfigurationUtil.BOOLEAN 219 )}; 220 } 221 222 @Nullable 223 @Override 224 public Plot getOwnedPlot(final @NonNull Location location) { 225 PlotId pid = PlotId.fromStringOrNull(location.getWorldName()); 226 Plot plot = pid == null ? null : this.plots.get(pid); 227 return plot == null ? null : plot.getBasePlot(false); 228 } 229 230 @Nullable 231 @Override 232 public Plot getOwnedPlotAbs(@NonNull Location location) { 233 PlotId pid = PlotId.fromStringOrNull(location.getWorldName()); 234 return pid == null ? null : plots.get(pid); 235 } 236 237 @Nullable 238 @Override 239 public Plot getPlot(final @NonNull Location location) { 240 PlotId pid = PlotId.fromStringOrNull(location.getWorldName()); 241 return pid == null ? null : getPlot(pid); 242 } 243 244 @Nullable 245 @Override 246 public Plot getPlotAbs(final @NonNull Location location) { 247 final PlotId pid = PlotId.fromStringOrNull(location.getWorldName()); 248 return pid == null ? null : getPlotAbs(pid); 249 } 250 251 public boolean addPlot(@NonNull Plot plot) { 252 plot = adapt(plot); 253 return super.addPlot(plot); 254 } 255 256 @Override 257 public boolean addPlotAbs(@NonNull Plot plot) { 258 plot = adapt(plot); 259 return super.addPlotAbs(plot); 260 } 261 262 @Override 263 public boolean addPlotIfAbsent(@NonNull Plot plot) { 264 plot = adapt(plot); 265 return super.addPlotIfAbsent(plot); 266 } 267 268 @Override 269 public boolean allowSigns() { 270 return false; // do not create signs for single plots 271 } 272 273 @SuppressWarnings("deprecation") 274 protected Plot adapt(Plot p) { 275 if (p instanceof SinglePlot) { 276 return p; 277 } 278 PlotSettings s = p.getSettings(); 279 280 final FlagContainer oldContainer = p.getFlagContainer(); 281 p = new SinglePlot(p.getId(), p.getOwnerAbs(), p.getTrusted(), p.getMembers(), 282 p.getDenied(), s.getAlias(), s.getPosition(), null, this, s.getMerged(), 283 p.getTimestamp(), p.temp 284 ); 285 p.getFlagContainer().addAll(oldContainer); 286 287 return p; 288 } 289 290 public @Nullable Plot getPlotAbs(final @NonNull PlotId id) { 291 Plot plot = getOwnedPlotAbs(id); 292 if (plot == null) { 293 return new SinglePlot(this, id); 294 } 295 return plot; 296 } 297 298 public @Nullable Plot getPlot(@NonNull PlotId id) { 299 // TODO 300 Plot plot = getOwnedPlotAbs(id); 301 if (plot == null) { 302 return new SinglePlot(this, id); 303 } 304 return plot.getBasePlot(false); 305 } 306 307}