864 lines
48 KiB
Java
864 lines
48 KiB
Java
/*
|
|
* PlotSquared, a land and world management plugin for Minecraft.
|
|
* Copyright (C) IntellectualSites <https://intellectualsites.com>
|
|
* Copyright (C) IntellectualSites team and contributors
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package com.plotsquared.core.command;
|
|
|
|
import com.google.inject.Inject;
|
|
import com.plotsquared.core.PlotSquared;
|
|
import com.plotsquared.core.configuration.ConfigurationSection;
|
|
import com.plotsquared.core.configuration.ConfigurationUtil;
|
|
import com.plotsquared.core.configuration.Settings;
|
|
import com.plotsquared.core.configuration.caption.CaptionHolder;
|
|
import com.plotsquared.core.configuration.caption.Templates;
|
|
import com.plotsquared.core.configuration.caption.TranslatableCaption;
|
|
import com.plotsquared.core.configuration.file.YamlConfiguration;
|
|
import com.plotsquared.core.events.TeleportCause;
|
|
import com.plotsquared.core.generator.AugmentedUtils;
|
|
import com.plotsquared.core.generator.HybridPlotWorld;
|
|
import com.plotsquared.core.inject.annotations.WorldConfig;
|
|
import com.plotsquared.core.inject.annotations.WorldFile;
|
|
import com.plotsquared.core.inject.factory.HybridPlotWorldFactory;
|
|
import com.plotsquared.core.location.Location;
|
|
import com.plotsquared.core.permissions.Permission;
|
|
import com.plotsquared.core.player.ConsolePlayer;
|
|
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.plot.world.PlotAreaManager;
|
|
import com.plotsquared.core.plot.world.SinglePlotArea;
|
|
import com.plotsquared.core.queue.GlobalBlockQueue;
|
|
import com.plotsquared.core.queue.QueueCoordinator;
|
|
import com.plotsquared.core.setup.PlotAreaBuilder;
|
|
import com.plotsquared.core.util.FileUtils;
|
|
import com.plotsquared.core.util.MathMan;
|
|
import com.plotsquared.core.util.Permissions;
|
|
import com.plotsquared.core.util.RegionUtil;
|
|
import com.plotsquared.core.util.SchematicHandler;
|
|
import com.plotsquared.core.util.SetupUtils;
|
|
import com.plotsquared.core.util.StringMan;
|
|
import com.plotsquared.core.util.TabCompletions;
|
|
import com.plotsquared.core.util.WorldUtil;
|
|
import com.plotsquared.core.util.task.RunnableVal3;
|
|
import com.sk89q.worldedit.EditSession;
|
|
import com.sk89q.worldedit.LocalSession;
|
|
import com.sk89q.worldedit.WorldEdit;
|
|
import com.sk89q.worldedit.entity.Player;
|
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
|
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
|
import com.sk89q.worldedit.function.operation.Operations;
|
|
import com.sk89q.worldedit.math.BlockVector3;
|
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
|
import com.sk89q.worldedit.regions.Region;
|
|
import com.sk89q.worldedit.world.World;
|
|
import net.kyori.adventure.text.minimessage.Template;
|
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
import java.util.stream.Collectors;
|
|
|
|
@CommandDeclaration(command = "area",
|
|
permission = "plots.area",
|
|
category = CommandCategory.ADMINISTRATION,
|
|
requiredType = RequiredType.NONE,
|
|
aliases = "world",
|
|
usage = "/plot area <create | info | list | tp | regen>",
|
|
confirmation = true)
|
|
public class Area extends SubCommand {
|
|
|
|
private final PlotAreaManager plotAreaManager;
|
|
private final YamlConfiguration worldConfiguration;
|
|
private final File worldFile;
|
|
private final HybridPlotWorldFactory hybridPlotWorldFactory;
|
|
private final SetupUtils setupUtils;
|
|
private final WorldUtil worldUtil;
|
|
private final GlobalBlockQueue blockQueue;
|
|
|
|
private final Map<UUID, Map<String, Object>> metaData = new HashMap<>();
|
|
|
|
@Inject
|
|
public Area(
|
|
final @NonNull PlotAreaManager plotAreaManager,
|
|
@WorldConfig final @NonNull YamlConfiguration worldConfiguration,
|
|
@WorldFile final @NonNull File worldFile,
|
|
final @NonNull HybridPlotWorldFactory hybridPlotWorldFactory,
|
|
final @NonNull SetupUtils setupUtils,
|
|
final @NonNull WorldUtil worldUtil,
|
|
final @NonNull GlobalBlockQueue blockQueue
|
|
) {
|
|
this.plotAreaManager = plotAreaManager;
|
|
this.worldConfiguration = worldConfiguration;
|
|
this.worldFile = worldFile;
|
|
this.hybridPlotWorldFactory = hybridPlotWorldFactory;
|
|
this.setupUtils = setupUtils;
|
|
this.worldUtil = worldUtil;
|
|
this.blockQueue = blockQueue;
|
|
}
|
|
|
|
@Override
|
|
public boolean onCommand(final PlotPlayer<?> player, String[] args) {
|
|
if (args.length == 0) {
|
|
sendUsage(player);
|
|
return false;
|
|
}
|
|
switch (args[0].toLowerCase()) {
|
|
case "single" -> {
|
|
if (player instanceof ConsolePlayer) {
|
|
player.sendMessage(RequiredType.CONSOLE.getErrorMessage());
|
|
return false;
|
|
}
|
|
if (!Permissions.hasPermission(player, Permission.PERMISSION_AREA_CREATE)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_AREA_CREATE))
|
|
);
|
|
return false;
|
|
}
|
|
if (args.length < 2) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("single.single_area_needs_name"),
|
|
Template.of("command", "/plot area single <name>")
|
|
);
|
|
return false;
|
|
}
|
|
final PlotArea existingArea = this.plotAreaManager.getPlotArea(player.getLocation().getWorldName(), args[1]);
|
|
if (existingArea != null && existingArea.getId().equalsIgnoreCase(args[1])) {
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_name_taken"));
|
|
return false;
|
|
}
|
|
final LocalSession localSession = WorldEdit.getInstance().getSessionManager().getIfPresent(player.toActor());
|
|
if (localSession == null) {
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_missing_selection"));
|
|
return false;
|
|
}
|
|
Region playerSelectedRegion = null;
|
|
try {
|
|
playerSelectedRegion = localSession.getSelection(((Player) player.toActor()).getWorld());
|
|
} catch (final Exception ignored) {
|
|
}
|
|
if (playerSelectedRegion == null) {
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_missing_selection"));
|
|
return false;
|
|
}
|
|
if (playerSelectedRegion.getWidth() != playerSelectedRegion.getLength()) {
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_not_square"));
|
|
return false;
|
|
}
|
|
if (this.plotAreaManager.getPlotAreas(
|
|
Objects.requireNonNull(playerSelectedRegion.getWorld()).getName(),
|
|
CuboidRegion.makeCuboid(playerSelectedRegion)
|
|
).length != 0) {
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_overlapping"));
|
|
}
|
|
// Alter the region
|
|
final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint();
|
|
final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint();
|
|
// Create a new selection that spans the entire vertical range of the world
|
|
World world = playerSelectedRegion.getWorld();
|
|
final CuboidRegion selectedRegion =
|
|
new CuboidRegion(
|
|
playerSelectedRegion.getWorld(),
|
|
BlockVector3.at(playerSelectionMin.getX(), world.getMinY(), playerSelectionMin.getZ()),
|
|
BlockVector3.at(playerSelectionMax.getX(), world.getMaxY(), playerSelectionMax.getZ())
|
|
);
|
|
// There's only one plot in the area...
|
|
final PlotId plotId = PlotId.of(1, 1);
|
|
final HybridPlotWorld hybridPlotWorld = this.hybridPlotWorldFactory
|
|
.create(
|
|
player.getLocation().getWorldName(),
|
|
args[1],
|
|
Objects.requireNonNull(PlotSquared.platform()).defaultGenerator(),
|
|
plotId,
|
|
plotId
|
|
);
|
|
// Plot size is the same as the region width
|
|
hybridPlotWorld.PLOT_WIDTH = hybridPlotWorld.SIZE = (short) selectedRegion.getWidth();
|
|
// We use a schematic generator
|
|
hybridPlotWorld.setTerrain(PlotAreaTerrainType.NONE);
|
|
// It is always a partial plot world
|
|
hybridPlotWorld.setType(PlotAreaType.PARTIAL);
|
|
// We save the schematic :D
|
|
hybridPlotWorld.PLOT_SCHEMATIC = true;
|
|
// Set the road width to 0
|
|
hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0;
|
|
// Set the plot height to the selection height
|
|
hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = playerSelectionMin.getBlockY();
|
|
// No sign plz
|
|
hybridPlotWorld.setAllowSigns(false);
|
|
final File parentFile = FileUtils.getFile(
|
|
PlotSquared.platform().getDirectory(),
|
|
Settings.Paths.SCHEMATICS + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator
|
|
+ hybridPlotWorld.getId()
|
|
);
|
|
if (!parentFile.exists() && !parentFile.mkdirs()) {
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_could_not_make_directories"));
|
|
return false;
|
|
}
|
|
final File file = new File(parentFile, "plot.schem");
|
|
try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(
|
|
file))) {
|
|
final BlockArrayClipboard clipboard = new BlockArrayClipboard(selectedRegion);
|
|
final EditSession editSession = WorldEdit
|
|
.getInstance()
|
|
.getEditSessionFactory()
|
|
.getEditSession(selectedRegion.getWorld(), -1);
|
|
final ForwardExtentCopy forwardExtentCopy =
|
|
new ForwardExtentCopy(editSession, selectedRegion, clipboard, selectedRegion.getMinimumPoint());
|
|
forwardExtentCopy.setCopyingBiomes(true);
|
|
forwardExtentCopy.setCopyingEntities(true);
|
|
Operations.complete(forwardExtentCopy);
|
|
clipboardWriter.write(clipboard);
|
|
} catch (final Exception e) {
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_failed_to_save"));
|
|
e.printStackTrace();
|
|
return false;
|
|
}
|
|
|
|
// Setup schematic
|
|
try {
|
|
hybridPlotWorld.setupSchematics();
|
|
} catch (final SchematicHandler.UnsupportedFormatException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
// Calculate the offset
|
|
final BlockVector3 singlePos1 = selectedRegion.getMinimumPoint();
|
|
|
|
// Now the schematic is saved, which is wonderful!
|
|
PlotAreaBuilder singleBuilder = PlotAreaBuilder.ofPlotArea(hybridPlotWorld).plotManager(PlotSquared
|
|
.platform()
|
|
.pluginName())
|
|
.generatorName(PlotSquared.platform().pluginName()).maximumId(plotId).minimumId(plotId);
|
|
Runnable singleRun = () -> {
|
|
final String path =
|
|
"worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld.getId() + '-' + singleBuilder
|
|
.minimumId() + '-'
|
|
+ singleBuilder.maximumId();
|
|
final int offsetX = singlePos1.getX();
|
|
final int offsetZ = singlePos1.getZ();
|
|
if (offsetX != 0) {
|
|
this.worldConfiguration.set(path + ".road.offset.x", offsetX);
|
|
}
|
|
if (offsetZ != 0) {
|
|
this.worldConfiguration.set(path + ".road.offset.z", offsetZ);
|
|
}
|
|
final String worldName = this.setupUtils.setupWorld(singleBuilder);
|
|
if (this.worldUtil.isWorld(worldName)) {
|
|
PlotSquared.get().loadWorld(worldName, null);
|
|
player.sendMessage(TranslatableCaption.of("single.single_area_created"));
|
|
} else {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("errors.error_create"),
|
|
Template.of("world", hybridPlotWorld.getWorldName())
|
|
);
|
|
}
|
|
};
|
|
singleRun.run();
|
|
return true;
|
|
}
|
|
case "c", "setup", "create" -> {
|
|
if (!Permissions.hasPermission(player, Permission.PERMISSION_AREA_CREATE)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_AREA_CREATE))
|
|
);
|
|
return false;
|
|
}
|
|
switch (args.length) {
|
|
case 1:
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Templates.of("value", "/plot area create [world[:id]] [<modifier>=<value>]...")
|
|
);
|
|
return false;
|
|
case 2:
|
|
switch (args[1].toLowerCase()) {
|
|
case "pos1" -> { // Set position 1
|
|
HybridPlotWorld area = (HybridPlotWorld) metaData.computeIfAbsent(
|
|
player.getUUID(),
|
|
missingUUID -> new HashMap<>()
|
|
)
|
|
.get("area_create_area");
|
|
if (area == null) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Templates.of("value", "/plot area create [world[:id]] [<modifier>=<value>]...")
|
|
);
|
|
return false;
|
|
}
|
|
Location location = player.getLocation();
|
|
metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).put(
|
|
"area_pos1",
|
|
location
|
|
);
|
|
player.sendMessage(
|
|
TranslatableCaption.of("set.set_attribute"),
|
|
Template.of("attribute", "area_pos1"),
|
|
Template.of("value", location.getX() + "," + location.getZ())
|
|
);
|
|
player.sendMessage(
|
|
TranslatableCaption.of("area.set_pos2"),
|
|
Template.of("command", "/plot area create pos2")
|
|
);
|
|
return true;
|
|
}
|
|
case "pos2" -> { // Set position 2 and finish creation for type=2 (partial)
|
|
final HybridPlotWorld area =
|
|
(HybridPlotWorld) metaData.computeIfAbsent(
|
|
player.getUUID(),
|
|
missingUUID -> new HashMap<>()
|
|
)
|
|
.get("area_create_area");
|
|
if (area == null) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Templates.of("value", "/plot area create [world[:id]] [<modifier>=<value>]...")
|
|
);
|
|
return false;
|
|
}
|
|
Location pos1 = player.getLocation();
|
|
Location pos2 =
|
|
(Location) metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).get(
|
|
"area_pos1");
|
|
int dx = Math.abs(pos1.getX() - pos2.getX());
|
|
int dz = Math.abs(pos1.getZ() - pos2.getZ());
|
|
int numX = Math.max(1, (dx + 1 + area.ROAD_WIDTH + area.SIZE / 2) / area.SIZE);
|
|
int numZ = Math.max(1, (dz + 1 + area.ROAD_WIDTH + area.SIZE / 2) / area.SIZE);
|
|
int ddx = dx - (numX * area.SIZE - area.ROAD_WIDTH);
|
|
int ddz = dz - (numZ * area.SIZE - area.ROAD_WIDTH);
|
|
int bx = Math.min(pos1.getX(), pos2.getX()) + ddx;
|
|
int bz = Math.min(pos1.getZ(), pos2.getZ()) + ddz;
|
|
int tx = Math.max(pos1.getX(), pos2.getX()) - ddx;
|
|
int tz = Math.max(pos1.getZ(), pos2.getZ()) - ddz;
|
|
int lower = (area.ROAD_WIDTH & 1) == 0 ? area.ROAD_WIDTH / 2 - 1 : area.ROAD_WIDTH / 2;
|
|
final int offsetX = bx - (area.ROAD_WIDTH == 0 ? 0 : lower);
|
|
final int offsetZ = bz - (area.ROAD_WIDTH == 0 ? 0 : lower);
|
|
// Height doesn't matter for this region
|
|
final CuboidRegion region = RegionUtil.createRegion(bx, tx, 0, 0, bz, tz);
|
|
final Set<PlotArea> areas = this.plotAreaManager.getPlotAreasSet(area.getWorldName(), region);
|
|
if (!areas.isEmpty()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("cluster.cluster_intersection"),
|
|
Template.of("cluster", areas.iterator().next().toString())
|
|
);
|
|
return false;
|
|
}
|
|
PlotAreaBuilder builder = PlotAreaBuilder.ofPlotArea(area).plotManager(PlotSquared
|
|
.platform()
|
|
.pluginName())
|
|
.generatorName(PlotSquared.platform().pluginName()).minimumId(PlotId.of(1, 1))
|
|
.maximumId(PlotId.of(numX, numZ));
|
|
final String path =
|
|
"worlds." + area.getWorldName() + ".areas." + area.getId() + '-' + builder.minimumId() + '-' + builder
|
|
.maximumId();
|
|
Runnable run = () -> {
|
|
if (offsetX != 0) {
|
|
this.worldConfiguration.set(path + ".road.offset.x", offsetX);
|
|
}
|
|
if (offsetZ != 0) {
|
|
this.worldConfiguration.set(path + ".road.offset.z", offsetZ);
|
|
}
|
|
final String world = this.setupUtils.setupWorld(builder);
|
|
if (this.worldUtil.isWorld(world)) {
|
|
PlotSquared.get().loadWorld(world, null);
|
|
player.teleport(this.worldUtil.getSpawn(world), TeleportCause.COMMAND_AREA_CREATE);
|
|
player.sendMessage(TranslatableCaption.of("setup.setup_finished"));
|
|
if (area.getTerrain() != PlotAreaTerrainType.ALL) {
|
|
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(world));
|
|
queue.setChunkConsumer(chunk -> AugmentedUtils.generate(
|
|
null,
|
|
world,
|
|
chunk.getX(),
|
|
chunk.getZ(),
|
|
null
|
|
));
|
|
queue.addReadChunks(region.getChunks());
|
|
queue.enqueue();
|
|
}
|
|
} else {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("errors.error_create"),
|
|
Template.of("world", area.getWorldName())
|
|
);
|
|
}
|
|
};
|
|
if (hasConfirmation(player)) {
|
|
CmdConfirm.addPending(player, getCommandString() + " create pos2 (Creates world)", run);
|
|
} else {
|
|
run.run();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
default: // Start creation
|
|
String[] split = args[1].split(":");
|
|
String id;
|
|
if (split.length == 2) {
|
|
id = split[1];
|
|
} else {
|
|
id = null;
|
|
}
|
|
PlotAreaBuilder builder = PlotAreaBuilder.newBuilder();
|
|
builder.worldName(split[0]);
|
|
final HybridPlotWorld pa =
|
|
this.hybridPlotWorldFactory.create(
|
|
builder.worldName(),
|
|
id,
|
|
PlotSquared.platform().defaultGenerator(),
|
|
null,
|
|
null
|
|
);
|
|
PlotArea other = this.plotAreaManager.getPlotArea(pa.getWorldName(), id);
|
|
if (other != null && Objects.equals(pa.getId(), other.getId())) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("setup.setup_world_taken"),
|
|
Template.of("value", pa.toString())
|
|
);
|
|
return false;
|
|
}
|
|
Set<PlotArea> areas = this.plotAreaManager.getPlotAreasSet(pa.getWorldName());
|
|
if (!areas.isEmpty()) {
|
|
PlotArea area = areas.iterator().next();
|
|
pa.setType(area.getType());
|
|
}
|
|
pa.SIZE = (short) (pa.PLOT_WIDTH + pa.ROAD_WIDTH);
|
|
for (int i = 2; i < args.length; i++) {
|
|
String[] pair = args[i].split("=");
|
|
if (pair.length != 2) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax_extended"),
|
|
Template.of("value1,", getCommandString()),
|
|
Template.of("value2", " create [world[:id]] [<modifier>=<value>]...")
|
|
);
|
|
return false;
|
|
}
|
|
switch (pair[0].toLowerCase()) {
|
|
case "s", "size" -> {
|
|
pa.PLOT_WIDTH = Integer.parseInt(pair[1]);
|
|
pa.SIZE = (short) (pa.PLOT_WIDTH + pa.ROAD_WIDTH);
|
|
}
|
|
case "g", "gap" -> {
|
|
pa.ROAD_WIDTH = Integer.parseInt(pair[1]);
|
|
pa.SIZE = (short) (pa.PLOT_WIDTH + pa.ROAD_WIDTH);
|
|
}
|
|
case "h", "height" -> {
|
|
int value = Integer.parseInt(pair[1]);
|
|
pa.PLOT_HEIGHT = value;
|
|
pa.ROAD_HEIGHT = value;
|
|
pa.WALL_HEIGHT = value;
|
|
}
|
|
case "f", "floor" -> pa.TOP_BLOCK = ConfigurationUtil.BLOCK_BUCKET.parseString(pair[1]);
|
|
case "m", "main" -> pa.MAIN_BLOCK = ConfigurationUtil.BLOCK_BUCKET.parseString(pair[1]);
|
|
case "w", "wall" -> pa.WALL_FILLING = ConfigurationUtil.BLOCK_BUCKET.parseString(pair[1]);
|
|
case "b", "border" -> pa.WALL_BLOCK = ConfigurationUtil.BLOCK_BUCKET.parseString(pair[1]);
|
|
case "terrain" -> {
|
|
pa.setTerrain(PlotAreaTerrainType.fromString(pair[1])
|
|
.orElseThrow(() -> new IllegalArgumentException(pair[1] + " is not a valid terrain.")));
|
|
builder.terrainType(pa.getTerrain());
|
|
}
|
|
case "type" -> {
|
|
pa.setType(PlotAreaType.fromString(pair[1])
|
|
.orElseThrow(() -> new IllegalArgumentException(pair[1] + " is not a valid type.")));
|
|
builder.plotAreaType(pa.getType());
|
|
}
|
|
default -> {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax_extended"),
|
|
Template.of("value1", getCommandString()),
|
|
Template.of("value2", " create [world[:id]] [<modifier>=<value>]...")
|
|
);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
if (pa.getType() != PlotAreaType.PARTIAL) {
|
|
if (this.worldUtil.isWorld(pa.getWorldName())) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("setup.setup_world_taken"),
|
|
Template.of("value", pa.getWorldName())
|
|
);
|
|
return false;
|
|
}
|
|
Runnable run = () -> {
|
|
String path = "worlds." + pa.getWorldName();
|
|
if (!this.worldConfiguration.contains(path)) {
|
|
this.worldConfiguration.createSection(path);
|
|
}
|
|
ConfigurationSection section = this.worldConfiguration.getConfigurationSection(path);
|
|
pa.saveConfiguration(section);
|
|
pa.loadConfiguration(section);
|
|
builder.plotManager(PlotSquared.platform().pluginName());
|
|
builder.generatorName(PlotSquared.platform().pluginName());
|
|
String world = this.setupUtils.setupWorld(builder);
|
|
if (this.worldUtil.isWorld(world)) {
|
|
player.teleport(this.worldUtil.getSpawn(world), TeleportCause.COMMAND_AREA_CREATE);
|
|
player.sendMessage(TranslatableCaption.of("setup.setup_finished"));
|
|
} else {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("errors.error_create"),
|
|
Template.of("world", pa.getWorldName())
|
|
);
|
|
}
|
|
try {
|
|
this.worldConfiguration.save(this.worldFile);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
};
|
|
if (hasConfirmation(player)) {
|
|
CmdConfirm.addPending(player, getCommandString() + ' ' + StringMan.join(args, " "), run);
|
|
} else {
|
|
run.run();
|
|
}
|
|
return true;
|
|
}
|
|
if (pa.getId() == null) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Template.of("value", getUsage())
|
|
);
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax_extended"),
|
|
Template.of("value1", getCommandString()),
|
|
Template.of("value2", " create [world[:id]] [<modifier>=<value>]...")
|
|
);
|
|
return false;
|
|
}
|
|
if (this.worldUtil.isWorld(pa.getWorldName())) {
|
|
if (!player.getLocation().getWorldName().equals(pa.getWorldName())) {
|
|
player.teleport(this.worldUtil.getSpawn(pa.getWorldName()), TeleportCause.COMMAND_AREA_CREATE);
|
|
}
|
|
} else {
|
|
builder.terrainType(PlotAreaTerrainType.NONE);
|
|
builder.plotAreaType(PlotAreaType.NORMAL);
|
|
this.setupUtils.setupWorld(builder);
|
|
player.teleport(this.worldUtil.getSpawn(pa.getWorldName()), TeleportCause.COMMAND_AREA_CREATE);
|
|
}
|
|
metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).put("area_create_area", pa);
|
|
player.sendMessage(
|
|
TranslatableCaption.of("single.get_position"),
|
|
Template.of("command", getCommandString())
|
|
);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
case "i", "info" -> {
|
|
if (!Permissions.hasPermission(player, Permission.PERMISSION_AREA_INFO)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_AREA_INFO))
|
|
);
|
|
return false;
|
|
}
|
|
PlotArea area;
|
|
switch (args.length) {
|
|
case 1 -> area = player.getApplicablePlotArea();
|
|
case 2 -> area = this.plotAreaManager.getPlotAreaByString(args[1]);
|
|
default -> {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax_extended"),
|
|
Template.of("value1", getCommandString()),
|
|
Template.of("value2", " info [area]")
|
|
);
|
|
return false;
|
|
}
|
|
}
|
|
if (area == null) {
|
|
if (args.length == 2) {
|
|
player.sendMessage(TranslatableCaption.of("errors.not_valid_plot_world"), Template.of("value", args[1]));
|
|
} else {
|
|
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
|
|
}
|
|
return false;
|
|
}
|
|
String name;
|
|
double percent;
|
|
int claimed = area.getPlotCount();
|
|
int clusters = area.getClusters().size();
|
|
String region;
|
|
String generator = String.valueOf(area.getGenerator());
|
|
if (area.getType() == PlotAreaType.PARTIAL) {
|
|
PlotId min = area.getMin();
|
|
PlotId max = area.getMax();
|
|
name = area.getWorldName() + ';' + area.getId() + ';' + min + ';' + max;
|
|
int size = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1);
|
|
percent = claimed == 0 ? 0 : size / (double) claimed;
|
|
region = area.getRegion().toString();
|
|
} else {
|
|
name = area.getWorldName();
|
|
percent = claimed == 0 ? 0 : 100d * claimed / Integer.MAX_VALUE;
|
|
region = "N/A";
|
|
}
|
|
Template headerTemplate = Template.of(
|
|
"header",
|
|
TranslatableCaption.of("info.plot_info_header").getComponent(player)
|
|
);
|
|
Template nameTemplate = Template.of("name", name);
|
|
Template typeTemplate = Template.of("type", area.getType().name());
|
|
Template terrainTemplate = Template.of("terrain", area.getTerrain().name());
|
|
Template usageTemplate = Template.of("usage", String.format("%.2f", percent));
|
|
Template claimedTemplate = Template.of("claimed", String.valueOf(claimed));
|
|
Template clustersTemplate = Template.of("clusters", String.valueOf(clusters));
|
|
Template regionTemplate = Template.of("region", region);
|
|
Template generatorTemplate = Template.of("generator", generator);
|
|
Template footerTemplate = Template.of(
|
|
"footer",
|
|
TranslatableCaption.of("info.plot_info_footer").getComponent(player)
|
|
);
|
|
player.sendMessage(
|
|
TranslatableCaption.of("info.area_info_format"),
|
|
headerTemplate,
|
|
nameTemplate,
|
|
typeTemplate,
|
|
terrainTemplate,
|
|
usageTemplate,
|
|
claimedTemplate,
|
|
clustersTemplate,
|
|
regionTemplate,
|
|
generatorTemplate,
|
|
footerTemplate
|
|
);
|
|
return true;
|
|
}
|
|
case "l", "list" -> {
|
|
if (!Permissions.hasPermission(player, Permission.PERMISSION_AREA_LIST)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_AREA_LIST))
|
|
);
|
|
return false;
|
|
}
|
|
int page;
|
|
switch (args.length) {
|
|
case 1:
|
|
page = 0;
|
|
break;
|
|
case 2:
|
|
if (MathMan.isInteger(args[1])) {
|
|
page = Integer.parseInt(args[1]) - 1;
|
|
break;
|
|
}
|
|
default:
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax_extended"),
|
|
Template.of("value1", getCommandString()),
|
|
Template.of("value2", " list [#]")
|
|
);
|
|
return false;
|
|
}
|
|
final List<PlotArea> areas = new ArrayList<>(Arrays.asList(this.plotAreaManager.getAllPlotAreas()));
|
|
paginate(player, areas, 8, page, new RunnableVal3<Integer, PlotArea, CaptionHolder>() {
|
|
@Override
|
|
public void run(Integer i, PlotArea area, CaptionHolder caption) {
|
|
String name;
|
|
double percent;
|
|
int claimed = area.getPlotCount();
|
|
int clusters = area.getClusters().size();
|
|
String region;
|
|
String generator = String.valueOf(area.getGenerator());
|
|
if (area.getType() == PlotAreaType.PARTIAL) {
|
|
PlotId min = area.getMin();
|
|
PlotId max = area.getMax();
|
|
name = area.getWorldName() + ';' + area.getId() + ';' + min + ';' + max;
|
|
int size = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1);
|
|
percent = claimed == 0 ? 0 : claimed / (double) size;
|
|
region = area.getRegion().toString();
|
|
} else {
|
|
name = area.getWorldName();
|
|
percent = claimed == 0 ? 0 : (double) claimed / Short.MAX_VALUE * Short.MAX_VALUE;
|
|
region = "N/A";
|
|
}
|
|
Template claimedTemplate = Template.of("claimed", String.valueOf(claimed));
|
|
Template usageTemplate = Template.of("usage", String.format("%.2f", percent) + "%");
|
|
Template clustersTemplate = Template.of("clusters", String.valueOf(clusters));
|
|
Template regionTemplate = Template.of("region", region);
|
|
Template generatorTemplate = Template.of("generator", generator);
|
|
String tooltip = MINI_MESSAGE.serialize(MINI_MESSAGE
|
|
.parse(
|
|
TranslatableCaption.of("info.area_list_tooltip").getComponent(player),
|
|
claimedTemplate,
|
|
usageTemplate,
|
|
clustersTemplate,
|
|
regionTemplate,
|
|
generatorTemplate
|
|
));
|
|
Template tooltipTemplate = Template.of("hover_info", tooltip);
|
|
Template visitcmdTemplate = Template.of("command_tp", "/plot area tp " + area);
|
|
Template infocmdTemplate = Template.of("command_info", "/plot area info " + area);
|
|
Template numberTemplate = Template.of("number", String.valueOf(i));
|
|
Template nameTemplate = Template.of("area_name", name);
|
|
Template typeTemplate = Template.of("area_type", area.getType().name());
|
|
Template terrainTemplate = Template.of("area_terrain", area.getTerrain().name());
|
|
caption.set(TranslatableCaption.of("info.area_list_item"));
|
|
caption.setTemplates(
|
|
tooltipTemplate,
|
|
visitcmdTemplate,
|
|
numberTemplate,
|
|
nameTemplate,
|
|
typeTemplate,
|
|
terrainTemplate,
|
|
infocmdTemplate
|
|
);
|
|
}
|
|
}, "/plot area list", TranslatableCaption.of("list.area_list_header_paged"));
|
|
return true;
|
|
}
|
|
case "regen", "clear", "reset", "regenerate" -> {
|
|
if (!Permissions.hasPermission(player, Permission.PERMISSION_AREA_REGEN)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_AREA_REGEN))
|
|
);
|
|
return false;
|
|
}
|
|
final PlotArea area = player.getApplicablePlotArea();
|
|
if (area == null) {
|
|
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
|
|
return false;
|
|
}
|
|
if (area.getType() != PlotAreaType.PARTIAL) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("single.delete_world_region"),
|
|
Template.of("world", area.getWorldName())
|
|
);
|
|
return false;
|
|
}
|
|
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
|
|
queue.setChunkConsumer(chunk -> AugmentedUtils.generate(
|
|
null,
|
|
area.getWorldName(),
|
|
chunk.getX(),
|
|
chunk.getZ(),
|
|
null
|
|
));
|
|
queue.addReadChunks(area.getRegion().getChunks());
|
|
queue.setCompleteTask(() -> player.sendMessage(TranslatableCaption.of("single.regeneration_complete")));
|
|
queue.enqueue();
|
|
return true;
|
|
}
|
|
case "goto", "v", "teleport", "visit", "tp" -> {
|
|
if (!Permissions.hasPermission(player, Permission.PERMISSION_AREA_TP)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_AREA_TP))
|
|
);
|
|
return false;
|
|
}
|
|
if (args.length != 2) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Template.of("value", "/plot area tp [area]")
|
|
);
|
|
return false;
|
|
}
|
|
PlotArea area = this.plotAreaManager.getPlotAreaByString(args[1]);
|
|
if (area == null) {
|
|
player.sendMessage(TranslatableCaption.of("errors.not_valid_plot_world"), Template.of("value", args[1]));
|
|
return false;
|
|
}
|
|
Location center;
|
|
if (area instanceof SinglePlotArea) {
|
|
((SinglePlotArea) area).loadWorld(PlotId.of(0, 0));
|
|
center = this.worldUtil.getSpawn(PlotId.of(0, 0).toUnderscoreSeparatedString());
|
|
player.teleport(center, TeleportCause.COMMAND_AREA_TELEPORT);
|
|
} else if (area.getType() != PlotAreaType.PARTIAL) {
|
|
center = this.worldUtil.getSpawn(area.getWorldName());
|
|
player.teleport(center, TeleportCause.COMMAND_AREA_TELEPORT);
|
|
} else {
|
|
CuboidRegion region = area.getRegion();
|
|
center = Location.at(area.getWorldName(),
|
|
region.getMinimumPoint().getX() + (region.getMaximumPoint().getX() - region
|
|
.getMinimumPoint()
|
|
.getX()) / 2, 0,
|
|
region.getMinimumPoint().getZ() + (region.getMaximumPoint().getZ() - region
|
|
.getMinimumPoint()
|
|
.getZ()) / 2
|
|
);
|
|
this.worldUtil.getHighestBlock(area.getWorldName(), center.getX(), center.getZ(),
|
|
y -> player.teleport(center.withY(1 + y), TeleportCause.COMMAND_AREA_TELEPORT)
|
|
);
|
|
}
|
|
return true;
|
|
}
|
|
case "delete", "remove" -> {
|
|
player.sendMessage(TranslatableCaption.of("single.worldcreation_location"));
|
|
return true;
|
|
}
|
|
}
|
|
sendUsage(player);
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) {
|
|
if (args.length == 1) {
|
|
final List<String> completions = new LinkedList<>();
|
|
if (Permissions.hasPermission(player, Permission.PERMISSION_AREA_CREATE)) {
|
|
completions.add("create");
|
|
}
|
|
if (Permissions.hasPermission(player, Permission.PERMISSION_AREA_CREATE)) {
|
|
completions.add("single");
|
|
}
|
|
if (Permissions.hasPermission(player, Permission.PERMISSION_AREA_LIST)) {
|
|
completions.add("list");
|
|
}
|
|
if (Permissions.hasPermission(player, Permission.PERMISSION_AREA_INFO)) {
|
|
completions.add("info");
|
|
}
|
|
if (Permissions.hasPermission(player, Permission.PERMISSION_AREA_TP)) {
|
|
completions.add("tp");
|
|
}
|
|
final List<Command> commands = completions.stream().filter(completion -> completion
|
|
.toLowerCase()
|
|
.startsWith(args[0].toLowerCase()))
|
|
.map(completion -> new Command(
|
|
null,
|
|
true,
|
|
completion,
|
|
"",
|
|
RequiredType.NONE,
|
|
CommandCategory.ADMINISTRATION
|
|
) {
|
|
}).collect(Collectors.toCollection(LinkedList::new));
|
|
if (Permissions.hasPermission(player, Permission.PERMISSION_AREA) && args[0].length() > 0) {
|
|
commands.addAll(TabCompletions.completePlayers(player, args[0], Collections.emptyList()));
|
|
}
|
|
return commands;
|
|
}
|
|
return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList());
|
|
}
|
|
|
|
}
|