mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2024-11-26 07:06:44 +01:00
Apply correct codestyle
This commit is contained in:
parent
9c90928d07
commit
51afbdfcdc
@ -0,0 +1,224 @@
|
||||
package com.github.intellectualsites.plotsquared.api;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.file.YamlConfiguration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
|
||||
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* PlotSquared API.
|
||||
*
|
||||
* <p>Useful classes:
|
||||
* <ul>
|
||||
* <li>{@link PlotPlayer}</li>
|
||||
* <li>{@link Plot}</li>
|
||||
* <li>{@link com.github.intellectualsites.plotsquared.plot.object.Location}</li>
|
||||
* <li>{@link PlotArea}</li>
|
||||
* <li>{@link PlotSquared}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @version 3.3.3
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"}) @NoArgsConstructor public class PlotAPI {
|
||||
|
||||
/**
|
||||
* Get all plots.
|
||||
*
|
||||
* @return all plots
|
||||
* @see PlotSquared#getPlots()
|
||||
*/
|
||||
public Set<Plot> getAllPlots() {
|
||||
return PlotSquared.get().getPlots();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all plots for a player.
|
||||
*
|
||||
* @param player Player, whose plots to search for
|
||||
* @return all plots that a player owns
|
||||
*/
|
||||
public Set<Plot> getPlayerPlots(PlotPlayer player) {
|
||||
return PlotSquared.get().getPlots(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a plot world.
|
||||
*
|
||||
* @param plotArea Plot World Object
|
||||
* @see PlotSquared#addPlotArea(PlotArea)
|
||||
*/
|
||||
public void addPlotArea(PlotArea plotArea) {
|
||||
PlotSquared.get().addPlotArea(plotArea);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PlotSquared configurations file.
|
||||
*
|
||||
* @return main configuration
|
||||
* @see PlotSquared#config
|
||||
*/
|
||||
public YamlConfiguration getConfig() {
|
||||
return PlotSquared.get().config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotSquared storage file.
|
||||
*
|
||||
* @return storage configuration
|
||||
* @see PlotSquared#storage
|
||||
*/
|
||||
public YamlConfiguration getStorage() {
|
||||
return PlotSquared.get().storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main class for this plugin. Only use this if you really need it.
|
||||
*
|
||||
* @return PlotSquared PlotSquared Main Class
|
||||
* @see PlotSquared
|
||||
*/
|
||||
public PlotSquared getMain() {
|
||||
return PlotSquared.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* ChunkManager class contains several useful methods.
|
||||
* <ul>
|
||||
* <li>Chunk deletion</li>
|
||||
* <li>Moving or copying regions</li>
|
||||
* <li>Plot swapping</li>
|
||||
* <li>Entity Tracking</li>
|
||||
* <li>Region Regeneration</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return ChunkManager
|
||||
* @see ChunkManager
|
||||
*/
|
||||
public ChunkManager getChunkManager() {
|
||||
return ChunkManager.manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block/biome set queue
|
||||
*
|
||||
* @return GlobalBlockQueue.IMP
|
||||
*/
|
||||
public GlobalBlockQueue getBlockQueue() {
|
||||
return GlobalBlockQueue.IMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* UUIDWrapper class has basic methods for getting UUIDS. It's recommended
|
||||
* to use the UUIDHandler class instead.
|
||||
*
|
||||
* @return UUIDWrapper
|
||||
* @see UUIDWrapper
|
||||
*/
|
||||
public UUIDWrapper getUUIDWrapper() {
|
||||
return UUIDHandler.getUUIDWrapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* SchematicHandler class contains methods related to pasting, reading
|
||||
* and writing schematics.
|
||||
*
|
||||
* @return SchematicHandler
|
||||
* @see SchematicHandler
|
||||
*/
|
||||
public SchematicHandler getSchematicHandler() {
|
||||
return SchematicHandler.manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of PlotAreas in the world.
|
||||
*
|
||||
* @param world The world to check for plot areas
|
||||
* @return A set of PlotAreas
|
||||
*/
|
||||
public Set<PlotArea> getPlotAreas(String world) {
|
||||
if (world == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return PlotSquared.get().getPlotAreas(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the console. The message supports color codes.
|
||||
*
|
||||
* @param message the message
|
||||
* @see MainUtil#sendConsoleMessage(C, String...)
|
||||
*/
|
||||
public void sendConsoleMessage(String message) {
|
||||
PlotSquared.log(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the console.
|
||||
*
|
||||
* @param caption the message
|
||||
* @see #sendConsoleMessage(String)
|
||||
* @see C
|
||||
*/
|
||||
public void sendConsoleMessage(C caption) {
|
||||
sendConsoleMessage(caption.s());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a flag for use in plots.
|
||||
*
|
||||
* @param flag the flag to register
|
||||
*/
|
||||
public void addFlag(Flag<?> flag) {
|
||||
Flags.registerFlag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PlotSquared class.
|
||||
*
|
||||
* @return PlotSquared Class
|
||||
* @see PlotSquared
|
||||
*/
|
||||
public PlotSquared getPlotSquared() {
|
||||
return PlotSquared.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotPlayer for a UUID.
|
||||
*
|
||||
* <p><i>Please note that PlotSquared can be configured to provide
|
||||
* different UUIDs than bukkit</i>
|
||||
*
|
||||
* @param uuid the uuid of the player to wrap
|
||||
* @return a {@code PlotPlayer}
|
||||
* @see PlotPlayer#wrap(Object)
|
||||
*/
|
||||
public PlotPlayer wrapPlayer(UUID uuid) {
|
||||
return PlotPlayer.wrap(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotPlayer for a username.
|
||||
*
|
||||
* @param player the player to wrap
|
||||
* @return a {@code PlotPlayer}
|
||||
* @see PlotPlayer#wrap(Object)
|
||||
*/
|
||||
public PlotPlayer wrapPlayer(String player) {
|
||||
return PlotPlayer.wrap(player);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.github.intellectualsites.plotsquared.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
|
||||
|
||||
public abstract class Argument<T> {
|
||||
|
||||
public static final Argument<Integer> Integer = new Argument<Integer>("int", 16) {
|
||||
@Override public Integer parse(String in) {
|
||||
Integer value = null;
|
||||
try {
|
||||
value = java.lang.Integer.parseInt(in);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
};
|
||||
public static final Argument<Boolean> Boolean = new Argument<Boolean>("boolean", true) {
|
||||
@Override public Boolean parse(String in) {
|
||||
Boolean value = null;
|
||||
if (in.equalsIgnoreCase("true") || in.equalsIgnoreCase("Yes") || in
|
||||
.equalsIgnoreCase("1")) {
|
||||
value = true;
|
||||
} else if (in.equalsIgnoreCase("false") || in.equalsIgnoreCase("No") || in
|
||||
.equalsIgnoreCase("0")) {
|
||||
value = false;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
};
|
||||
public static final Argument<String> String = new Argument<String>("String", "Example") {
|
||||
@Override public String parse(String in) {
|
||||
return in;
|
||||
}
|
||||
};
|
||||
public static final Argument<String> PlayerName =
|
||||
new Argument<String>("PlayerName", "Dinnerbone") {
|
||||
@Override public String parse(String in) {
|
||||
return in.length() <= 16 ? in : null;
|
||||
}
|
||||
};
|
||||
public static final Argument<PlotId> PlotID =
|
||||
new Argument<PlotId>("PlotID", new PlotId(-6, 3)) {
|
||||
@Override public PlotId parse(String in) {
|
||||
return PlotId.fromString(in);
|
||||
}
|
||||
};
|
||||
private final String name;
|
||||
private final T example;
|
||||
|
||||
public Argument(String name, T example) {
|
||||
this.name = name;
|
||||
this.example = example;
|
||||
}
|
||||
|
||||
public abstract T parse(String in);
|
||||
|
||||
@Override public final String toString() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public final T getExample() {
|
||||
return this.example;
|
||||
}
|
||||
}
|
@ -0,0 +1,596 @@
|
||||
package com.github.intellectualsites.plotsquared.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.file.YamlConfiguration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.commands.CommandCategory;
|
||||
import com.github.intellectualsites.plotsquared.plot.commands.MainCommand;
|
||||
import com.github.intellectualsites.plotsquared.plot.commands.RequiredType;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotMessage;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
// May be none
|
||||
private final ArrayList<Command> allCommands = new ArrayList<>();
|
||||
private final ArrayList<Command> dynamicCommands = new ArrayList<>();
|
||||
private final HashMap<String, Command> staticCommands = new HashMap<>();
|
||||
|
||||
// Parent command (may be null)
|
||||
private final Command parent;
|
||||
private final boolean isStatic;
|
||||
// The command ID
|
||||
private String id;
|
||||
private List<String> aliases;
|
||||
private RequiredType required;
|
||||
private String usage;
|
||||
private String description;
|
||||
private String perm;
|
||||
private boolean confirmation;
|
||||
private CommandCategory category;
|
||||
private Argument[] arguments;
|
||||
|
||||
public Command(Command parent, boolean isStatic, String id, String perm, RequiredType required,
|
||||
CommandCategory cat) {
|
||||
this.parent = parent;
|
||||
this.isStatic = isStatic;
|
||||
this.id = id;
|
||||
this.perm = perm;
|
||||
this.required = required;
|
||||
this.category = cat;
|
||||
this.aliases = Arrays.asList(id);
|
||||
if (this.parent != null) {
|
||||
this.parent.register(this);
|
||||
}
|
||||
}
|
||||
|
||||
public Command(Command parent, boolean isStatic) {
|
||||
this.parent = parent;
|
||||
this.isStatic = isStatic;
|
||||
Annotation cdAnnotation = getClass().getAnnotation(CommandDeclaration.class);
|
||||
if (cdAnnotation != null) {
|
||||
CommandDeclaration declaration = (CommandDeclaration) cdAnnotation;
|
||||
init(declaration);
|
||||
}
|
||||
for (final Method method : getClass().getDeclaredMethods()) {
|
||||
if (method.isAnnotationPresent(CommandDeclaration.class)) {
|
||||
Class<?>[] types = method.getParameterTypes();
|
||||
// final PlotPlayer player, String[] args, RunnableVal3<Command,Runnable,Runnable> confirm, RunnableVal2<Command, CommandResult>
|
||||
// whenDone
|
||||
if (types.length == 5 && types[0] == Command.class && types[1] == PlotPlayer.class
|
||||
&& types[2] == String[].class && types[3] == RunnableVal3.class
|
||||
&& types[4] == RunnableVal2.class) {
|
||||
Command tmp = new Command(this, true) {
|
||||
@Override public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) {
|
||||
try {
|
||||
method.invoke(Command.this, this, player, args, confirm, whenDone);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
tmp.init(method.getAnnotation(CommandDeclaration.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Command getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getFullId() {
|
||||
if (this.parent != null && this.parent.getParent() != null) {
|
||||
return this.parent.getFullId() + "." + this.id;
|
||||
}
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public List<Command> getCommands(PlotPlayer player) {
|
||||
List<Command> commands = new ArrayList<>();
|
||||
for (Command cmd : this.allCommands) {
|
||||
if (cmd.canExecute(player, false)) {
|
||||
commands.add(cmd);
|
||||
}
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
||||
public List<Command> getCommands(CommandCategory cat, PlotPlayer player) {
|
||||
List<Command> commands = getCommands(player);
|
||||
if (cat != null) {
|
||||
Iterator<Command> iterator = commands.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next().category != cat) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
||||
public List<Command> getCommands() {
|
||||
return this.allCommands;
|
||||
}
|
||||
|
||||
public boolean hasConfirmation(PlotPlayer player) {
|
||||
return this.confirmation && !player.hasPermission(getPermission() + ".confirm.bypass");
|
||||
}
|
||||
|
||||
public List<String> getAliases() {
|
||||
return this.aliases;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public RequiredType getRequiredType() {
|
||||
return this.required;
|
||||
}
|
||||
|
||||
public Argument[] getRequiredArguments() {
|
||||
return this.arguments;
|
||||
}
|
||||
|
||||
public void setRequiredArguments(Argument[] arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public void init(CommandDeclaration declaration) {
|
||||
this.id = declaration.command();
|
||||
this.perm = declaration.permission();
|
||||
this.required = declaration.requiredType();
|
||||
this.category = declaration.category();
|
||||
HashMap<String, Object> options = new HashMap<>();
|
||||
List<String> aliasOptions = new ArrayList<>();
|
||||
aliasOptions.add(this.id);
|
||||
aliasOptions.addAll(Arrays.asList(declaration.aliases()));
|
||||
options.put("aliases", aliasOptions);
|
||||
options.put("description", declaration.description());
|
||||
options.put("usage", declaration.usage());
|
||||
options.put("confirmation", declaration.confirmation());
|
||||
boolean set = false;
|
||||
YamlConfiguration commands =
|
||||
PlotSquared.get() == null ? new YamlConfiguration() : PlotSquared.get().commands;
|
||||
for (Map.Entry<String, Object> entry : options.entrySet()) {
|
||||
String key = this.getFullId() + "." + entry.getKey();
|
||||
if (!commands.contains(key)) {
|
||||
commands.set(key, entry.getValue());
|
||||
set = true;
|
||||
}
|
||||
}
|
||||
if (set && PlotSquared.get() != null) {
|
||||
try {
|
||||
commands.save(PlotSquared.get().commandsFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
}
|
||||
this.aliases = commands.getStringList(this.getFullId() + ".aliases");
|
||||
this.description = commands.getString(this.getFullId() + ".description");
|
||||
this.usage = commands.getString(this.getFullId() + ".usage");
|
||||
this.confirmation = commands.getBoolean(this.getFullId() + ".confirmation");
|
||||
if (this.parent != null) {
|
||||
this.parent.register(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void register(Command command) {
|
||||
if (command.isStatic) {
|
||||
for (String alias : command.aliases) {
|
||||
this.staticCommands.put(alias.toLowerCase(), command);
|
||||
}
|
||||
} else {
|
||||
this.dynamicCommands.add(command);
|
||||
}
|
||||
this.allCommands.add(command);
|
||||
}
|
||||
|
||||
public String getPermission() {
|
||||
if (this.perm != null && !this.perm.isEmpty()) {
|
||||
return this.perm;
|
||||
}
|
||||
if (this.parent == null) {
|
||||
return "plots.use";
|
||||
}
|
||||
return "plots." + getFullId();
|
||||
}
|
||||
|
||||
public <T> void paginate(PlotPlayer player, List<T> c, int size, int page,
|
||||
RunnableVal3<Integer, T, PlotMessage> add, String baseCommand, String header) {
|
||||
// Calculate pages & index
|
||||
if (page < 0) {
|
||||
page = 0;
|
||||
}
|
||||
int totalPages = (int) Math.ceil(c.size() / size);
|
||||
if (page > totalPages) {
|
||||
page = totalPages;
|
||||
}
|
||||
int max = page * size + size;
|
||||
if (max > c.size()) {
|
||||
max = c.size();
|
||||
}
|
||||
// Send the header
|
||||
header = header.replaceAll("%cur", page + 1 + "").replaceAll("%max", totalPages + 1 + "")
|
||||
.replaceAll("%amount%", c.size() + "").replaceAll("%word%", "all");
|
||||
MainUtil.sendMessage(player, header);
|
||||
// Send the page content
|
||||
List<T> subList = c.subList(page * size, max);
|
||||
int i = page * size;
|
||||
for (T obj : subList) {
|
||||
i++;
|
||||
PlotMessage msg = new PlotMessage();
|
||||
add.run(i, obj, msg);
|
||||
msg.send(player);
|
||||
}
|
||||
// Send the footer
|
||||
if (page < totalPages && page > 0) { // Back | Next
|
||||
new PlotMessage().text("<-").color("$1").command(baseCommand + " " + page).text(" | ")
|
||||
.color("$3").text("->").color("$1").command(baseCommand + " " + (page + 2))
|
||||
.text(C.CLICKABLE.s()).color("$2").send(player);
|
||||
return;
|
||||
}
|
||||
if (page == 0 && totalPages != 0) { // Next
|
||||
new PlotMessage().text("<-").color("$3").text(" | ").color("$3").text("->").color("$1")
|
||||
.command(baseCommand + " " + (0 + 2)).text(C.CLICKABLE.s()).color("$2")
|
||||
.send(player);
|
||||
return;
|
||||
}
|
||||
if (page == totalPages && totalPages != 0) { // Back
|
||||
new PlotMessage().text("<-").color("$1").command(baseCommand + " " + page).text(" | ")
|
||||
.color("$3").text("->").color("$3").text(C.CLICKABLE.s()).color("$2").send(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player Caller
|
||||
* @param args Arguments
|
||||
* @param confirm Instance, Success, Failure
|
||||
* @return
|
||||
*/
|
||||
public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
|
||||
if (args.length == 0 || args[0] == null) {
|
||||
if (this.parent == null) {
|
||||
MainCommand.getInstance().help.displayHelp(player, null, 0);
|
||||
} else {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.allCommands == null || this.allCommands.isEmpty()) {
|
||||
player.sendMessage(
|
||||
"Not Implemented: https://github.com/IntellectualSites/PlotSquared/issues/new");
|
||||
return;
|
||||
}
|
||||
Command cmd = getCommand(args[0]);
|
||||
if (cmd == null) {
|
||||
if (this.parent != null) {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return;
|
||||
}
|
||||
// Help command
|
||||
try {
|
||||
if (args.length == 0 || MathMan.isInteger(args[0])
|
||||
|| CommandCategory.valueOf(args[0].toUpperCase()) != null) {
|
||||
// This will default certain syntax to the help command
|
||||
// e.g. /plot, /plot 1, /plot claiming
|
||||
MainCommand.getInstance().help.execute(player, args, null, null);
|
||||
return;
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
// Command recommendation
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_SUBCOMMAND);
|
||||
List<Command> commands = getCommands(player);
|
||||
if (commands.isEmpty()) {
|
||||
MainUtil
|
||||
.sendMessage(player, C.DID_YOU_MEAN, MainCommand.getInstance().help.getUsage());
|
||||
return;
|
||||
}
|
||||
HashSet<String> setargs = new HashSet<>(args.length);
|
||||
for (String arg : args) {
|
||||
setargs.add(arg.toLowerCase());
|
||||
}
|
||||
String[] allargs = setargs.toArray(new String[setargs.size()]);
|
||||
int best = 0;
|
||||
for (Command current : commands) {
|
||||
int match = getMatch(allargs, current);
|
||||
if (match > best) {
|
||||
cmd = current;
|
||||
}
|
||||
}
|
||||
if (cmd == null) {
|
||||
cmd = new StringComparison<>(args[0], this.allCommands).getMatchObject();
|
||||
}
|
||||
MainUtil.sendMessage(player, C.DID_YOU_MEAN, cmd.getUsage());
|
||||
return;
|
||||
}
|
||||
String[] newArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
if (!cmd.checkArgs(player, newArgs) || !cmd.canExecute(player, true)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
cmd.execute(player, newArgs, confirm, whenDone);
|
||||
} catch (CommandException e) {
|
||||
e.perform(player);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkArgs(PlotPlayer player, String[] args) {
|
||||
Argument<?>[] reqArgs = getRequiredArguments();
|
||||
if (reqArgs != null && reqArgs.length > 0) {
|
||||
boolean failed = args.length < reqArgs.length;
|
||||
String[] baseSplit = getCommandString().split(" ");
|
||||
String[] fullSplit = getUsage().split(" ");
|
||||
String base = getCommandString();
|
||||
if (fullSplit.length - baseSplit.length < reqArgs.length) {
|
||||
String[] tmp = new String[baseSplit.length + reqArgs.length];
|
||||
System.arraycopy(fullSplit, 0, tmp, 0, fullSplit.length);
|
||||
fullSplit = tmp;
|
||||
}
|
||||
for (int i = 0; i < reqArgs.length; i++) {
|
||||
fullSplit[i + baseSplit.length] = reqArgs[i].getExample().toString();
|
||||
failed = failed || reqArgs[i].parse(args[i]) == null;
|
||||
}
|
||||
if (failed) {
|
||||
C.COMMAND_SYNTAX.send(player, StringMan.join(fullSplit, " "));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getMatch(String[] args, Command cmd) {
|
||||
int count = 0;
|
||||
String perm = cmd.getPermission();
|
||||
HashSet<String> desc = new HashSet<>();
|
||||
for (String alias : cmd.getAliases()) {
|
||||
if (alias.startsWith(args[0])) {
|
||||
count += 5;
|
||||
}
|
||||
}
|
||||
Collections.addAll(desc, cmd.getDescription().split(" "));
|
||||
for (String arg : args) {
|
||||
if (perm.startsWith(arg)) {
|
||||
count++;
|
||||
}
|
||||
if (desc.contains(arg)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
String[] usage = cmd.getUsage().split(" ");
|
||||
for (int i = 0; i < Math.min(4, usage.length); i++) {
|
||||
int require;
|
||||
if (usage[i].startsWith("<")) {
|
||||
require = 1;
|
||||
} else {
|
||||
require = 0;
|
||||
}
|
||||
String[] split = usage[i].split("\\|| |\\>|\\<|\\[|\\]|\\{|\\}|\\_|\\/");
|
||||
for (String aSplit : split) {
|
||||
for (String arg : args) {
|
||||
if (StringMan.isEqualIgnoreCase(arg, aSplit)) {
|
||||
count += 5 - i + require;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
count += StringMan.intersection(desc, args);
|
||||
return count;
|
||||
}
|
||||
|
||||
public Command getCommand(String arg) {
|
||||
Command cmd = this.staticCommands.get(arg.toLowerCase());
|
||||
if (cmd == null) {
|
||||
for (Command command : this.dynamicCommands) {
|
||||
if (command.matches(arg)) {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
public Command getCommand(Class clazz) {
|
||||
for (Command cmd : this.allCommands) {
|
||||
if (cmd.getClass() == clazz) {
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Command getCommandById(String id) {
|
||||
Command exact = this.staticCommands.get(id);
|
||||
if (exact != null) {
|
||||
return exact;
|
||||
}
|
||||
for (Command cmd : this.allCommands) {
|
||||
if (cmd.getId().equals(id)) {
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean canExecute(PlotPlayer player, boolean message) {
|
||||
if (player == null) {
|
||||
return true;
|
||||
}
|
||||
if (!this.required.allows(player)) {
|
||||
if (message) {
|
||||
MainUtil.sendMessage(player,
|
||||
this.required == RequiredType.PLAYER ? C.IS_CONSOLE : C.NOT_CONSOLE);
|
||||
}
|
||||
} else if (!Permissions.hasPermission(player, getPermission())) {
|
||||
if (message) {
|
||||
C.NO_PERMISSION.send(player, getPermission());
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean matches(String arg) {
|
||||
arg = arg.toLowerCase();
|
||||
return StringMan.isEqual(arg, this.id) || this.aliases.contains(arg);
|
||||
}
|
||||
|
||||
public String getCommandString() {
|
||||
String base;
|
||||
if (this.parent == null) {
|
||||
return "/" + toString();
|
||||
} else {
|
||||
return this.parent.getCommandString() + " " + toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
if (this.usage != null && !this.usage.isEmpty()) {
|
||||
if (this.usage.startsWith("/")) {
|
||||
return this.usage;
|
||||
}
|
||||
return getCommandString() + " " + this.usage;
|
||||
}
|
||||
if (this.allCommands.isEmpty()) {
|
||||
return getCommandString();
|
||||
}
|
||||
StringBuilder args = new StringBuilder("[");
|
||||
String prefix = "";
|
||||
for (Command cmd : this.allCommands) {
|
||||
args.append(prefix).append(cmd.isStatic ? cmd.toString() : "<" + cmd + ">");
|
||||
prefix = "|";
|
||||
}
|
||||
return getCommandString() + " " + args + "]";
|
||||
}
|
||||
|
||||
public Collection<Command> tabOf(PlotPlayer player, String[] input, boolean space,
|
||||
String... args) {
|
||||
if (!space) {
|
||||
return null;
|
||||
}
|
||||
List<Command> result = new ArrayList<>();
|
||||
int index = input.length - (space ? 0 : 1);
|
||||
for (String arg : args) {
|
||||
arg = arg.replace(getCommandString() + " ", "");
|
||||
String[] split = arg.split(" ");
|
||||
if (split.length <= index) {
|
||||
continue;
|
||||
}
|
||||
arg = StringMan.join(Arrays.copyOfRange(split, index, split.length), " ");
|
||||
Command cmd = new Command(null, false, arg, getPermission(), getRequiredType(), null) {
|
||||
};
|
||||
result.add(cmd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection<Command> tab(PlotPlayer player, String[] args, boolean space) {
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
return this.allCommands;
|
||||
case 1:
|
||||
String arg = args[0].toLowerCase();
|
||||
if (space) {
|
||||
Command cmd = getCommand(arg);
|
||||
if (cmd != null && cmd.canExecute(player, false)) {
|
||||
return cmd.tab(player, Arrays.copyOfRange(args, 1, args.length), space);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Set<Command> commands = new HashSet<Command>();
|
||||
for (Map.Entry<String, Command> entry : this.staticCommands.entrySet()) {
|
||||
if (entry.getKey().startsWith(arg) && entry.getValue()
|
||||
.canExecute(player, false)) {
|
||||
commands.add(entry.getValue());
|
||||
}
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
default:
|
||||
Command cmd = getCommand(args[0]);
|
||||
if (cmd != null) {
|
||||
return cmd.tab(player, Arrays.copyOfRange(args, 1, args.length), space);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return !this.aliases.isEmpty() ? this.aliases.get(0) : this.id;
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Command other = (Command) obj;
|
||||
if (this.hashCode() != other.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
return this.getFullId().equals(other.getFullId());
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return this.getFullId().hashCode();
|
||||
}
|
||||
|
||||
public void checkTrue(boolean mustBeTrue, C message, Object... args) {
|
||||
if (!mustBeTrue) {
|
||||
throw new CommandException(message, args);
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Object> T check(T object, C message, Object... args) {
|
||||
if (object == null) {
|
||||
throw new CommandException(message, args);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
public enum CommandResult {
|
||||
FAILURE, SUCCESS
|
||||
}
|
||||
|
||||
|
||||
public static class CommandException extends RuntimeException {
|
||||
private final Object[] args;
|
||||
private final C message;
|
||||
|
||||
public CommandException(C message, Object... args) {
|
||||
this.message = message;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public void perform(PlotPlayer player) {
|
||||
if (player != null && message != null) {
|
||||
message.send(player, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.github.intellectualsites.plotsquared.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.plot.commands.RequiredType;
|
||||
|
||||
public interface CommandCaller {
|
||||
|
||||
/**
|
||||
* Send the player a message.
|
||||
*
|
||||
* @param message the message to send
|
||||
*/
|
||||
void sendMessage(String message);
|
||||
|
||||
/**
|
||||
* Check the player's permissions. <i>Will be cached if permission caching is enabled.</i>
|
||||
*
|
||||
* @param permission the name of the permission
|
||||
*/
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
boolean isPermissionSet(String permission);
|
||||
|
||||
RequiredType getSuperCaller();
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.github.intellectualsites.plotsquared.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.plot.commands.CommandCategory;
|
||||
import com.github.intellectualsites.plotsquared.plot.commands.RequiredType;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandDeclaration {
|
||||
|
||||
String command();
|
||||
|
||||
String[] aliases() default {};
|
||||
|
||||
String permission() default "";
|
||||
|
||||
String usage() default "";
|
||||
|
||||
String description() default "";
|
||||
|
||||
RequiredType requiredType() default RequiredType.NONE;
|
||||
|
||||
CommandCategory category() default CommandCategory.INFO;
|
||||
|
||||
boolean confirmation() default false;
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a source of configurable options and settings.
|
||||
*/
|
||||
public interface Configuration extends ConfigurationSection {
|
||||
/**
|
||||
* Sets the default value of the given path as provided.
|
||||
* <p>
|
||||
* <p>If no source {@link Configuration} was provided as a default
|
||||
* collection, then a new {@link MemoryConfiguration} will be created to
|
||||
* hold the new default value.</p>
|
||||
* <p>
|
||||
* <p>If value is null, the value will be removed from the default
|
||||
* Configuration source.</p>
|
||||
*
|
||||
* @param path Path of the value to set.
|
||||
* @param value Value to set the default to.
|
||||
* @throws IllegalArgumentException Thrown if path is null.
|
||||
*/
|
||||
@Override void addDefault(@Nonnull String path, Object value);
|
||||
|
||||
/**
|
||||
* Sets the default values of the given paths as provided.
|
||||
* <p>
|
||||
* <p>If no source {@link Configuration} was provided as a default
|
||||
* collection, then a new {@link MemoryConfiguration} will be created to
|
||||
* hold the new default values.</p>
|
||||
*
|
||||
* @param defaults A map of Path->Values to add to defaults.
|
||||
* @throws IllegalArgumentException Thrown if defaults is null.
|
||||
*/
|
||||
void addDefaults(Map<String, Object> defaults);
|
||||
|
||||
/**
|
||||
* Sets the default values of the given paths as provided.
|
||||
* <p>
|
||||
* <p>If no source {@link Configuration} was provided as a default
|
||||
* collection, then a new {@link MemoryConfiguration} will be created to
|
||||
* hold the new default value.</p>
|
||||
* <p>
|
||||
* <p>This method will not hold a reference to the specified Configuration,
|
||||
* nor will it automatically update if that Configuration ever changes. If
|
||||
* you check this, you should set the default source with {@link
|
||||
* #setDefaults(Configuration)}.</p>
|
||||
*
|
||||
* @param defaults A configuration holding a list of defaults to copy.
|
||||
* @throws IllegalArgumentException Thrown if defaults is null or this.
|
||||
*/
|
||||
void addDefaults(Configuration defaults);
|
||||
|
||||
/**
|
||||
* Gets the source {@link Configuration} for this configuration.
|
||||
* <p>
|
||||
* <p>
|
||||
* If no configuration source was set, but default values were added, then
|
||||
* a {@link MemoryConfiguration} will be returned. If no source was set
|
||||
* and no defaults were set, then this method will return null.</p>
|
||||
*
|
||||
* @return Configuration source for default values, or null if none exist.
|
||||
*/
|
||||
Configuration getDefaults();
|
||||
|
||||
/**
|
||||
* Sets the source of all default values for this {@link Configuration}.
|
||||
* <p>
|
||||
* <p>
|
||||
* If a previous source was set, or previous default values were defined,
|
||||
* then they will not be copied to the new source.</p>
|
||||
*
|
||||
* @param defaults New source of default values for this configuration.
|
||||
* @throws IllegalArgumentException Thrown if defaults is null or this.
|
||||
*/
|
||||
void setDefaults(Configuration defaults);
|
||||
|
||||
/**
|
||||
* Gets the {@link ConfigurationOptions} for this {@link Configuration}.
|
||||
* <p>
|
||||
* <p>All setters through this method are chainable.</p>
|
||||
*
|
||||
* @return Options for this configuration
|
||||
*/
|
||||
ConfigurationOptions options();
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* Configuration}.
|
||||
*/
|
||||
class ConfigurationOptions {
|
||||
private final Configuration configuration;
|
||||
private char pathSeparator = '.';
|
||||
private boolean copyDefaults = false;
|
||||
|
||||
protected ConfigurationOptions(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Configuration} that this object is responsible for.
|
||||
*
|
||||
* @return Parent configuration
|
||||
*/
|
||||
public Configuration configuration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the char that will be used to separate {@link
|
||||
* ConfigurationSection}s.
|
||||
*
|
||||
* <p>This value does not affect how the {@link Configuration} is stored,
|
||||
* only in how you access the data. The default value is '.'.
|
||||
*
|
||||
* @return Path separator
|
||||
*/
|
||||
char pathSeparator() {
|
||||
return pathSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the char that will be used to separate {@link
|
||||
* ConfigurationSection}s.
|
||||
*
|
||||
* <p>This value does not affect how the {@link Configuration} is stored,
|
||||
* only in how you access the data. The default value is '.'.
|
||||
*
|
||||
* @param value Path separator
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public ConfigurationOptions pathSeparator(char value) {
|
||||
pathSeparator = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@link Configuration} should copy values from its default
|
||||
* {@link Configuration} directly.
|
||||
*
|
||||
* <p>If this is true, all values in the default Configuration will be
|
||||
* directly copied, making it impossible to distinguish between values
|
||||
* that were set and values that are provided by default. As a result,
|
||||
* {@link ConfigurationSection#contains(String)} will always
|
||||
* return the same value as {@link
|
||||
* ConfigurationSection#isSet(String)}. The default value is
|
||||
* false.
|
||||
*
|
||||
* @return Whether or not defaults are directly copied
|
||||
*/
|
||||
boolean copyDefaults() {
|
||||
return copyDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the {@link Configuration} should copy values from its default
|
||||
* {@link Configuration} directly.
|
||||
*
|
||||
* <p>If this is true, all values in the default Configuration will be
|
||||
* directly copied, making it impossible to distinguish between values
|
||||
* that were set and values that are provided by default. As a result,
|
||||
* {@link ConfigurationSection#contains(String)} will always
|
||||
* return the same value as {@link
|
||||
* ConfigurationSection#isSet(String)}. The default value is
|
||||
* false.
|
||||
*
|
||||
* @param value Whether or not defaults are directly copied
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public ConfigurationOptions copyDefaults(boolean value) {
|
||||
copyDefaults = value;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,649 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a section of a {@link Configuration}.
|
||||
*/
|
||||
public interface ConfigurationSection {
|
||||
|
||||
/**
|
||||
* Gets a set containing all keys in this section.
|
||||
*
|
||||
* <p>If deep is set to true, then this will contain all the keys within any
|
||||
* child {@link ConfigurationSection}s (and their children, etc). These
|
||||
* will be in a valid path notation for you to use.
|
||||
*
|
||||
* <p>If deep is set to false, then this will contain only the keys of any
|
||||
* direct children, and not their own children.
|
||||
*
|
||||
* @param deep Whether or not to get a deep list, as opposed to a shallow
|
||||
* list.
|
||||
* @return Set of keys contained within this ConfigurationSection.
|
||||
*/
|
||||
Set<String> getKeys(boolean deep);
|
||||
|
||||
/**
|
||||
* Gets a Map containing all keys and their values for this section.
|
||||
*
|
||||
* <p>If deep is set to true, then this will contain all the keys and values
|
||||
* within any child {@link ConfigurationSection}s (and their children,
|
||||
* etc). These keys will be in a valid path notation for you to use.
|
||||
*
|
||||
* <p>If deep is set to false, then this will contain only the keys and
|
||||
* values of any direct children, and not their own children.
|
||||
*
|
||||
* @param deep Whether or not to get a deep list, as opposed to a shallow
|
||||
* list.
|
||||
* @return Map of keys and values of this section.
|
||||
*/
|
||||
Map<String, Object> getValues(boolean deep);
|
||||
|
||||
/**
|
||||
* Checks if this {@link ConfigurationSection} contains the given path.
|
||||
*
|
||||
* <p>If the value for the requested path does not exist but a default value
|
||||
* has been specified, this will return true.
|
||||
*
|
||||
* @param path Path to check for existence.
|
||||
* @return True if this section contains the requested path, either via
|
||||
* default or being set.
|
||||
* @throws IllegalArgumentException Thrown when path is {@code null}.
|
||||
*/
|
||||
boolean contains(@Nonnull String path);
|
||||
|
||||
/**
|
||||
* Checks if this {@link ConfigurationSection} has a value set for the
|
||||
* given path.
|
||||
*
|
||||
* <p>If the value for the requested path does not exist but a default value
|
||||
* has been specified, this will still return false.
|
||||
*
|
||||
* @param path Path to check for existence.
|
||||
* @return True if this section contains the requested path, regardless of
|
||||
* having a default.
|
||||
* @throws IllegalArgumentException Thrown when path is {@code null}.
|
||||
*/
|
||||
boolean isSet(@Nonnull String path);
|
||||
|
||||
/**
|
||||
* Gets the path of this {@link ConfigurationSection} from its root {@link
|
||||
* Configuration}.
|
||||
*
|
||||
* <p>For any {@link Configuration} themselves, this will return an empty
|
||||
* string.
|
||||
*
|
||||
* <p>If the section is no longer contained within its root for any reason,
|
||||
* such as being replaced with a different value,
|
||||
* this may return {@code null}.
|
||||
*
|
||||
* <p>To retrieve the single name of this section, that is, the final part
|
||||
* of the path returned by this method, you may use {@link #getName()}.
|
||||
*
|
||||
* @return Path of this section relative to its root
|
||||
*/
|
||||
String getCurrentPath();
|
||||
|
||||
/**
|
||||
* Gets the name of this individual {@link ConfigurationSection}, in the
|
||||
* path.
|
||||
*
|
||||
* <p>This will always be the final part of {@link #getCurrentPath()}, unless
|
||||
* the section is orphaned.
|
||||
*
|
||||
* @return Name of this section
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the root {@link Configuration} that contains this {@link
|
||||
* ConfigurationSection}
|
||||
*
|
||||
* <p>For any {@link Configuration} themselves, this will return its own
|
||||
* object.
|
||||
*
|
||||
* <p>If the section is no longer contained within its root for any reason,
|
||||
* such as being replaced with a different value,
|
||||
* this may return {@code null}.
|
||||
*
|
||||
* @return Root configuration containing this section.
|
||||
*/
|
||||
Configuration getRoot();
|
||||
|
||||
/**
|
||||
* Gets the parent {@link ConfigurationSection} that directly contains
|
||||
* this {@link ConfigurationSection}.
|
||||
*
|
||||
* <p>For any {@link Configuration} themselves, this will return
|
||||
* {@code null}.
|
||||
*
|
||||
* <p>If the section is no longer contained within its parent for any
|
||||
* reason, such as being replaced with a different value, this may
|
||||
* return {@code null}.
|
||||
*
|
||||
* @return Parent section containing this section.
|
||||
*/
|
||||
ConfigurationSection getParent();
|
||||
|
||||
/**
|
||||
* Gets the requested Object by path.
|
||||
*
|
||||
* <p>If the Object does not exist but a default value has been specified,
|
||||
* this will return the default value. If the Object does not exist and no
|
||||
* default value was specified, this will return {@code null}.
|
||||
*
|
||||
* @param path Path of the Object to get.
|
||||
* @return Requested Object.
|
||||
*/
|
||||
Object get(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested Object by path, returning a default value if not
|
||||
* found.
|
||||
*
|
||||
* <p>If the Object does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the Object to get.
|
||||
* @param defaultValue The default value to return if the path is not found.
|
||||
* @return Requested Object.
|
||||
*/
|
||||
Object getOrDefault(@Nonnull String path, Object defaultValue);
|
||||
|
||||
/**
|
||||
* Sets the specified path to the given value.
|
||||
*
|
||||
* <p>If value is {@code null}, the entry will be removed. Any
|
||||
* existing entry will be replaced, regardless of what the new value is.
|
||||
*
|
||||
* <p>Some implementations may have limitations on what you may store. See
|
||||
* their individual javadoc for details. No implementations should allow
|
||||
* you to store {@link Configuration}s or {@link ConfigurationSection}s,
|
||||
* please use {@link #createSection(String)} for that.
|
||||
*
|
||||
* @param path Path of the object to set.
|
||||
* @param value New value to set the path to.
|
||||
*/
|
||||
void set(String path, Object value);
|
||||
|
||||
/**
|
||||
* Creates an empty {@link ConfigurationSection} at the specified path.
|
||||
*
|
||||
* <p>Any value that was previously set at this path will be overwritten. If
|
||||
* the previous value was itself a {@link ConfigurationSection}, it will
|
||||
* be orphaned.
|
||||
*
|
||||
* @param path Path to create the section at.
|
||||
* @return Newly created section
|
||||
*/
|
||||
ConfigurationSection createSection(String path);
|
||||
|
||||
/**
|
||||
* Creates a {@link ConfigurationSection} at the specified path, with
|
||||
* specified values.
|
||||
*
|
||||
* <p>Any value that was previously set at this path will be overwritten. If
|
||||
* the previous value was itself a {@link ConfigurationSection}, it will
|
||||
* be orphaned.
|
||||
*
|
||||
* @param path Path to create the section at.
|
||||
* @param map The values to used.
|
||||
* @return Newly created section
|
||||
*/
|
||||
ConfigurationSection createSection(String path, Map<?, ?> map);
|
||||
|
||||
// Primitives
|
||||
|
||||
/**
|
||||
* Gets the requested String by path.
|
||||
*
|
||||
* <p>If the String does not exist but a default value has been specified,
|
||||
* this will return the default value. If the String does not exist and no
|
||||
* default value was specified, this will return {@code null}.
|
||||
*
|
||||
* @param path Path of the String to get.
|
||||
* @return Requested String.
|
||||
*/
|
||||
String getString(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested String by path, returning a default value if not
|
||||
* found.
|
||||
*
|
||||
* <p>If the String does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the String to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a String.
|
||||
* @return Requested String.
|
||||
*/
|
||||
String getString(String path, String def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a String.
|
||||
*
|
||||
* <p>If the path exists but is not a String, this will return false. If
|
||||
* the path does not exist, this will return false. If the path does not
|
||||
* exist but a default value has been specified, this will check if that
|
||||
* defaultvalue is a String and return appropriately.
|
||||
*
|
||||
* @param path Path of the String to check.
|
||||
* @return Whether or not the specified path is a String.
|
||||
*/
|
||||
boolean isString(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested int by path.
|
||||
*
|
||||
* <p>If the int does not exist but a default value has been specified, this
|
||||
* will return the default value. If the int does not exist and no default
|
||||
* value was specified, this will return 0.
|
||||
*
|
||||
* @param path Path of the int to get.
|
||||
* @return Requested int.
|
||||
*/
|
||||
int getInt(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested int by path, returning a default value if not found.
|
||||
*
|
||||
* <p>If the int does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the int to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not an int.
|
||||
* @return Requested int.
|
||||
*/
|
||||
int getInt(String path, int def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is an int.
|
||||
*
|
||||
* <p>If the path exists but is not a int, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a int and return appropriately.
|
||||
*
|
||||
* @param path Path of the int to check.
|
||||
* @return Whether or not the specified path is an int.
|
||||
*/
|
||||
boolean isInt(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested boolean by path.
|
||||
*
|
||||
* <p>If the boolean does not exist but a default value has been specified,
|
||||
* this will return the default value. If the boolean does not exist and
|
||||
* no default value was specified, this will return false.
|
||||
*
|
||||
* @param path Path of the boolean to get.
|
||||
* @return Requested boolean.
|
||||
*/
|
||||
boolean getBoolean(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested boolean by path, returning a default value if not
|
||||
* found.
|
||||
*
|
||||
* <p>If the boolean does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the boolean to get.
|
||||
* @param defaultValue The default value to return if the path is not found or is
|
||||
* not a boolean.
|
||||
* @return Requested boolean.
|
||||
*/
|
||||
boolean getBoolean(String path, boolean defaultValue);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a boolean.
|
||||
*
|
||||
* <p>If the path exists but is not a boolean, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a boolean and return appropriately.
|
||||
*
|
||||
* @param path Path of the boolean to check.
|
||||
* @return Whether or not the specified path is a boolean.
|
||||
*/
|
||||
boolean isBoolean(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested double by path.
|
||||
*
|
||||
* <p>If the double does not exist but a default value has been specified,
|
||||
* this will return the default value. If the double does not exist and no
|
||||
* default value was specified, this will return 0.
|
||||
*
|
||||
* @param path Path of the double to get.
|
||||
* @return Requested double.
|
||||
*/
|
||||
double getDouble(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested double by path, returning a default value if not
|
||||
* found.
|
||||
*
|
||||
* <p>If the double does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the double to get.
|
||||
* @param defaultValue The default value to return if the path is not found or is
|
||||
* not a double.
|
||||
* @return Requested double.
|
||||
*/
|
||||
double getDouble(String path, double defaultValue);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a double.
|
||||
*
|
||||
* <p>If the path exists but is not a double, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a double and return appropriately.
|
||||
*
|
||||
* @param path Path of the double to check.
|
||||
* @return Whether or not the specified path is a double.
|
||||
*/
|
||||
boolean isDouble(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested long by path.
|
||||
*
|
||||
* <p>If the long does not exist but a default value has been specified, this
|
||||
* will return the default value. If the long does not exist and no
|
||||
* default value was specified, this will return 0.
|
||||
*
|
||||
* @param path Path of the long to get.
|
||||
* @return Requested long.
|
||||
*/
|
||||
long getLong(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested long by path, returning a default value if not
|
||||
* found.
|
||||
*
|
||||
* <p>If the long does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the long to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a long.
|
||||
* @return Requested long.
|
||||
*/
|
||||
long getLong(String path, long def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a long.
|
||||
*
|
||||
* <p>If the path exists but is not a long, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a long and return appropriately.
|
||||
*
|
||||
* @param path Path of the long to check.
|
||||
* @return Whether or not the specified path is a long.
|
||||
*/
|
||||
boolean isLong(String path);
|
||||
|
||||
// Java
|
||||
|
||||
/**
|
||||
* Gets the requested List by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return null.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List.
|
||||
*/
|
||||
List<?> getList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List by path, returning a default value if not
|
||||
* found.
|
||||
*
|
||||
* <p>If the List does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link Configuration}.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a List.
|
||||
* @return Requested List.
|
||||
*/
|
||||
List<?> getList(String path, List<?> def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a List.
|
||||
*
|
||||
* <p>If the path exists but is not a List, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a List and return appropriately.
|
||||
*
|
||||
* @param path Path of the List to check.
|
||||
* @return Whether or not the specified path is a List.
|
||||
*/
|
||||
boolean isList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of String by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a String if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of String.
|
||||
*/
|
||||
List<String> getStringList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Integer by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Integer if
|
||||
* possible, but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Integer.
|
||||
*/
|
||||
List<Integer> getIntegerList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Boolean by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Boolean if
|
||||
* possible, but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Boolean.
|
||||
*/
|
||||
List<Boolean> getBooleanList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Double by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Double if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Double.
|
||||
*/
|
||||
List<Double> getDoubleList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Float by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Float if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Float.
|
||||
*/
|
||||
List<Float> getFloatList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Long by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Long if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Long.
|
||||
*/
|
||||
List<Long> getLongList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Byte by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Byte if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Byte.
|
||||
*/
|
||||
List<Byte> getByteList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Character by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Character if
|
||||
* possible, but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Character.
|
||||
*/
|
||||
List<Character> getCharacterList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Short by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
*
|
||||
* <p>This method will attempt to cast any values into a Short if
|
||||
* possible, but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Short.
|
||||
*/
|
||||
List<Short> getShortList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Maps by path.
|
||||
*
|
||||
* <p>If the List does not exist but a default value has been specified,
|
||||
* this will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>This method will attempt to cast any values into a Map if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Maps.
|
||||
*/
|
||||
List<Map<?, ?>> getMapList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested ConfigurationSection by path.
|
||||
*
|
||||
* <p>If the ConfigurationSection does not exist but a default value has
|
||||
* been specified, this will return the default value. If the
|
||||
* ConfigurationSection does not exist and no default value was specified,
|
||||
* this will return {@code null}.
|
||||
*
|
||||
* @param path Path of the ConfigurationSection to get.
|
||||
* @return Requested ConfigurationSection.
|
||||
*/
|
||||
ConfigurationSection getConfigurationSection(String path);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a ConfigurationSection.
|
||||
*
|
||||
* <p>If the path exists but is not a ConfigurationSection, this will return
|
||||
* false. If the path does not exist, this will return false. If the path
|
||||
* does not exist but a default value has been specified, this will check
|
||||
* if that default value is a ConfigurationSection and return
|
||||
* appropriately.
|
||||
*
|
||||
* @param path Path of the ConfigurationSection to check.
|
||||
* @return Whether or not the specified path is a ConfigurationSection.
|
||||
*/
|
||||
boolean isConfigurationSection(String path);
|
||||
|
||||
/**
|
||||
* Gets the equivalent {@link ConfigurationSection} from the default
|
||||
* {@link Configuration} defined in {@link #getRoot()}.
|
||||
*
|
||||
* <p>If the root contains no defaults, or the defaults doesn't contain a
|
||||
* value for this path, or the value at this path is not a {@link
|
||||
* ConfigurationSection} then this will return {@code null}.
|
||||
*
|
||||
* @return Equivalent section in root configuration
|
||||
*/
|
||||
ConfigurationSection getDefaultSection();
|
||||
|
||||
/**
|
||||
* Sets the default value in the root at the given path as provided.
|
||||
*
|
||||
* <p>If no source {@link Configuration} was provided as a default
|
||||
* collection, then a new {@link MemoryConfiguration} will be created to
|
||||
* hold the new default value.
|
||||
*
|
||||
* <p>If value is {@code null}, the value will be removed from the
|
||||
* default Configuration source.
|
||||
*
|
||||
* <p>If the value as returned by {@link #getDefaultSection()} is
|
||||
* {@code null}, then this will create a new section at the path,
|
||||
* replacing anything that may have existed there previously.
|
||||
*
|
||||
* @param path Path of the value to set
|
||||
* @param value Value to set the default to
|
||||
* @throws IllegalArgumentException Thrown if path is {@code null}
|
||||
*/
|
||||
void addDefault(@Nonnull String path, Object value);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration;
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to load an invalid {@link Configuration}.
|
||||
*/
|
||||
@SuppressWarnings("serial") public class InvalidConfigurationException extends Exception {
|
||||
|
||||
/**
|
||||
* Creates a new instance of InvalidConfigurationException without a
|
||||
* message or cause.
|
||||
*/
|
||||
public InvalidConfigurationException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of InvalidConfigurationException with the
|
||||
* specified message.
|
||||
*
|
||||
* @param msg The details of the exception.
|
||||
*/
|
||||
public InvalidConfigurationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of InvalidConfigurationException with the
|
||||
* specified cause.
|
||||
*
|
||||
* @param cause The cause of the exception.
|
||||
*/
|
||||
public InvalidConfigurationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of InvalidConfigurationException with the
|
||||
* specified message and cause.
|
||||
*
|
||||
* @param cause The cause of the exception.
|
||||
* @param msg The details of the exception.
|
||||
*/
|
||||
public InvalidConfigurationException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is a {@link Configuration} implementation that does not save or load
|
||||
* from any source, and stores all values in memory only.
|
||||
* This is useful for temporary Configurations for providing defaults.
|
||||
*/
|
||||
public class MemoryConfiguration extends MemorySection implements Configuration {
|
||||
protected Configuration defaults;
|
||||
protected MemoryConfigurationOptions options;
|
||||
|
||||
/**
|
||||
* Creates an empty {@link MemoryConfiguration} with no default values.
|
||||
*/
|
||||
public MemoryConfiguration() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty {@link MemoryConfiguration} using the specified {@link
|
||||
* Configuration} as a source for all default values.
|
||||
*
|
||||
* @param defaults Default value provider
|
||||
* @throws IllegalArgumentException Thrown if defaults is null
|
||||
*/
|
||||
public MemoryConfiguration(Configuration defaults) {
|
||||
this.defaults = defaults;
|
||||
}
|
||||
|
||||
@Override public void addDefault(@Nonnull String path, Object value) {
|
||||
if (this.defaults == null) {
|
||||
this.defaults = new MemoryConfiguration();
|
||||
}
|
||||
|
||||
this.defaults.set(path, value);
|
||||
}
|
||||
|
||||
@Override public void addDefaults(Map<String, Object> defaults) {
|
||||
for (Map.Entry<String, Object> entry : defaults.entrySet()) {
|
||||
addDefault(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void addDefaults(Configuration defaults) {
|
||||
addDefaults(defaults.getValues(true));
|
||||
}
|
||||
|
||||
@Override public Configuration getDefaults() {
|
||||
return this.defaults;
|
||||
}
|
||||
|
||||
@Override public void setDefaults(Configuration defaults) {
|
||||
if (defaults == null) {
|
||||
throw new NullPointerException("Defaults may not be null");
|
||||
}
|
||||
|
||||
this.defaults = defaults;
|
||||
}
|
||||
|
||||
@Override public ConfigurationSection getParent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public MemoryConfigurationOptions options() {
|
||||
if (this.options == null) {
|
||||
this.options = new MemoryConfigurationOptions(this);
|
||||
}
|
||||
|
||||
return this.options;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* MemoryConfiguration}.
|
||||
*/
|
||||
public class MemoryConfigurationOptions extends ConfigurationOptions {
|
||||
protected MemoryConfigurationOptions(MemoryConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override public MemoryConfiguration configuration() {
|
||||
return (MemoryConfiguration) super.configuration();
|
||||
}
|
||||
|
||||
@Override public MemoryConfigurationOptions copyDefaults(boolean value) {
|
||||
super.copyDefaults(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public MemoryConfigurationOptions pathSeparator(char value) {
|
||||
super.pathSeparator(value);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,771 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A type of {@link ConfigurationSection} that is stored in memory.
|
||||
*/
|
||||
public class MemorySection implements ConfigurationSection {
|
||||
|
||||
protected final Map<String, Object> map = new LinkedHashMap<>();
|
||||
private final Configuration root;
|
||||
private final ConfigurationSection parent;
|
||||
private final String path;
|
||||
private final String fullPath;
|
||||
|
||||
/**
|
||||
* Creates an empty MemorySection for use as a root {@link Configuration} section.
|
||||
*
|
||||
* <p>Note that calling this without being yourself a {@link Configuration}
|
||||
* will throw an exception!
|
||||
*
|
||||
* @throws IllegalStateException Thrown if this is not a {@link Configuration} root.
|
||||
*/
|
||||
protected MemorySection() {
|
||||
if (!(this instanceof Configuration)) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot construct a root MemorySection when not a Configuration");
|
||||
}
|
||||
|
||||
this.path = "";
|
||||
this.fullPath = "";
|
||||
this.parent = null;
|
||||
this.root = (Configuration) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty MemorySection with the specified parent and path.
|
||||
*
|
||||
* @param parent Parent section that contains this own section.
|
||||
* @param path Path that you may access this section from via the root {@link Configuration}.
|
||||
* @throws IllegalArgumentException Thrown is parent or path is null, or if parent contains no
|
||||
* root Configuration.
|
||||
*/
|
||||
protected MemorySection(ConfigurationSection parent, String path) {
|
||||
this.path = path;
|
||||
this.parent = parent;
|
||||
this.root = parent.getRoot();
|
||||
|
||||
if (this.root == null) {
|
||||
throw new NullPointerException("Path may not be orphaned");
|
||||
}
|
||||
|
||||
this.fullPath = createPath(parent, path);
|
||||
}
|
||||
|
||||
public static double toDouble(Object obj, double def) {
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).doubleValue();
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
try {
|
||||
return Double.parseDouble((String) obj);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (obj instanceof List) {
|
||||
List<?> val = (List<?>) obj;
|
||||
if (!val.isEmpty()) {
|
||||
return toDouble(val.get(0), def);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static int toInt(Object obj, int def) {
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).intValue();
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
try {
|
||||
return Integer.parseInt((String) obj);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (obj instanceof List) {
|
||||
List<?> val = (List<?>) obj;
|
||||
if (!val.isEmpty()) {
|
||||
return toInt(val.get(0), def);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static long toLong(Object obj, long def) {
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).longValue();
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
try {
|
||||
return Long.parseLong((String) obj);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (obj instanceof List) {
|
||||
List<?> val = (List<?>) obj;
|
||||
if (!val.isEmpty()) {
|
||||
return toLong(val.get(0), def);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a full path to the given {@link ConfigurationSection} from its root {@link
|
||||
* Configuration}.
|
||||
*
|
||||
* <p>You may use this method for any given {@link ConfigurationSection}, not
|
||||
* only {@link MemorySection}.
|
||||
*
|
||||
* @param section Section to create a path for.
|
||||
* @param key Name of the specified section.
|
||||
* @return Full path of the section from its root.
|
||||
*/
|
||||
public static String createPath(ConfigurationSection section, String key) {
|
||||
return createPath(section, key, section.getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a relative path to the given {@link ConfigurationSection} from the given relative
|
||||
* section.
|
||||
*
|
||||
* <p>You may use this method for any given {@link ConfigurationSection}, not
|
||||
* only {@link MemorySection}.
|
||||
*
|
||||
* @param section Section to create a path for.
|
||||
* @param key Name of the specified section.
|
||||
* @param relativeTo Section to create the path relative to.
|
||||
* @return Full path of the section from its root.
|
||||
*/
|
||||
public static String createPath(ConfigurationSection section, String key,
|
||||
ConfigurationSection relativeTo) {
|
||||
Configuration root = section.getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot create path without a root");
|
||||
}
|
||||
char separator = root.options().pathSeparator();
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (ConfigurationSection parent = section;
|
||||
(parent != null) && (parent != relativeTo); parent = parent.getParent()) {
|
||||
if (builder.length() > 0) {
|
||||
builder.insert(0, separator);
|
||||
}
|
||||
|
||||
builder.insert(0, parent.getName());
|
||||
}
|
||||
|
||||
if ((key != null) && !key.isEmpty()) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append(separator);
|
||||
}
|
||||
|
||||
builder.append(key);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override public Set<String> getKeys(boolean deep) {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
|
||||
Configuration root = getRoot();
|
||||
if ((root != null) && root.options().copyDefaults()) {
|
||||
ConfigurationSection defaults = getDefaultSection();
|
||||
|
||||
if (defaults != null) {
|
||||
result.addAll(defaults.getKeys(deep));
|
||||
}
|
||||
}
|
||||
|
||||
mapChildrenKeys(result, this, deep);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public Map<String, Object> getValues(boolean deep) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
|
||||
Configuration root = getRoot();
|
||||
if ((root != null) && root.options().copyDefaults()) {
|
||||
ConfigurationSection defaults = getDefaultSection();
|
||||
|
||||
if (defaults != null) {
|
||||
result.putAll(defaults.getValues(deep));
|
||||
}
|
||||
}
|
||||
|
||||
mapChildrenValues(result, this, deep);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public boolean contains(@Nonnull String path) {
|
||||
return get(path) != null;
|
||||
}
|
||||
|
||||
@Override public boolean isSet(@Nonnull String path) {
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
return false;
|
||||
}
|
||||
if (root.options().copyDefaults()) {
|
||||
return contains(path);
|
||||
}
|
||||
return getOrDefault(path, null) != null;
|
||||
}
|
||||
|
||||
@Override public String getCurrentPath() {
|
||||
return this.fullPath;
|
||||
}
|
||||
|
||||
@Override public String getName() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@Override public Configuration getRoot() {
|
||||
return this.root;
|
||||
}
|
||||
|
||||
@Override public ConfigurationSection getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
@Override public void addDefault(@Nonnull String path, Object value) {
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot add default without root");
|
||||
}
|
||||
if (root == this) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported addDefault(String, Object) implementation");
|
||||
}
|
||||
root.addDefault(createPath(this, path), value);
|
||||
}
|
||||
|
||||
@Override public ConfigurationSection getDefaultSection() {
|
||||
Configuration root = getRoot();
|
||||
Configuration defaults = root == null ? null : root.getDefaults();
|
||||
|
||||
if (defaults != null) {
|
||||
if (defaults.isConfigurationSection(getCurrentPath())) {
|
||||
return defaults.getConfigurationSection(getCurrentPath());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public void set(String path, Object value) {
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot use section without a root");
|
||||
}
|
||||
|
||||
char separator = root.options().pathSeparator();
|
||||
// i1 is the leading (higher) index
|
||||
// i2 is the trailing (lower) index
|
||||
int i1 = -1;
|
||||
int i2;
|
||||
ConfigurationSection section = this;
|
||||
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
|
||||
String node = path.substring(i2, i1);
|
||||
ConfigurationSection subSection = section.getConfigurationSection(node);
|
||||
if (subSection == null) {
|
||||
section = section.createSection(node);
|
||||
} else {
|
||||
section = subSection;
|
||||
}
|
||||
}
|
||||
|
||||
String key = path.substring(i2);
|
||||
if (section == this) {
|
||||
if (value == null) {
|
||||
this.map.remove(key);
|
||||
} else {
|
||||
this.map.put(key, value);
|
||||
}
|
||||
} else {
|
||||
section.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public Object get(String path) {
|
||||
return getOrDefault(path, getDefault(path));
|
||||
}
|
||||
|
||||
@Override public Object getOrDefault(@Nonnull String path, Object defaultValue) {
|
||||
if (path.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot access section without a root");
|
||||
}
|
||||
|
||||
char separator = root.options().pathSeparator();
|
||||
// i1 is the leading (higher) index
|
||||
// i2 is the trailing (lower) index
|
||||
int i1 = -1;
|
||||
int i2;
|
||||
ConfigurationSection section = this;
|
||||
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
|
||||
section = section.getConfigurationSection(path.substring(i2, i1));
|
||||
if (section == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
String key = path.substring(i2);
|
||||
if (section == this) {
|
||||
Object result = this.map.get(key);
|
||||
if (result == null) {
|
||||
return defaultValue;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return section.getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override public ConfigurationSection createSection(String path) {
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot create section without a root");
|
||||
}
|
||||
|
||||
char separator = root.options().pathSeparator();
|
||||
// i1 is the leading (higher) index
|
||||
// i2 is the trailing (lower) index
|
||||
int i1 = -1;
|
||||
int i2;
|
||||
ConfigurationSection section = this;
|
||||
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
|
||||
String node = path.substring(i2, i1);
|
||||
ConfigurationSection subSection = section.getConfigurationSection(node);
|
||||
if (subSection == null) {
|
||||
section = section.createSection(node);
|
||||
} else {
|
||||
section = subSection;
|
||||
}
|
||||
}
|
||||
|
||||
String key = path.substring(i2);
|
||||
if (section == this) {
|
||||
ConfigurationSection result = new MemorySection(this, key);
|
||||
this.map.put(key, result);
|
||||
return result;
|
||||
}
|
||||
return section.createSection(key);
|
||||
}
|
||||
|
||||
@Override public ConfigurationSection createSection(String path, Map<?, ?> map) {
|
||||
ConfigurationSection section = createSection(path);
|
||||
|
||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
if (entry.getValue() instanceof Map) {
|
||||
section.createSection(entry.getKey().toString(), (Map<?, ?>) entry.getValue());
|
||||
} else {
|
||||
section.set(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
// Primitives
|
||||
@Override public String getString(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getString(path, def != null ? def.toString() : null);
|
||||
}
|
||||
|
||||
@Override public String getString(String path, String def) {
|
||||
Object val = getOrDefault(path, def);
|
||||
if (val != null) {
|
||||
return val.toString();
|
||||
} else {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean isString(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof String;
|
||||
}
|
||||
|
||||
@Override public int getInt(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getInt(path, toInt(def, 0));
|
||||
}
|
||||
|
||||
@Override public int getInt(String path, int def) {
|
||||
Object val = getOrDefault(path, def);
|
||||
return toInt(val, def);
|
||||
}
|
||||
|
||||
@Override public boolean isInt(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Integer;
|
||||
}
|
||||
|
||||
@Override public boolean getBoolean(String path) {
|
||||
Object def = getDefault(path);
|
||||
if (def instanceof Boolean) {
|
||||
return getBoolean(path, (Boolean) def);
|
||||
} else {
|
||||
return getBoolean(path, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean getBoolean(String path, boolean defaultValue) {
|
||||
Object val = getOrDefault(path, defaultValue);
|
||||
if (val instanceof Boolean) {
|
||||
return (Boolean) val;
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean isBoolean(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Boolean;
|
||||
}
|
||||
|
||||
@Override public double getDouble(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getDouble(path, toDouble(def, 0));
|
||||
}
|
||||
|
||||
@Override public double getDouble(String path, double defaultValue) {
|
||||
Object val = getOrDefault(path, defaultValue);
|
||||
return toDouble(val, defaultValue);
|
||||
}
|
||||
|
||||
@Override public boolean isDouble(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Double;
|
||||
}
|
||||
|
||||
@Override public long getLong(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getLong(path, toLong(def, 0));
|
||||
}
|
||||
|
||||
@Override public long getLong(String path, long def) {
|
||||
Object val = getOrDefault(path, def);
|
||||
return toLong(val, def);
|
||||
}
|
||||
|
||||
@Override public boolean isLong(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Long;
|
||||
}
|
||||
|
||||
// Java
|
||||
@Override public List<?> getList(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getList(path, def instanceof List ? (List<?>) def : null);
|
||||
}
|
||||
|
||||
@Override public List<?> getList(String path, List<?> def) {
|
||||
Object val = getOrDefault(path, def);
|
||||
return (List<?>) ((val instanceof List) ? val : def);
|
||||
}
|
||||
|
||||
@Override public boolean isList(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof List;
|
||||
}
|
||||
|
||||
@Override public List<String> getStringList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
if (list == null) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if ((object instanceof String) || isPrimitiveWrapper(object)) {
|
||||
result.add(String.valueOf(object));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Integer> getIntegerList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Integer> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Integer) {
|
||||
result.add((Integer) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Integer.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((int) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Boolean> getBooleanList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Boolean> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Boolean) {
|
||||
result.add((Boolean) object);
|
||||
} else if (object instanceof String) {
|
||||
if (Boolean.TRUE.toString().equals(object)) {
|
||||
result.add(true);
|
||||
} else if (Boolean.FALSE.toString().equals(object)) {
|
||||
result.add(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Double> getDoubleList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Double> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Double) {
|
||||
result.add((Double) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Double.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((double) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).doubleValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Float> getFloatList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Float> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Float) {
|
||||
result.add((Float) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Float.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((float) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).floatValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Long> getLongList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Long> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Long) {
|
||||
result.add((Long) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Long.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((long) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).longValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Byte> getByteList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Byte> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Byte) {
|
||||
result.add((Byte) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Byte.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((byte) ((Character) object).charValue());
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).byteValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Character> getCharacterList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Character> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Character) {
|
||||
result.add((Character) object);
|
||||
} else if (object instanceof String) {
|
||||
String str = (String) object;
|
||||
|
||||
if (str.length() == 1) {
|
||||
result.add(str.charAt(0));
|
||||
}
|
||||
} else if (object instanceof Number) {
|
||||
result.add((char) ((Number) object).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Short> getShortList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Short> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Short) {
|
||||
result.add((Short) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Short.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((short) ((Character) object).charValue());
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).shortValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public List<Map<?, ?>> getMapList(String path) {
|
||||
List<?> list = getList(path);
|
||||
List<Map<?, ?>> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Map) {
|
||||
result.add((Map<?, ?>) object);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public ConfigurationSection getConfigurationSection(String path) {
|
||||
Object val = getOrDefault(path, null);
|
||||
if (val != null) {
|
||||
return (val instanceof ConfigurationSection) ? (ConfigurationSection) val : null;
|
||||
}
|
||||
|
||||
val = getOrDefault(path, getDefault(path));
|
||||
return (val instanceof ConfigurationSection) ? createSection(path) : null;
|
||||
}
|
||||
|
||||
@Override public boolean isConfigurationSection(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof ConfigurationSection;
|
||||
}
|
||||
|
||||
protected boolean isPrimitiveWrapper(Object input) {
|
||||
return (input instanceof Integer) || (input instanceof Boolean)
|
||||
|| (input instanceof Character) || (input instanceof Byte) || (input instanceof Short)
|
||||
|| (input instanceof Double) || (input instanceof Long) || (input instanceof Float);
|
||||
}
|
||||
|
||||
protected Object getDefault(String path) {
|
||||
Configuration root = getRoot();
|
||||
Configuration defaults = root == null ? null : root.getDefaults();
|
||||
return (defaults == null) ? null : defaults.get(createPath(this, path));
|
||||
}
|
||||
|
||||
protected void mapChildrenKeys(Set<String> output, ConfigurationSection section, boolean deep) {
|
||||
if (section instanceof MemorySection) {
|
||||
MemorySection sec = (MemorySection) section;
|
||||
|
||||
for (Map.Entry<String, Object> entry : sec.map.entrySet()) {
|
||||
output.add(createPath(section, entry.getKey(), this));
|
||||
|
||||
if (deep && (entry.getValue() instanceof ConfigurationSection)) {
|
||||
ConfigurationSection subsection = (ConfigurationSection) entry.getValue();
|
||||
mapChildrenKeys(output, subsection, deep);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Set<String> keys = section.getKeys(deep);
|
||||
|
||||
for (String key : keys) {
|
||||
output.add(createPath(section, key, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void mapChildrenValues(Map<String, Object> output, ConfigurationSection section,
|
||||
boolean deep) {
|
||||
if (section instanceof MemorySection) {
|
||||
MemorySection sec = (MemorySection) section;
|
||||
|
||||
for (Map.Entry<String, Object> entry : sec.map.entrySet()) {
|
||||
output.put(createPath(section, entry.getKey(), this), entry.getValue());
|
||||
|
||||
if (entry.getValue() instanceof ConfigurationSection) {
|
||||
if (deep) {
|
||||
mapChildrenValues(output, (ConfigurationSection) entry.getValue(), deep);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Map<String, Object> values = section.getValues(deep);
|
||||
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
output.put(createPath(section, entry.getKey(), this), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + null
|
||||
+ "']";
|
||||
} else {
|
||||
return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + root
|
||||
.getClass().getSimpleName() + "']";
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.file;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.Configuration;
|
||||
import com.github.intellectualsites.plotsquared.configuration.InvalidConfigurationException;
|
||||
import com.github.intellectualsites.plotsquared.configuration.MemoryConfiguration;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* This is a base class for all File based implementations of {@link
|
||||
* Configuration}.
|
||||
*/
|
||||
public abstract class FileConfiguration extends MemoryConfiguration {
|
||||
|
||||
/**
|
||||
* Creates an empty {@link FileConfiguration} with no default values.
|
||||
*/
|
||||
FileConfiguration() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty {@link FileConfiguration} using the specified {@link
|
||||
* Configuration} as a source for all default values.
|
||||
*
|
||||
* @param defaults Default value provider
|
||||
*/
|
||||
public FileConfiguration(Configuration defaults) {
|
||||
super(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this {@link FileConfiguration} to the specified location.
|
||||
*
|
||||
* <p>If the file does not exist, it will be created. If already exists, it
|
||||
* will be overwritten. If it cannot be overwritten or created, an
|
||||
* exception will be thrown.
|
||||
*
|
||||
* <p>This method will save using the system default encoding, or possibly
|
||||
* using UTF8.
|
||||
*
|
||||
* @param file File to save to.
|
||||
* @throws IOException Thrown when the given file cannot be written to for
|
||||
* any reason.
|
||||
*/
|
||||
public void save(File file) throws IOException {
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
|
||||
String data = saveToString();
|
||||
|
||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file),
|
||||
StandardCharsets.UTF_8)) {
|
||||
writer.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this {@link FileConfiguration} to a string, and returns it.
|
||||
*
|
||||
* @return String containing this configuration.
|
||||
*/
|
||||
public abstract String saveToString();
|
||||
|
||||
/**
|
||||
* Loads this {@link FileConfiguration} from the specified location.
|
||||
*
|
||||
* <p>All the values contained within this configuration will be removed,
|
||||
* leaving only settings and defaults, and the new values will be loaded
|
||||
* from the given file.
|
||||
*
|
||||
* <p>If the file cannot be loaded for any reason, an exception will be
|
||||
* thrown.
|
||||
*
|
||||
* @param file File to load from.
|
||||
* @throws FileNotFoundException Thrown when the given file cannot be
|
||||
* opened.
|
||||
* @throws IOException Thrown when the given file cannot be read.
|
||||
* @throws InvalidConfigurationException Thrown when the given file is not
|
||||
* a valid Configuration.
|
||||
* @throws IllegalArgumentException Thrown when file is null.
|
||||
*/
|
||||
public void load(@Nonnull File file) throws IOException, InvalidConfigurationException {
|
||||
|
||||
FileInputStream stream = new FileInputStream(file);
|
||||
|
||||
load(new InputStreamReader(stream, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads this {@link FileConfiguration} from the specified reader.
|
||||
*
|
||||
* <p>All the values contained within this configuration will be removed,
|
||||
* leaving only settings and defaults, and the new values will be loaded
|
||||
* from the given stream.
|
||||
*
|
||||
* @param reader the reader to load from
|
||||
* @throws IOException thrown when underlying reader throws an IOException
|
||||
* @throws InvalidConfigurationException thrown when the reader does not
|
||||
* represent a valid Configuration
|
||||
*/
|
||||
public void load(Reader reader) throws IOException, InvalidConfigurationException {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
try (BufferedReader input = reader instanceof BufferedReader ?
|
||||
(BufferedReader) reader :
|
||||
new BufferedReader(reader)) {
|
||||
String line;
|
||||
|
||||
while ((line = input.readLine()) != null) {
|
||||
builder.append(line);
|
||||
builder.append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
loadFromString(builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads this {@link FileConfiguration} from the specified string, as
|
||||
* opposed to from file.
|
||||
*
|
||||
* <p>All the values contained within this configuration will be removed,
|
||||
* leaving only settings and defaults, and the new values will be loaded
|
||||
* from the given string.
|
||||
*
|
||||
* <p>If the string is invalid in any way, an exception will be thrown.
|
||||
*
|
||||
* @param contents Contents of a Configuration to load.
|
||||
* @throws InvalidConfigurationException Thrown if the specified string is
|
||||
* invalid.
|
||||
*/
|
||||
public abstract void loadFromString(String contents) throws InvalidConfigurationException;
|
||||
|
||||
/**
|
||||
* Compiles the header for this {@link FileConfiguration} and returns the
|
||||
* result.
|
||||
*
|
||||
* <p>This will use the header from {@link #options()} -> {@link
|
||||
* FileConfigurationOptions#header()}, respecting the rules of {@link
|
||||
* FileConfigurationOptions#copyHeader()} if set.
|
||||
*
|
||||
* @return Compiled header
|
||||
*/
|
||||
protected abstract String buildHeader();
|
||||
|
||||
@Override public FileConfigurationOptions options() {
|
||||
if (this.options == null) {
|
||||
this.options = new FileConfigurationOptions(this);
|
||||
}
|
||||
|
||||
return (FileConfigurationOptions) this.options;
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.file;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.Configuration;
|
||||
import com.github.intellectualsites.plotsquared.configuration.MemoryConfiguration;
|
||||
import com.github.intellectualsites.plotsquared.configuration.MemoryConfigurationOptions;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* FileConfiguration}.
|
||||
*/
|
||||
public class FileConfigurationOptions extends MemoryConfigurationOptions {
|
||||
private String header = null;
|
||||
private boolean copyHeader = true;
|
||||
|
||||
protected FileConfigurationOptions(MemoryConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override public FileConfiguration configuration() {
|
||||
return (FileConfiguration) super.configuration();
|
||||
}
|
||||
|
||||
@Override public FileConfigurationOptions copyDefaults(boolean value) {
|
||||
super.copyDefaults(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public FileConfigurationOptions pathSeparator(char value) {
|
||||
super.pathSeparator(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the header that will be applied to the top of the saved output.
|
||||
*
|
||||
* <p>This header will be commented out and applied directly at the top of
|
||||
* the generated output of the {@link FileConfiguration}. It is not
|
||||
* required to include a newline at the end of the header as it will
|
||||
* automatically be applied, but you may include one if you wish for extra
|
||||
* spacing.
|
||||
*
|
||||
* <p>{@code null} is a valid value which will indicate that no header]
|
||||
* is to be applied. The default value is {@code null}.
|
||||
*
|
||||
* @return Header
|
||||
*/
|
||||
public String header() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the header that will be applied to the top of the saved output.
|
||||
*
|
||||
* <p>This header will be commented out and applied directly at the top of
|
||||
* the generated output of the {@link FileConfiguration}. It is not
|
||||
* required to include a newline at the end of the header as it will
|
||||
* automatically be applied, but you may include one if you wish for extra
|
||||
* spacing.
|
||||
*
|
||||
* <p>{@code null} is a valid value which will indicate that no header
|
||||
* is to be applied.
|
||||
*
|
||||
* @param value New header
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public FileConfigurationOptions header(String value) {
|
||||
header = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not the header should be copied from a default source.
|
||||
*
|
||||
* <p>If this is true, if a default {@link FileConfiguration} is passed to
|
||||
* {@link FileConfiguration#setDefaults(Configuration)}
|
||||
* then upon saving it will use the header from that config, instead of
|
||||
* the one provided here.
|
||||
*
|
||||
* <p>If no default is set on the configuration, or the default is not of
|
||||
* type FileConfiguration, or that config has no header ({@link #header()}
|
||||
* returns null) then the header specified in this configuration will be
|
||||
* used.
|
||||
*
|
||||
* <p>Defaults to true.
|
||||
*
|
||||
* @return Whether or not to copy the header
|
||||
*/
|
||||
public boolean copyHeader() {
|
||||
return copyHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the header should be copied from a default source.
|
||||
*
|
||||
* <p>If this is true, if a default {@link FileConfiguration} is passed to
|
||||
* {@link FileConfiguration#setDefaults(Configuration)}
|
||||
* then upon saving it will use the header from that config, instead of
|
||||
* the one provided here.
|
||||
*
|
||||
* <p>If no default is set on the configuration, or the default is not of
|
||||
* type FileConfiguration, or that config has no header ({@link #header()}
|
||||
* returns null) then the header specified in this configuration will be
|
||||
* used.
|
||||
*
|
||||
* <p>Defaults to true.
|
||||
*
|
||||
* @param value Whether or not to copy the header
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public FileConfigurationOptions copyHeader(boolean value) {
|
||||
copyHeader = value;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.file;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.Configuration;
|
||||
import com.github.intellectualsites.plotsquared.configuration.ConfigurationSection;
|
||||
import com.github.intellectualsites.plotsquared.configuration.InvalidConfigurationException;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An implementation of {@link Configuration} which saves all files in Yaml.
|
||||
* Note that this implementation is not synchronized.
|
||||
*/
|
||||
public class YamlConfiguration extends FileConfiguration {
|
||||
private static final String COMMENT_PREFIX = "# ";
|
||||
private static final String BLANK_CONFIG = "{}\n";
|
||||
private final DumperOptions yamlOptions = new DumperOptions();
|
||||
private final Representer yamlRepresenter = new YamlRepresenter();
|
||||
private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions);
|
||||
|
||||
/**
|
||||
* Creates a new {@link YamlConfiguration}, loading from the given file.
|
||||
*
|
||||
* <p>Any errors loading the Configuration will be logged and then ignored.
|
||||
* If the specified input is not a valid config, a blank config will be
|
||||
* returned.
|
||||
*
|
||||
* <p>The encoding used may follow the system dependent default.
|
||||
*
|
||||
* @param file Input file
|
||||
* @return Resulting configuration
|
||||
*/
|
||||
public static YamlConfiguration loadConfiguration(File file) {
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
|
||||
try {
|
||||
config.load(file);
|
||||
} catch (InvalidConfigurationException | IOException ex) {
|
||||
try {
|
||||
File dest = new File(file.getAbsolutePath() + "_broken");
|
||||
int i = 0;
|
||||
while (dest.exists()) {
|
||||
dest = new File(file.getAbsolutePath() + "_broken_" + i++);
|
||||
}
|
||||
Files.copy(file.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
PlotSquared.debug("&dCould not read: &7" + file);
|
||||
PlotSquared.debug("&dRenamed to: &7" + dest.getName());
|
||||
PlotSquared.debug("&c============ Full stacktrace ============");
|
||||
ex.printStackTrace();
|
||||
PlotSquared.debug("&c=========================================");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override public String saveToString() {
|
||||
yamlOptions.setIndent(options().indent());
|
||||
yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
|
||||
String header = buildHeader();
|
||||
String dump = yaml.dump(getValues(false));
|
||||
|
||||
if (dump.equals(BLANK_CONFIG)) {
|
||||
dump = "";
|
||||
}
|
||||
|
||||
return header + dump;
|
||||
}
|
||||
|
||||
@Override public void loadFromString(String contents) throws InvalidConfigurationException {
|
||||
|
||||
Map<?, ?> input;
|
||||
try {
|
||||
input = yaml.load(contents);
|
||||
} catch (YAMLException e) {
|
||||
throw new InvalidConfigurationException(e);
|
||||
} catch (ClassCastException ignored) {
|
||||
throw new InvalidConfigurationException("Top level is not a Map.");
|
||||
}
|
||||
|
||||
String header = parseHeader(contents);
|
||||
if (!header.isEmpty()) {
|
||||
options().header(header);
|
||||
}
|
||||
|
||||
if (input != null) {
|
||||
convertMapsToSections(input, this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void convertMapsToSections(Map<?, ?> input, ConfigurationSection section) {
|
||||
for (Map.Entry<?, ?> entry : input.entrySet()) {
|
||||
String key = entry.getKey().toString();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (value instanceof Map) {
|
||||
convertMapsToSections((Map<?, ?>) value, section.createSection(key));
|
||||
} else {
|
||||
section.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String parseHeader(String input) {
|
||||
String[] lines = input.split("\r?\n", -1);
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean readingHeader = true;
|
||||
boolean foundHeader = false;
|
||||
|
||||
for (int i = 0; (i < lines.length) && readingHeader; i++) {
|
||||
String line = lines[i];
|
||||
|
||||
if (line.startsWith(COMMENT_PREFIX)) {
|
||||
if (i > 0) {
|
||||
result.append('\n');
|
||||
}
|
||||
|
||||
if (line.length() > COMMENT_PREFIX.length()) {
|
||||
result.append(line.substring(COMMENT_PREFIX.length()));
|
||||
}
|
||||
|
||||
foundHeader = true;
|
||||
} else if (foundHeader && line.isEmpty()) {
|
||||
result.append('\n');
|
||||
} else if (foundHeader) {
|
||||
readingHeader = false;
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override protected String buildHeader() {
|
||||
String header = options().header();
|
||||
|
||||
if (options().copyHeader()) {
|
||||
Configuration def = getDefaults();
|
||||
|
||||
if (def instanceof FileConfiguration) {
|
||||
FileConfiguration fileDefaults = (FileConfiguration) def;
|
||||
String defaultsHeader = fileDefaults.buildHeader();
|
||||
|
||||
if ((defaultsHeader != null) && !defaultsHeader.isEmpty()) {
|
||||
return defaultsHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (header == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String[] lines = header.split("\r?\n", -1);
|
||||
boolean startedHeader = false;
|
||||
|
||||
for (int i = lines.length - 1; i >= 0; i--) {
|
||||
builder.insert(0, '\n');
|
||||
|
||||
if (startedHeader || !lines[i].isEmpty()) {
|
||||
builder.insert(0, lines[i]);
|
||||
builder.insert(0, COMMENT_PREFIX);
|
||||
startedHeader = true;
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override public YamlConfigurationOptions options() {
|
||||
if (options == null) {
|
||||
options = new YamlConfigurationOptions(this);
|
||||
}
|
||||
|
||||
return (YamlConfigurationOptions) options;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.file;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* YamlConfiguration}.
|
||||
*/
|
||||
public class YamlConfigurationOptions extends FileConfigurationOptions {
|
||||
private int indent = 2;
|
||||
|
||||
YamlConfigurationOptions(YamlConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override public YamlConfiguration configuration() {
|
||||
return (YamlConfiguration) super.configuration();
|
||||
}
|
||||
|
||||
@Override public YamlConfigurationOptions copyDefaults(boolean value) {
|
||||
super.copyDefaults(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public YamlConfigurationOptions pathSeparator(char value) {
|
||||
super.pathSeparator(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public YamlConfigurationOptions header(String value) {
|
||||
super.header(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public YamlConfigurationOptions copyHeader(boolean value) {
|
||||
super.copyHeader(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets how much spaces should be used to indent each line.
|
||||
*
|
||||
* <p>The minimum value this may be is 2, and the maximum is 9.
|
||||
*
|
||||
* @return How much to indent by
|
||||
*/
|
||||
int indent() {
|
||||
return indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets how much spaces should be used to indent each line.
|
||||
*
|
||||
* <p>The minimum value this may be is 2, and the maximum is 9.
|
||||
*
|
||||
* @param value New indent
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public YamlConfigurationOptions indent(int value) {
|
||||
if (value < 2) {
|
||||
throw new IllegalArgumentException("Indent must be at least 2 characters");
|
||||
}
|
||||
if (value > 9) {
|
||||
throw new IllegalArgumentException("Indent cannot be greater than 9 characters");
|
||||
}
|
||||
|
||||
indent = value;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.file;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.serialization.ConfigurationSerialization;
|
||||
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.nodes.Tag;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class YamlConstructor extends SafeConstructor {
|
||||
|
||||
YamlConstructor() {
|
||||
yamlConstructors.put(Tag.MAP, new ConstructCustomObject());
|
||||
}
|
||||
|
||||
private class ConstructCustomObject extends ConstructYamlMap {
|
||||
@Override public Object construct(final Node node) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
throw new YAMLException("Unexpected referential mapping structure. Node: " + node);
|
||||
}
|
||||
|
||||
final Map<?, ?> raw = (Map<?, ?>) super.construct(node);
|
||||
|
||||
if (raw.containsKey(ConfigurationSerialization.SERIALIZED_TYPE_KEY)) {
|
||||
final Map<String, Object> typed = new LinkedHashMap<>(raw.size());
|
||||
for (final Map.Entry<?, ?> entry : raw.entrySet()) {
|
||||
typed.put(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
|
||||
try {
|
||||
return ConfigurationSerialization.deserializeObject(typed);
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
throw new YAMLException("Could not deserialize object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override public void construct2ndStep(final Node node, final Object object) {
|
||||
throw new YAMLException("Unexpected referential mapping structure. Node: " + node);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.file;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.ConfigurationSection;
|
||||
import com.github.intellectualsites.plotsquared.configuration.serialization.ConfigurationSerializable;
|
||||
import com.github.intellectualsites.plotsquared.configuration.serialization.ConfigurationSerialization;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class YamlRepresenter extends Representer {
|
||||
|
||||
YamlRepresenter() {
|
||||
this.multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection());
|
||||
this.multiRepresenters
|
||||
.put(ConfigurationSerializable.class, new RepresentConfigurationSerializable());
|
||||
}
|
||||
|
||||
private class RepresentConfigurationSection extends RepresentMap {
|
||||
|
||||
@Override public Node representData(Object data) {
|
||||
return super.representData(((ConfigurationSection) data).getValues(false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class RepresentConfigurationSerializable extends RepresentMap {
|
||||
|
||||
@Override public Node representData(Object data) {
|
||||
ConfigurationSerializable serializable = (ConfigurationSerializable) data;
|
||||
Map<String, Object> values = new LinkedHashMap<>();
|
||||
values.put(ConfigurationSerialization.SERIALIZED_TYPE_KEY,
|
||||
ConfigurationSerialization.getAlias(serializable.getClass()));
|
||||
values.putAll(serializable.serialize());
|
||||
|
||||
return super.representData(values);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.serialization;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents an object that may be serialized.
|
||||
* <p>These objects MUST implement one of the following, in addition to
|
||||
* the methods as defined by this interface:
|
||||
* <ul>
|
||||
* <li>A static method "deserialize" that accepts a single {@link Map}<
|
||||
* {@link String}, {@link Object}> and returns the class.</li>
|
||||
* <li>A static method "valueOf" that accepts a single {@link Map}<{@link
|
||||
* String}, {@link Object}> and returns the class.</li>
|
||||
* <li>A constructor that accepts a single {@link Map}<{@link String},
|
||||
* {@link Object}>.</li>
|
||||
* </ul>
|
||||
* In addition to implementing this interface, you must register the class
|
||||
* with {@link ConfigurationSerialization#registerClass(Class)}.
|
||||
*
|
||||
* @see DelegateDeserialization
|
||||
* @see SerializableAs
|
||||
*/
|
||||
public interface ConfigurationSerializable {
|
||||
|
||||
/**
|
||||
* Creates a Map representation of this class.
|
||||
*
|
||||
* <p>This class must provide a method to restore this class, as defined in
|
||||
* the {@link ConfigurationSerializable} interface javadoc.
|
||||
*
|
||||
* @return Map containing the current state of this class
|
||||
*/
|
||||
Map<String, Object> serialize();
|
||||
}
|
@ -0,0 +1,262 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.serialization;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.configuration.Configuration;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Utility class for storing and retrieving classes for {@link Configuration}.
|
||||
*/
|
||||
public class ConfigurationSerialization {
|
||||
|
||||
public static final String SERIALIZED_TYPE_KEY = "==";
|
||||
private static final Map<String, Class<? extends ConfigurationSerializable>> aliases =
|
||||
new HashMap<>();
|
||||
private final Class<? extends ConfigurationSerializable> clazz;
|
||||
|
||||
protected ConfigurationSerialization(Class<? extends ConfigurationSerializable> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to deserialize the given arguments into a new instance of the
|
||||
* given class.
|
||||
* <p>
|
||||
* <p>The class must implement {@link ConfigurationSerializable}, including
|
||||
* the extra methods as specified in the javadoc of
|
||||
* ConfigurationSerializable.</p>
|
||||
* <p>
|
||||
* <p>If a new instance could not be made, an example being the class not
|
||||
* fully implementing the interface, null will be returned.</p>
|
||||
*
|
||||
* @param args Arguments for deserialization
|
||||
* @param clazz Class to deserialize into
|
||||
* @return New instance of the specified class
|
||||
*/
|
||||
public static ConfigurationSerializable deserializeObject(Map<String, ?> args,
|
||||
Class<? extends ConfigurationSerializable> clazz) {
|
||||
return new ConfigurationSerialization(clazz).deserialize(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to deserialize the given arguments into a new instance of the
|
||||
* <p>
|
||||
* given class.
|
||||
* <p>
|
||||
* The class must implement {@link ConfigurationSerializable}, including
|
||||
* the extra methods as specified in the javadoc of
|
||||
* ConfigurationSerializable.</p>
|
||||
* <p>
|
||||
* <p>
|
||||
* If a new instance could not be made, an example being the class not
|
||||
* fully implementing the interface, null will be returned.</p>
|
||||
*
|
||||
* @param args Arguments for deserialization
|
||||
* @return New instance of the specified class
|
||||
*/
|
||||
public static ConfigurationSerializable deserializeObject(Map<String, ?> args) {
|
||||
Class<? extends ConfigurationSerializable> clazz = null;
|
||||
|
||||
if (args.containsKey(SERIALIZED_TYPE_KEY)) {
|
||||
try {
|
||||
String alias = (String) args.get(SERIALIZED_TYPE_KEY);
|
||||
|
||||
if (alias == null) {
|
||||
throw new IllegalArgumentException("Cannot have null alias");
|
||||
}
|
||||
clazz = getClassByAlias(alias);
|
||||
if (clazz == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Specified class does not exist ('" + alias + "')");
|
||||
}
|
||||
} catch (ClassCastException ex) {
|
||||
ex.fillInStackTrace();
|
||||
throw ex;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Args doesn't contain type key ('" + SERIALIZED_TYPE_KEY + "')");
|
||||
}
|
||||
|
||||
return new ConfigurationSerialization(clazz).deserialize(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link ConfigurationSerializable} class by its
|
||||
* alias.
|
||||
*
|
||||
* @param clazz Class to register
|
||||
*/
|
||||
public static void registerClass(Class<? extends ConfigurationSerializable> clazz) {
|
||||
DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class);
|
||||
|
||||
if (delegate == null) {
|
||||
registerClass(clazz, getAlias(clazz));
|
||||
registerClass(clazz, clazz.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given alias to the specified {@link
|
||||
* ConfigurationSerializable} class.
|
||||
*
|
||||
* @param clazz Class to register
|
||||
* @param alias Alias to register as
|
||||
* @see SerializableAs
|
||||
*/
|
||||
public static void registerClass(Class<? extends ConfigurationSerializable> clazz,
|
||||
String alias) {
|
||||
aliases.put(alias, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the specified alias to a {@link ConfigurationSerializable}
|
||||
*
|
||||
* @param alias Alias to unregister
|
||||
*/
|
||||
public static void unregisterClass(String alias) {
|
||||
aliases.remove(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters any aliases for the specified {@link
|
||||
* ConfigurationSerializable} class.
|
||||
*
|
||||
* @param clazz Class to unregister
|
||||
*/
|
||||
public static void unregisterClass(Class<? extends ConfigurationSerializable> clazz) {
|
||||
while (aliases.values().remove(clazz)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get a registered {@link ConfigurationSerializable} class by
|
||||
* its alias.
|
||||
*
|
||||
* @param alias Alias of the serializable
|
||||
* @return Registered class, or null if not found
|
||||
*/
|
||||
public static Class<? extends ConfigurationSerializable> getClassByAlias(String alias) {
|
||||
return aliases.get(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the correct alias for the given {@link ConfigurationSerializable}
|
||||
* class.
|
||||
*
|
||||
* @param clazz Class to get alias for
|
||||
* @return Alias to use for the class
|
||||
*/
|
||||
public static String getAlias(Class<? extends ConfigurationSerializable> clazz) {
|
||||
DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class);
|
||||
|
||||
if (delegate != null) {
|
||||
if (delegate.value() == clazz) {
|
||||
delegate = null;
|
||||
} else {
|
||||
return getAlias(delegate.value());
|
||||
}
|
||||
}
|
||||
|
||||
SerializableAs alias = clazz.getAnnotation(SerializableAs.class);
|
||||
|
||||
if (alias != null) {
|
||||
return alias.value();
|
||||
}
|
||||
|
||||
return clazz.getName();
|
||||
}
|
||||
|
||||
protected Method getMethod(String name, boolean isStatic) {
|
||||
try {
|
||||
Method method = this.clazz.getDeclaredMethod(name, Map.class);
|
||||
|
||||
if (!ConfigurationSerializable.class.isAssignableFrom(method.getReturnType())) {
|
||||
return null;
|
||||
}
|
||||
if (Modifier.isStatic(method.getModifiers()) != isStatic) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return method;
|
||||
} catch (NoSuchMethodException | SecurityException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Constructor<? extends ConfigurationSerializable> getConstructor() {
|
||||
try {
|
||||
return this.clazz.getConstructor(Map.class);
|
||||
} catch (NoSuchMethodException | SecurityException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected ConfigurationSerializable deserializeViaMethod(Method method, Map<String, ?> args) {
|
||||
try {
|
||||
ConfigurationSerializable result =
|
||||
(ConfigurationSerializable) method.invoke(null, args);
|
||||
|
||||
if (result == null) {
|
||||
Logger.getLogger(ConfigurationSerialization.class.getName()).log(Level.SEVERE,
|
||||
"Could not call method '" + method.toString() + "' of " + this.clazz
|
||||
+ " for deserialization: method returned null");
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ex) {
|
||||
Logger.getLogger(ConfigurationSerialization.class.getName()).log(Level.SEVERE,
|
||||
"Could not call method '" + method.toString() + "' of " + this.clazz
|
||||
+ " for deserialization",
|
||||
ex instanceof InvocationTargetException ? ex.getCause() : ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ConfigurationSerializable deserializeViaCtor(
|
||||
Constructor<? extends ConfigurationSerializable> ctor, Map<String, ?> args) {
|
||||
try {
|
||||
return ctor.newInstance(args);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException ex) {
|
||||
Logger.getLogger(ConfigurationSerialization.class.getName()).log(Level.SEVERE,
|
||||
"Could not call constructor '" + ctor.toString() + "' of " + this.clazz
|
||||
+ " for deserialization",
|
||||
ex instanceof InvocationTargetException ? ex.getCause() : ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ConfigurationSerializable deserialize(Map<String, ?> args) {
|
||||
if (args == null) {
|
||||
throw new NullPointerException("Args must not be null");
|
||||
}
|
||||
ConfigurationSerializable result = null;
|
||||
Method method = getMethod("deserialize", true);
|
||||
if (method != null) {
|
||||
result = deserializeViaMethod(method, args);
|
||||
}
|
||||
if (result == null) {
|
||||
method = getMethod("valueOf", true);
|
||||
if (method != null) {
|
||||
result = deserializeViaMethod(method, args);
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
Constructor<? extends ConfigurationSerializable> constructor = getConstructor();
|
||||
if (constructor != null) {
|
||||
result = deserializeViaCtor(constructor, args);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.serialization;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Applies to a {@link ConfigurationSerializable} that will delegate all
|
||||
* deserialization to another {@link ConfigurationSerializable}.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)
|
||||
public @interface DelegateDeserialization {
|
||||
/**
|
||||
* Which class should be used as a delegate for this classes
|
||||
* deserialization
|
||||
*
|
||||
* @return Delegate class
|
||||
*/
|
||||
Class<? extends ConfigurationSerializable> value();
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.github.intellectualsites.plotsquared.configuration.serialization;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Represents an "alias" that a {@link ConfigurationSerializable} may be
|
||||
* stored as.
|
||||
* If this is not present on a {@link ConfigurationSerializable} class, it
|
||||
* will use the fully qualified name of the class.
|
||||
* <p>
|
||||
* This value will be stored in the configuration so that the configuration
|
||||
* deserialization can determine what type it is.
|
||||
* <p>
|
||||
* Using this annotation on any other class than a {@link
|
||||
* ConfigurationSerializable} will have no effect.
|
||||
*
|
||||
* @see ConfigurationSerialization#registerClass(Class, String)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface SerializableAs {
|
||||
/**
|
||||
* This is the name your class will be stored and retrieved as.
|
||||
* <p>
|
||||
* This name MUST be unique. We recommend using names such as
|
||||
* "MyPluginThing" instead of "Thing".
|
||||
*
|
||||
* @return Name to serialize the class as.
|
||||
*/
|
||||
String value();
|
||||
}
|
@ -0,0 +1,815 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A JSONArray is an ordered sequence of values. Its external text form is a string wrapped in square brackets with
|
||||
* commas separating the values. The internal form is an object having {@code get} and {@code opt} methods for
|
||||
* accessing the values by index, and {@code put} methods for adding or replacing values. The values can be any of
|
||||
* these types: {@code Boolean}, {@code JSONArray}, {@code JSONObject}, {@code Number},
|
||||
* {@code String}, or the {@code JSONObject.NULL object}.
|
||||
*
|
||||
* <p>The constructor can convert a JSON text into a Java object. The {@code toString} method converts to JSON text.
|
||||
*
|
||||
* <p>A {@code get} method returns a value if one can be found, and throws an exception if one cannot be found. An
|
||||
* {@code opt} method returns a default value instead of throwing an exception, and so is useful for obtaining
|
||||
* optional values.
|
||||
*
|
||||
* <p>The generic {@code get()} and {@code opt()} methods return an object which you can cast or query for type.
|
||||
* There are also typed {@code get} and {@code opt} methods that do type checking and type coercion for you.
|
||||
*
|
||||
* <p>The texts produced by the {@code toString} methods strictly conform to JSON syntax rules. The constructors are
|
||||
* more forgiving in the texts they will accept: <ul> <li>An extra {@code ,} <small>(comma)</small> may appear
|
||||
* just before the closing bracket.</li> <li>The {@code null} value will be inserted when there is {@code ,}
|
||||
* <small>(comma)</small> elision.</li> <li>Strings may be quoted with {@code '} <small>(single
|
||||
* quote)</small>.</li> <li>Strings do not need to be quoted at all if they do not begin with a quote or single quote,
|
||||
* and if they do not contain leading or trailing spaces, and if they do not contain any of these characters: {@code { }
|
||||
* [ ] / \ : , #} and if they do not look like numbers and if they are not the reserved words {@code true},
|
||||
* {@code false}, or {@code null}.</li> </ul>
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONArray {
|
||||
/**
|
||||
* The arrayList where the JSONArray's properties are kept.
|
||||
*/
|
||||
private final ArrayList<Object> myArrayList;
|
||||
|
||||
/**
|
||||
* Construct an empty JSONArray.
|
||||
*/
|
||||
public JSONArray() {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a JSONTokener.
|
||||
*
|
||||
* @param x A JSONTokener
|
||||
* @throws JSONException If there is a syntax error.
|
||||
*/
|
||||
public JSONArray(JSONTokener x) throws JSONException {
|
||||
this();
|
||||
if (x.nextClean() != '[') {
|
||||
throw x.syntaxError("A JSONArray text must start with '['");
|
||||
}
|
||||
if (x.nextClean() != ']') {
|
||||
x.back();
|
||||
for (; ; ) {
|
||||
if (x.nextClean() == ',') {
|
||||
x.back();
|
||||
this.myArrayList.add(JSONObject.NULL);
|
||||
} else {
|
||||
x.back();
|
||||
this.myArrayList.add(x.nextValue());
|
||||
}
|
||||
switch (x.nextClean()) {
|
||||
case ',':
|
||||
if (x.nextClean() == ']') {
|
||||
return;
|
||||
}
|
||||
x.back();
|
||||
break;
|
||||
case ']':
|
||||
return;
|
||||
default:
|
||||
throw x.syntaxError("Expected a ',' or ']'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a source JSON text.
|
||||
*
|
||||
* @param source A string that begins with {@code [} <small>(left bracket)</small> and ends with
|
||||
* {@code ]} <small>(right bracket)</small>.
|
||||
* @throws JSONException If there is a syntax error.
|
||||
*/
|
||||
public JSONArray(String source) throws JSONException {
|
||||
this(new JSONTokener(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a Collection.
|
||||
*
|
||||
* @param collection A Collection.
|
||||
*/
|
||||
public JSONArray(Collection<Object> collection) {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
if (collection != null) {
|
||||
for (Object aCollection : collection) {
|
||||
this.myArrayList.add(JSONObject.wrap(aCollection));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from an array
|
||||
*
|
||||
* @throws JSONException If not an array.
|
||||
*/
|
||||
public JSONArray(Object array) throws JSONException {
|
||||
this();
|
||||
if (array.getClass().isArray()) {
|
||||
int length = Array.getLength(array);
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
this.put(JSONObject.wrap(Array.get(array, i)));
|
||||
}
|
||||
} else {
|
||||
throw new JSONException(
|
||||
"JSONArray initial value should be a string or collection or array.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object value associated with an index.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return An object value.
|
||||
* @throws JSONException If there is no value for the index.
|
||||
*/
|
||||
public Object get(int index) throws JSONException {
|
||||
Object object = opt(index);
|
||||
if (object == null) {
|
||||
throw new JSONException("JSONArray[" + index + "] not found.");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the boolean value associated with an index. The string values "true" and "false" are converted to boolean.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The truth.
|
||||
* @throws JSONException If there is no value for the index or if the value is not convertible to boolean.
|
||||
*/
|
||||
public boolean getBoolean(int index) throws JSONException {
|
||||
Object object = get(index);
|
||||
if (object.equals(Boolean.FALSE) || ((object instanceof String) && ((String) object)
|
||||
.equalsIgnoreCase("false"))) {
|
||||
return false;
|
||||
} else if (object.equals(Boolean.TRUE) || ((object instanceof String) && ((String) object)
|
||||
.equalsIgnoreCase("true"))) {
|
||||
return true;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a boolean.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the double value associated with an index.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException If the key is not found or if the value cannot be converted to a number.
|
||||
*/
|
||||
public double getDouble(int index) throws JSONException {
|
||||
Object object = get(index);
|
||||
try {
|
||||
return object instanceof Number ?
|
||||
((Number) object).doubleValue() :
|
||||
Double.parseDouble((String) object);
|
||||
} catch (NumberFormatException ignored) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the int value associated with an index.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException If the key is not found or if the value is not a number.
|
||||
*/
|
||||
public int getInt(int index) throws JSONException {
|
||||
Object object = get(index);
|
||||
try {
|
||||
return object instanceof Number ?
|
||||
((Number) object).intValue() :
|
||||
Integer.parseInt((String) object);
|
||||
} catch (NumberFormatException ignored) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSONArray associated with an index.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return A JSONArray value.
|
||||
* @throws JSONException If there is no value for the index. or if the value is not a JSONArray
|
||||
*/
|
||||
public JSONArray getJSONArray(int index) throws JSONException {
|
||||
Object object = get(index);
|
||||
if (object instanceof JSONArray) {
|
||||
return (JSONArray) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a JSONArray.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSONObject associated with an index.
|
||||
*
|
||||
* @param index subscript
|
||||
* @return A JSONObject value.
|
||||
* @throws JSONException If there is no value for the index or if the value is not a JSONObject
|
||||
*/
|
||||
public JSONObject getJSONObject(int index) throws JSONException {
|
||||
Object object = get(index);
|
||||
if (object instanceof JSONObject) {
|
||||
return (JSONObject) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a JSONObject.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the long value associated with an index.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
* @throws JSONException If the key is not found or if the value cannot be converted to a number.
|
||||
*/
|
||||
public long getLong(int index) throws JSONException {
|
||||
Object object = get(index);
|
||||
try {
|
||||
return object instanceof Number ?
|
||||
((Number) object).longValue() :
|
||||
Long.parseLong((String) object);
|
||||
} catch (NumberFormatException ignored) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string associated with an index.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return A string value.
|
||||
* @throws JSONException If there is no string value for the index.
|
||||
*/
|
||||
public String getString(int index) throws JSONException {
|
||||
Object object = get(index);
|
||||
if (object instanceof String) {
|
||||
return (String) object;
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] not a string.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the value is null.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return true if the value at the index is null, or if there is no value.
|
||||
*/
|
||||
public boolean isNull(int index) {
|
||||
return JSONObject.NULL.equals(opt(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a string from the contents of this JSONArray. The {@code separator} string is inserted between each
|
||||
* element. Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param separator A string that will be inserted between the elements.
|
||||
* @return a string.
|
||||
* @throws JSONException If the array contains an invalid number.
|
||||
*/
|
||||
public String join(String separator) throws JSONException {
|
||||
int len = length();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < len; i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append(separator);
|
||||
}
|
||||
sb.append(JSONObject.valueToString(this.myArrayList.get(i)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of elements in the JSONArray, included nulls.
|
||||
*
|
||||
* @return The length (or size).
|
||||
*/
|
||||
public int length() {
|
||||
return this.myArrayList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional object value associated with an index.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return An object value, or null if there is no object at that index.
|
||||
*/
|
||||
public Object opt(int index) {
|
||||
return ((index < 0) || (index >= length())) ? null : this.myArrayList.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional boolean value associated with an index. It returns false if there is no value at that index, or
|
||||
* if the value is not Boolean.TRUE or the String "true".
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(int index) {
|
||||
return this.optBoolean(index, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional boolean value associated with an index. It returns the defaultValue if there is no value at that
|
||||
* index or if it is not a Boolean or the String "true" or "false" (case insensitive).
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @param defaultValue A boolean default.
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(int index, boolean defaultValue) {
|
||||
try {
|
||||
return getBoolean(index);
|
||||
} catch (JSONException ignored) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. NaN is returned if there is no value for the index, or if
|
||||
* the value is not a number and cannot be converted to a number.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index) {
|
||||
return this.optDouble(index, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. The defaultValue is returned if there is no value for the
|
||||
* index, or if the value is not a number and cannot be converted to a number.
|
||||
*
|
||||
* @param index subscript
|
||||
* @param defaultValue The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index, double defaultValue) {
|
||||
try {
|
||||
return getDouble(index);
|
||||
} catch (JSONException ignored) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional int value associated with an index. Zero is returned if there is no value for the index, or if
|
||||
* the value is not a number and cannot be converted to a number.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index) {
|
||||
return this.optInt(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional int value associated with an index. The defaultValue is returned if there is no value for the
|
||||
* index, or if the value is not a number and cannot be converted to a number.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @param defaultValue The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index, int defaultValue) {
|
||||
try {
|
||||
return getInt(index);
|
||||
} catch (JSONException ignored) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional JSONArray associated with an index.
|
||||
*
|
||||
* @param index subscript
|
||||
* @return A JSONArray value, or null if the index has no value, or if the value is not a JSONArray.
|
||||
*/
|
||||
public JSONArray optJSONArray(int index) {
|
||||
Object o = opt(index);
|
||||
return o instanceof JSONArray ? (JSONArray) o : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional JSONObject associated with an index. Null is returned if the key is not found, or null if the
|
||||
* index has no value, or if the value is not a JSONObject.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return A JSONObject value.
|
||||
*/
|
||||
public JSONObject optJSONObject(int index) {
|
||||
Object o = opt(index);
|
||||
return o instanceof JSONObject ? (JSONObject) o : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional long value associated with an index. Zero is returned if there is no value for the index, or if
|
||||
* the value is not a number and cannot be converted to a number.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index) {
|
||||
return this.optLong(index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional long value associated with an index. The defaultValue
|
||||
* is returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @param defaultValue The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index, long defaultValue) {
|
||||
try {
|
||||
return getLong(index);
|
||||
} catch (JSONException ignored) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional string value associated with an index. It returns an
|
||||
* empty string if there is no value at that index. If the value is not a
|
||||
* string and is not null, then it is converted to a string.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @return A String value.
|
||||
*/
|
||||
public String optString(int index) {
|
||||
return this.optString(index, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional string associated with an index. The defaultValue is
|
||||
* returned if the key is not found.
|
||||
*
|
||||
* @param index The index must be between 0 and length() - 1.
|
||||
* @param defaultValue The default value.
|
||||
* @return A String value.
|
||||
*/
|
||||
public String optString(int index, String defaultValue) {
|
||||
Object object = opt(index);
|
||||
return JSONObject.NULL.equals(object) ? defaultValue : object.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a boolean value. This increases the array's length by one.
|
||||
*
|
||||
* @param value A boolean value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(boolean value) {
|
||||
this.put(value ? Boolean.TRUE : Boolean.FALSE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONArray which
|
||||
* is produced from a Collection.
|
||||
*
|
||||
* @param value A Collection value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Collection<Object> value) {
|
||||
this.put(new JSONArray(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value. This increases the array's length by one.
|
||||
*
|
||||
* @param value A double value.
|
||||
* @return this.
|
||||
* @throws JSONException if the value is not finite.
|
||||
*/
|
||||
public JSONArray put(double value) throws JSONException {
|
||||
Double d = value;
|
||||
JSONObject.testValidity(d);
|
||||
this.put(d);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an int value. This increases the array's length by one.
|
||||
*
|
||||
* @param value An int value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(int value) {
|
||||
this.put(Integer.valueOf(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an long value. This increases the array's length by one.
|
||||
*
|
||||
* @param value A long value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(long value) {
|
||||
this.put(Long.valueOf(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONObject which
|
||||
* is produced from a Map.
|
||||
*
|
||||
* @param value A Map value.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Map<String, Object> value) {
|
||||
this.put(new JSONObject(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an object value. This increases the array's length by one.
|
||||
*
|
||||
* @param value An object value. The value should be a Boolean, Double,
|
||||
* Integer, JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray put(Object value) {
|
||||
this.myArrayList.add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a boolean value in the JSONArray. If the index is greater than the length of the JSONArray, then
|
||||
* null elements will be added as necessary to pad it out.
|
||||
*
|
||||
* @param index The subscript.
|
||||
* @param value A boolean value.
|
||||
* @return this.
|
||||
* @throws JSONException If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, boolean value) throws JSONException {
|
||||
this.put(index, value ? Boolean.TRUE : Boolean.FALSE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONArray which
|
||||
* is produced from a Collection.
|
||||
*
|
||||
* @param index The subscript.
|
||||
* @param value A Collection value.
|
||||
* @return this.
|
||||
* @throws JSONException If the index is negative or if the value is not
|
||||
* finite.
|
||||
*/
|
||||
public JSONArray put(int index, Collection<Object> value) throws JSONException {
|
||||
this.put(index, new JSONArray(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a double value. If the index is greater than the length
|
||||
* of the JSONArray, then null elements will be added as necessary to pad
|
||||
* it out.
|
||||
*
|
||||
* @param index The subscript.
|
||||
* @param value A double value.
|
||||
* @return this.
|
||||
* @throws JSONException If the index is negative or if the value is not
|
||||
* finite.
|
||||
*/
|
||||
public JSONArray put(int index, double value) throws JSONException {
|
||||
this.put(index, new Double(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace an int value. If the index is greater than the length of the JSONArray, then null elements will be
|
||||
* added as necessary to pad it out.
|
||||
*
|
||||
* @param index The subscript.
|
||||
* @param value An int value.
|
||||
* @return this.
|
||||
* @throws JSONException If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, int value) throws JSONException {
|
||||
this.put(index, Integer.valueOf(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace a long value. If the index is greater than the length of the JSONArray, then null elements will be
|
||||
* added as necessary to pad it out.
|
||||
*
|
||||
* @param index The subscript.
|
||||
* @param value A long value.
|
||||
* @return this.
|
||||
* @throws JSONException If the index is negative.
|
||||
*/
|
||||
public JSONArray put(int index, long value) throws JSONException {
|
||||
this.put(index, Long.valueOf(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONObject that
|
||||
* is produced from a Map.
|
||||
*
|
||||
* @param index The subscript.
|
||||
* @param value The Map value.
|
||||
* @return this.
|
||||
* @throws JSONException If the index is negative or if the the value is an
|
||||
* invalid number.
|
||||
*/
|
||||
public JSONArray put(int index, Map<String, Object> value) throws JSONException {
|
||||
this.put(index, new JSONObject(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put or replace an object value in the JSONArray. If the index is greater than the length of the JSONArray, then
|
||||
* null elements will be added as necessary to pad it out.
|
||||
*
|
||||
* @param index The subscript.
|
||||
* @param value The value to put into the array. The value should be a Boolean, Double, Integer, JSONArray,
|
||||
* JSONObject, Long, or String, or the JSONObject.NULL object.
|
||||
* @return this.
|
||||
* @throws JSONException If the index is negative or if the the value is an invalid number.
|
||||
*/
|
||||
public JSONArray put(int index, Object value) throws JSONException {
|
||||
JSONObject.testValidity(value);
|
||||
if (index < 0) {
|
||||
throw new JSONException("JSONArray[" + index + "] not found.");
|
||||
}
|
||||
if (index < length()) {
|
||||
this.myArrayList.set(index, value);
|
||||
} else {
|
||||
while (index != length()) {
|
||||
this.put(JSONObject.NULL);
|
||||
}
|
||||
this.put(value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an index and close the hole.
|
||||
*
|
||||
* @param index The index of the element to be removed.
|
||||
* @return The value that was associated with the index, or null if there was no value.
|
||||
*/
|
||||
public Object remove(int index) {
|
||||
return (index >= 0) && (index < length()) ? this.myArrayList.remove(index) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two JSONArrays are similar. They must contain similar sequences.
|
||||
*
|
||||
* @param other The other JSONArray
|
||||
* @return true if they are equal
|
||||
*/
|
||||
public boolean similar(Object other) {
|
||||
if (!(other instanceof JSONArray)) {
|
||||
return false;
|
||||
}
|
||||
int len = length();
|
||||
if (len != ((JSONArray) other).length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i += 1) {
|
||||
Object valueThis = get(i);
|
||||
Object valueOther = ((JSONArray) other).get(i);
|
||||
if (valueThis instanceof JSONObject) {
|
||||
if (!((JSONObject) valueThis).similar(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
} else if (valueThis instanceof JSONArray) {
|
||||
if (!((JSONArray) valueThis).similar(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!valueThis.equals(valueOther)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a JSONObject by combining a JSONArray of names with the values of this JSONArray.
|
||||
*
|
||||
* @param names A JSONArray containing a list of key strings. These will be paired with the values.
|
||||
* @return A JSONObject, or null if there are no names or if this JSONArray has no values.
|
||||
* @throws JSONException If any of the names are null.
|
||||
*/
|
||||
public JSONObject toJSONObject(JSONArray names) throws JSONException {
|
||||
if ((names == null) || (names.length() == 0) || (length() == 0)) {
|
||||
return null;
|
||||
}
|
||||
JSONObject jo = new JSONObject();
|
||||
for (int i = 0; i < names.length(); i += 1) {
|
||||
jo.put(names.getString(i), opt(i));
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSON text of this JSONArray. For compactness, no unnecessary whitespace is added. If it is not possible to
|
||||
* produce a syntactically correct JSON text then null will be returned instead. This could occur if the array
|
||||
* contains an invalid number.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @return a printable, displayable, transmittable representation of the array.
|
||||
*/
|
||||
@Override public String toString() {
|
||||
try {
|
||||
return this.toString(0);
|
||||
} catch (JSONException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a prettyprinted JSON text of this JSONArray. Warning: This method assumes that the data structure is
|
||||
* acyclical.
|
||||
*
|
||||
* @param indentFactor The number of spaces to add to each level of indentation.
|
||||
* @return a printable, displayable, transmittable representation of the object, beginning with
|
||||
* {@code [} <small>(left bracket)</small> and ending with {@code ]} <small>(right
|
||||
* bracket)</small>.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public String toString(int indentFactor) throws JSONException {
|
||||
StringWriter sw = new StringWriter();
|
||||
synchronized (sw.getBuffer()) {
|
||||
return this.write(sw, indentFactor, 0).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For compactness, no whitespace is added.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public Writer write(Writer writer) throws JSONException {
|
||||
return this.write(writer, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For compactness, no whitespace is added.
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param indentFactor The number of spaces to add to each level of indentation.
|
||||
* @param indent The indention of the top level.
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
*/
|
||||
Writer write(Writer writer, int indentFactor, int indent) throws JSONException {
|
||||
try {
|
||||
boolean commanate = false;
|
||||
int length = length();
|
||||
writer.write('[');
|
||||
if (length == 1) {
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(0), indentFactor, indent);
|
||||
} else if (length != 0) {
|
||||
int newindent = indent + indentFactor;
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
if (commanate) {
|
||||
writer.write(',');
|
||||
}
|
||||
if (indentFactor > 0) {
|
||||
writer.write('\n');
|
||||
}
|
||||
JSONObject.indent(writer, newindent);
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(i), indentFactor, newindent);
|
||||
commanate = true;
|
||||
}
|
||||
if (indentFactor > 0) {
|
||||
writer.write('\n');
|
||||
}
|
||||
JSONObject.indent(writer, indent);
|
||||
}
|
||||
writer.write(']');
|
||||
return writer;
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
/**
|
||||
* The JSONException is thrown by the JSON.org classes when things are amiss.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONException extends RuntimeException {
|
||||
private static final long serialVersionUID = 0;
|
||||
private Throwable cause;
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message.
|
||||
*
|
||||
* @param message Detail about the reason for the exception.
|
||||
*/
|
||||
public JSONException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JSONException with the specified cause.
|
||||
*
|
||||
* @param cause The cause.
|
||||
*/
|
||||
public JSONException(final Throwable cause) {
|
||||
super(cause.getMessage());
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause of this exception or null if the cause is nonexistent or unknown.
|
||||
*
|
||||
* @return the cause of this exception or null if the cause is nonexistent or unknown.
|
||||
*/
|
||||
@Override public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,16 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
/**
|
||||
* The <code>JSONString</code> interface allows a <code>toJSONString()</code> method so that a class can change the
|
||||
* behavior of <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>, and
|
||||
* <code>JSONWriter.value(</code>Object<code>)</code>. The <code>toJSONString</code> method will be used instead of the
|
||||
* default behavior of using the Object's <code>toString()</code> method and quoting the result.
|
||||
*/
|
||||
public interface JSONString {
|
||||
/**
|
||||
* The <code>toJSONString</code> method allows a class to produce its own JSON serialization.
|
||||
*
|
||||
* @return A strictly syntactically correct JSON text.
|
||||
*/
|
||||
String toJSONString();
|
||||
}
|
@ -0,0 +1,384 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A JSONTokener takes a source string and extracts characters and tokens from it. It is used by the JSONObject and
|
||||
* JSONArray constructors to parse JSON source strings.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONTokener {
|
||||
private final Reader reader;
|
||||
private long character;
|
||||
private boolean eof;
|
||||
private long index;
|
||||
private long line;
|
||||
private char previous;
|
||||
private boolean usePrevious;
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a Reader.
|
||||
*
|
||||
* @param reader A reader.
|
||||
*/
|
||||
public JSONTokener(final Reader reader) {
|
||||
this.reader = reader.markSupported() ? reader : new BufferedReader(reader);
|
||||
eof = false;
|
||||
usePrevious = false;
|
||||
previous = 0;
|
||||
index = 0;
|
||||
character = 1;
|
||||
line = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from an InputStream.
|
||||
*
|
||||
* @param inputStream The source.
|
||||
*/
|
||||
public JSONTokener(final InputStream inputStream) throws JSONException {
|
||||
this(new InputStreamReader(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a string.
|
||||
*
|
||||
* @param s A source string.
|
||||
*/
|
||||
public JSONTokener(final String s) {
|
||||
this(new StringReader(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hex value of a character (base16).
|
||||
*
|
||||
* @param c A character between '0' and '9' or between 'A' and 'F' or between 'a' and 'f'.
|
||||
* @return An int between 0 and 15, or -1 if c was not a hex digit.
|
||||
*/
|
||||
public static int dehexchar(final char c) {
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
return c - '0';
|
||||
}
|
||||
if ((c >= 'A') && (c <= 'F')) {
|
||||
return c - ('A' - 10);
|
||||
}
|
||||
if ((c >= 'a') && (c <= 'f')) {
|
||||
return c - ('a' - 10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Back up one character. This provides a sort of lookahead capability, so that you can test for a digit or letter
|
||||
* before attempting to parse the next number or identifier.
|
||||
*/
|
||||
public void back() throws JSONException {
|
||||
if (usePrevious || (index <= 0)) {
|
||||
throw new JSONException("Stepping back two steps is not supported");
|
||||
}
|
||||
index -= 1;
|
||||
character -= 1;
|
||||
usePrevious = true;
|
||||
eof = false;
|
||||
}
|
||||
|
||||
public boolean end() {
|
||||
return eof && !usePrevious;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the source string still contains characters that next() can consume.
|
||||
*
|
||||
* @return true if not yet at the end of the source.
|
||||
*/
|
||||
public boolean more() throws JSONException {
|
||||
this.next();
|
||||
if (end()) {
|
||||
return false;
|
||||
}
|
||||
back();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next character in the source string.
|
||||
*
|
||||
* @return The next character, or 0 if past the end of the source string.
|
||||
*/
|
||||
public char next() throws JSONException {
|
||||
int c;
|
||||
if (usePrevious) {
|
||||
usePrevious = false;
|
||||
c = previous;
|
||||
} else {
|
||||
try {
|
||||
c = reader.read();
|
||||
} catch (final IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
if (c <= 0) { // End of stream
|
||||
eof = true;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
index += 1;
|
||||
if (previous == '\r') {
|
||||
line += 1;
|
||||
character = c == '\n' ? 0 : 1;
|
||||
} else if (c == '\n') {
|
||||
line += 1;
|
||||
character = 0;
|
||||
} else {
|
||||
character += 1;
|
||||
}
|
||||
previous = (char) c;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the next character, and check that it matches a specified character.
|
||||
*
|
||||
* @param c The character to match.
|
||||
* @return The character.
|
||||
* @throws JSONException if the character does not match.
|
||||
*/
|
||||
public char next(final char c) throws JSONException {
|
||||
final char n = this.next();
|
||||
if (n != c) {
|
||||
throw syntaxError("Expected '" + c + "' and instead saw '" + n + "'");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next n characters.
|
||||
*
|
||||
* @param n The number of characters to take.
|
||||
* @return A string of n characters.
|
||||
* @throws JSONException Substring bounds error if there are not n characters remaining in the source string.
|
||||
*/
|
||||
public String next(final int n) throws JSONException {
|
||||
if (n == 0) {
|
||||
return "";
|
||||
}
|
||||
final char[] chars = new char[n];
|
||||
int pos = 0;
|
||||
while (pos < n) {
|
||||
chars[pos] = this.next();
|
||||
if (end()) {
|
||||
throw syntaxError("Substring bounds error");
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next char in the string, skipping whitespace.
|
||||
*
|
||||
* @return A character, or 0 if there are no more characters.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public char nextClean() throws JSONException {
|
||||
for (; ; ) {
|
||||
final char c = this.next();
|
||||
if ((c == 0) || (c > ' ')) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the characters up to the next close quote character. Backslash processing is done. The formal JSON format
|
||||
* does not allow strings in single quotes, but an implementation is allowed to accept them.
|
||||
*
|
||||
* @param quote The quoting character, either <code>"</code> <small>(double quote)</small> or <code>'</code>
|
||||
* <small>(single quote)</small>.
|
||||
* @return A String.
|
||||
* @throws JSONException Unterminated string.
|
||||
*/
|
||||
public String nextString(final char quote) throws JSONException {
|
||||
char c;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '\n':
|
||||
case '\r':
|
||||
throw syntaxError("Unterminated string");
|
||||
case '\\':
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 'b':
|
||||
sb.append('\b');
|
||||
break;
|
||||
case 't':
|
||||
sb.append('\t');
|
||||
break;
|
||||
case 'n':
|
||||
sb.append('\n');
|
||||
break;
|
||||
case 'f':
|
||||
sb.append('\f');
|
||||
break;
|
||||
case 'r':
|
||||
sb.append('\r');
|
||||
break;
|
||||
case 'u':
|
||||
sb.append((char) Integer.parseInt(this.next(4), 16));
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '/':
|
||||
sb.append(c);
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Illegal escape.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (c == quote) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text up but not including the specified character or the end of line, whichever comes first.
|
||||
*
|
||||
* @param delimiter A delimiter character.
|
||||
* @return A string.
|
||||
*/
|
||||
public String nextTo(final char delimiter) throws JSONException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
final char c = this.next();
|
||||
if ((c == delimiter) || (c == 0) || (c == '\n') || (c == '\r')) {
|
||||
if (c != 0) {
|
||||
back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text up but not including one of the specified delimiter characters or the end of line, whichever comes
|
||||
* first.
|
||||
*
|
||||
* @param delimiters A set of delimiter characters.
|
||||
* @return A string, trimmed.
|
||||
*/
|
||||
public String nextTo(final String delimiters) throws JSONException {
|
||||
char c;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
c = this.next();
|
||||
if ((delimiters.indexOf(c) >= 0) || (c == 0) || (c == '\n') || (c == '\r')) {
|
||||
if (c != 0) {
|
||||
back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
|
||||
* JSONObject.NULL object.
|
||||
*
|
||||
* @return An object.
|
||||
* @throws JSONException If syntax error.
|
||||
*/
|
||||
public Object nextValue() throws JSONException {
|
||||
char c = nextClean();
|
||||
String string;
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\'':
|
||||
return nextString(c);
|
||||
case '{':
|
||||
back();
|
||||
return new JSONObject(this);
|
||||
case '[':
|
||||
back();
|
||||
return new JSONArray(this);
|
||||
}
|
||||
/*
|
||||
* Handle unquoted text. This could be the values true, false, or
|
||||
* null, or it can be a number. An implementation (such as this one)
|
||||
* is allowed to also accept non-standard forms.
|
||||
* Accumulate characters until we reach the end of the text or a
|
||||
* formatting character.
|
||||
*/
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while ((c >= ' ') && (",:]}/\\\"[{;=#".indexOf(c) < 0)) {
|
||||
sb.append(c);
|
||||
c = this.next();
|
||||
}
|
||||
back();
|
||||
string = sb.toString().trim();
|
||||
if (string.isEmpty()) {
|
||||
throw syntaxError("Missing value");
|
||||
}
|
||||
return JSONObject.stringToValue(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip characters until the next character is the requested character. If the requested character is not found, no
|
||||
* characters are skipped.
|
||||
*
|
||||
* @param to A character to skip to.
|
||||
* @return The requested character, or zero if the requested character is not found.
|
||||
*/
|
||||
public char skipTo(final char to) throws JSONException {
|
||||
char c;
|
||||
try {
|
||||
final long startIndex = index;
|
||||
final long startCharacter = character;
|
||||
final long startLine = line;
|
||||
reader.mark(1000000);
|
||||
do {
|
||||
c = this.next();
|
||||
if (c == 0) {
|
||||
reader.reset();
|
||||
index = startIndex;
|
||||
character = startCharacter;
|
||||
line = startLine;
|
||||
return 0;
|
||||
}
|
||||
} while (c != to);
|
||||
} catch (final IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
back();
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSONException to signal a syntax error.
|
||||
*
|
||||
* @param message The error message.
|
||||
* @return A JSONException object, suitable for throwing
|
||||
*/
|
||||
public JSONException syntaxError(final String message) {
|
||||
return new JSONException(message + toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a printable string of this JSONTokener.
|
||||
*
|
||||
* @return " at {index} [character {character} line {line}]"
|
||||
*/
|
||||
@Override public String toString() {
|
||||
return " at " + index + " [character " + character + " line " + line + "]";
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Converts a Property file data into JSONObject and back.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class Property {
|
||||
/**
|
||||
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
|
||||
*
|
||||
* @param properties java.util.Properties
|
||||
* @return JSONObject
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(final java.util.Properties properties)
|
||||
throws JSONException {
|
||||
final JSONObject jo = new JSONObject();
|
||||
if ((properties != null) && !properties.isEmpty()) {
|
||||
final Enumeration enumProperties = properties.propertyNames();
|
||||
while (enumProperties.hasMoreElements()) {
|
||||
final String name = (String) enumProperties.nextElement();
|
||||
jo.put(name, properties.getProperty(name));
|
||||
}
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the JSONObject into a property file object.
|
||||
*
|
||||
* @param jo JSONObject
|
||||
* @return java.util.Properties
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static Properties toProperties(final JSONObject jo) throws JSONException {
|
||||
final Properties properties = new Properties();
|
||||
if (jo != null) {
|
||||
final Iterator<String> keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
final String name = keys.next();
|
||||
properties.put(name, jo.getString(name));
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
@ -0,0 +1,375 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONObject, and to covert a JSONObject into an XML text.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
class XML {
|
||||
|
||||
static final Character AMP = '&';
|
||||
static final Character APOS = '\'';
|
||||
static final Character BANG = '!';
|
||||
static final Character EQ = '=';
|
||||
static final Character GT = '>';
|
||||
static final Character LT = '<';
|
||||
static final Character QUEST = '?';
|
||||
static final Character QUOT = '"';
|
||||
static final Character SLASH = '/';
|
||||
|
||||
static String escape(String string) {
|
||||
StringBuilder sb = new StringBuilder(string.length());
|
||||
for (int i = 0, length = string.length(); i < length; i++) {
|
||||
char c = string.charAt(i);
|
||||
switch (c) {
|
||||
case '&':
|
||||
sb.append("&");
|
||||
break;
|
||||
case '<':
|
||||
sb.append("<");
|
||||
break;
|
||||
case '>':
|
||||
sb.append(">");
|
||||
break;
|
||||
case '"':
|
||||
sb.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
sb.append("'");
|
||||
break;
|
||||
default:
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if the string contains whitespace. Whitespace is not allowed in tagNames and attributes.
|
||||
*
|
||||
* @param string A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
static void noSpace(String string) throws JSONException {
|
||||
int length = string.length();
|
||||
if (length == 0) {
|
||||
throw new JSONException("Empty string.");
|
||||
}
|
||||
for (char c : string.toCharArray()) {
|
||||
if (Character.isWhitespace(c)) {
|
||||
throw new JSONException('\'' + string + "' contains a space character.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the content following the named tag, attaching it to the context.
|
||||
*
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param context The JSONObject that will include the new material.
|
||||
* @param name The tag name.
|
||||
* @return true if the close tag is processed.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static boolean parse(XMLTokener x, JSONObject context, String name)
|
||||
throws JSONException {
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <! ... >
|
||||
// <![ ... ]]>
|
||||
// <? ... ?>
|
||||
// Report errors for these forms:
|
||||
// <>
|
||||
// <=
|
||||
// <<
|
||||
Object token = x.nextToken();
|
||||
// <!
|
||||
String string;
|
||||
if (token == BANG) {
|
||||
char c = x.next();
|
||||
if (c == '-') {
|
||||
if (x.next() == '-') {
|
||||
x.skipPast("-->");
|
||||
return false;
|
||||
}
|
||||
x.back();
|
||||
} else if (c == '[') {
|
||||
token = x.nextToken();
|
||||
if ("CDATA".equals(token)) {
|
||||
if (x.next() == '[') {
|
||||
string = x.nextCDATA();
|
||||
if (!string.isEmpty()) {
|
||||
context.accumulate("content", string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
int i = 1;
|
||||
do {
|
||||
token = x.nextMeta();
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if (token == LT) {
|
||||
i += 1;
|
||||
} else if (token == GT) {
|
||||
i -= 1;
|
||||
}
|
||||
} while (i > 0);
|
||||
return false;
|
||||
} else if (token == QUEST) {
|
||||
// <?
|
||||
x.skipPast("?>");
|
||||
return false;
|
||||
} else if (token == SLASH) {
|
||||
// Close tag </
|
||||
token = x.nextToken();
|
||||
if (name == null) {
|
||||
throw x.syntaxError("Mismatched close tag " + token);
|
||||
}
|
||||
if (!token.equals(name)) {
|
||||
throw x.syntaxError("Mismatched " + name + " and " + token);
|
||||
}
|
||||
if (x.nextToken() != GT) {
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return true;
|
||||
} else if (token instanceof Character) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
// Open tag <
|
||||
} else {
|
||||
String tagName = (String) token;
|
||||
token = null;
|
||||
JSONObject jsonobject = new JSONObject();
|
||||
for (; ; ) {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
// attribute = value
|
||||
if (token instanceof String) {
|
||||
string = (String) token;
|
||||
token = x.nextToken();
|
||||
if (token == EQ) {
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
jsonobject.accumulate(string, XML.stringToValue((String) token));
|
||||
token = null;
|
||||
} else {
|
||||
jsonobject.accumulate(string, "");
|
||||
}
|
||||
// Empty tag <.../>
|
||||
} else if (token == SLASH) {
|
||||
if (x.nextToken() != GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (jsonobject.length() > 0) {
|
||||
context.accumulate(tagName, jsonobject);
|
||||
} else {
|
||||
context.accumulate(tagName, "");
|
||||
}
|
||||
return false;
|
||||
// Content, between <...> and </...>
|
||||
} else if (token == GT) {
|
||||
for (; ; ) {
|
||||
token = x.nextContent();
|
||||
if (token == null) {
|
||||
if (tagName != null) {
|
||||
throw x.syntaxError("Unclosed tag " + tagName);
|
||||
}
|
||||
return false;
|
||||
} else if (token instanceof String) {
|
||||
string = (String) token;
|
||||
if (!string.isEmpty()) {
|
||||
jsonobject.accumulate("content", XML.stringToValue(string));
|
||||
}
|
||||
// Nested element
|
||||
} else if (token == LT) {
|
||||
if (parse(x, jsonobject, tagName)) {
|
||||
if (jsonobject.length() == 0) {
|
||||
context.accumulate(tagName, "");
|
||||
} else if ((jsonobject.length() == 1) && (jsonobject.opt("content")
|
||||
!= null)) {
|
||||
context.accumulate(tagName, jsonobject.opt("content"));
|
||||
} else {
|
||||
context.accumulate(tagName, jsonobject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to convert a string into a number, boolean, or null. If the string can't be converted, return the string.
|
||||
* This is much less ambitious than JSONObject.stringToValue, especially because it does not attempt to convert plus
|
||||
* forms, octal forms, hex forms, or E forms lacking decimal points.
|
||||
*
|
||||
* @param string A String.
|
||||
* @return A simple JSON value.
|
||||
*/
|
||||
static Object stringToValue(String string) {
|
||||
if ("true".equalsIgnoreCase(string)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if ("false".equalsIgnoreCase(string)) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if ("null".equalsIgnoreCase(string)) {
|
||||
return JSONObject.NULL;
|
||||
}
|
||||
//If it might be a number, try converting it, first as a Long, and then as a Double. If that doesn't work, return the string.
|
||||
try {
|
||||
char initial = string.charAt(0);
|
||||
if ((initial == '-') || ((initial >= '0') && (initial <= '9'))) {
|
||||
Long value = Long.valueOf(string);
|
||||
if (value.toString().equals(string)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException ignore) {
|
||||
try {
|
||||
Double value = Double.valueOf(string);
|
||||
if (value.toString().equals(string)) {
|
||||
return value;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
XMLTokener x = new XMLTokener(string);
|
||||
while (x.more() && x.skipPast("<")) {
|
||||
parse(x, jo, null);
|
||||
}
|
||||
return jo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
*
|
||||
* @param object A JSONObject.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object) throws JSONException {
|
||||
return toString(object, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||
*
|
||||
* @param object A JSONObject.
|
||||
* @param tagName The optional name of the enclosing tag.
|
||||
* @return A string.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static String toString(Object object, String tagName) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
int length;
|
||||
String string;
|
||||
if (object instanceof JSONObject) {
|
||||
// Emit <tagName>
|
||||
if (tagName != null) {
|
||||
sb.append('<');
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
// Loop thru the keys.
|
||||
JSONObject jo = (JSONObject) object;
|
||||
Iterator<String> keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
Object value = jo.opt(key);
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
string = value instanceof String ? (String) value : null;
|
||||
// Emit content in body
|
||||
if ("content".equals(key)) {
|
||||
if (value instanceof JSONArray) {
|
||||
ja = (JSONArray) value;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (i > 0) {
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(escape(ja.get(i).toString()));
|
||||
}
|
||||
} else {
|
||||
sb.append(escape(value.toString()));
|
||||
}
|
||||
// Emit an array of similar keys
|
||||
} else if (value instanceof JSONArray) {
|
||||
ja = (JSONArray) value;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
value = ja.get(i);
|
||||
if (value instanceof JSONArray) {
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
sb.append(toString(value));
|
||||
sb.append("</");
|
||||
sb.append(key);
|
||||
sb.append('>');
|
||||
} else {
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
} else if ("".equals(value)) {
|
||||
sb.append('<');
|
||||
sb.append(key);
|
||||
sb.append("/>");
|
||||
// Emit a new tag <k>
|
||||
} else {
|
||||
sb.append(toString(value, key));
|
||||
}
|
||||
}
|
||||
if (tagName != null) {
|
||||
// Emit the </tagname> close tag
|
||||
sb.append("</");
|
||||
sb.append(tagName);
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
// XML does not have good support for arrays. If an array appears in
|
||||
// a place
|
||||
// where XML is lacking, synthesize an <array> element.
|
||||
} else {
|
||||
if (object.getClass().isArray()) {
|
||||
object = new JSONArray(object);
|
||||
}
|
||||
if (object instanceof JSONArray) {
|
||||
ja = (JSONArray) object;
|
||||
length = ja.length();
|
||||
for (i = 0; i < length; i += 1) {
|
||||
sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName));
|
||||
}
|
||||
return sb.toString();
|
||||
} else {
|
||||
string = escape(object.toString());
|
||||
return (tagName == null) ?
|
||||
'"' + string + '"' :
|
||||
string.isEmpty() ?
|
||||
'<' + tagName + "/>" :
|
||||
'<' + tagName + '>' + string + "</" + tagName + '>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,315 @@
|
||||
package com.github.intellectualsites.plotsquared.json;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* The XMLTokener extends the JSONTokener to provide additional methods for the parsing of XML texts.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class XMLTokener extends JSONTokener {
|
||||
/**
|
||||
* The table of entity values. It initially contains Character values for amp, apos, gt, lt, quot.
|
||||
*/
|
||||
public static final HashMap<String, Character> entity;
|
||||
|
||||
static {
|
||||
entity = new HashMap<>(8);
|
||||
entity.put("amp", XML.AMP);
|
||||
entity.put("apos", XML.APOS);
|
||||
entity.put("gt", XML.GT);
|
||||
entity.put("lt", XML.LT);
|
||||
entity.put("quot", XML.QUOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an XMLTokener from a string.
|
||||
*
|
||||
* @param s A source string.
|
||||
*/
|
||||
public XMLTokener(final String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text in the CDATA block.
|
||||
*
|
||||
* @return The string up to the <code>]]></code>.
|
||||
* @throws JSONException If the <code>]]></code> is not found.
|
||||
*/
|
||||
public String nextCDATA() throws JSONException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
char c = next();
|
||||
if (end()) {
|
||||
throw syntaxError("Unclosed CDATA");
|
||||
}
|
||||
sb.append(c);
|
||||
int i = sb.length() - 3;
|
||||
if ((i >= 0) && (sb.charAt(i) == ']') && (sb.charAt(i + 1) == ']') && (sb.charAt(i + 2)
|
||||
== '>')) {
|
||||
sb.setLength(i);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next XML outer token, trimming whitespace. There are two kinds of tokens: the '<' character which begins
|
||||
* a markup tag, and the content text between markup tags.
|
||||
*
|
||||
* @return A string, or a '<' Character, or null if there is no more source text.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public Object nextContent() throws JSONException {
|
||||
char c;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
if (c == 0) {
|
||||
return null;
|
||||
}
|
||||
if (c == '<') {
|
||||
return XML.LT;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
if ((c == '<') || (c == 0)) {
|
||||
back();
|
||||
return sb.toString().trim();
|
||||
}
|
||||
if (c == '&') {
|
||||
sb.append(nextEntity('&'));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
c = next();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next entity. These entities are translated to Characters: <code>& " > <
|
||||
* "</code>.
|
||||
*
|
||||
* @param ampersand An ampersand character.
|
||||
* @return A Character or an entity String if the entity is not recognized.
|
||||
* @throws JSONException If missing ';' in XML entity.
|
||||
*/
|
||||
public Object nextEntity(final char ampersand) throws JSONException {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
final char c = next();
|
||||
if (Character.isLetterOrDigit(c) || (c == '#')) {
|
||||
sb.append(Character.toLowerCase(c));
|
||||
} else if (c == ';') {
|
||||
break;
|
||||
} else {
|
||||
throw syntaxError("Missing ';' in XML entity: &" + sb);
|
||||
}
|
||||
}
|
||||
final String string = sb.toString();
|
||||
final Object object = entity.get(string);
|
||||
return object != null ? object : ampersand + string + ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next XML meta token. This is used for skipping over <!...> and <?...?> structures.
|
||||
*
|
||||
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as Character, and strings and names are
|
||||
* returned as Boolean. We don't care what the values actually are.
|
||||
* @throws JSONException If a string is not properly closed or if the XML is badly structured.
|
||||
*/
|
||||
public Object nextMeta() throws JSONException {
|
||||
char c;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
char q;
|
||||
switch (c) {
|
||||
case 0:
|
||||
throw syntaxError("Misshaped meta tag");
|
||||
case '<':
|
||||
return XML.LT;
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
for (; ; ) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if (c == q) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
default:
|
||||
for (; ; ) {
|
||||
c = next();
|
||||
if (Character.isWhitespace(c)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '<':
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '"':
|
||||
case '\'':
|
||||
back();
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next XML Token. These tokens are found inside of angle brackets. It may be one of these characters:
|
||||
* <code>/ >= ! ?</code> or it may be a string wrapped in single quotes or double quotes, or it may be a name.
|
||||
*
|
||||
* @return a String or a Character.
|
||||
* @throws JSONException If the XML is not well formed.
|
||||
*/
|
||||
public Object nextToken() throws JSONException {
|
||||
char c;
|
||||
do {
|
||||
c = next();
|
||||
} while (Character.isWhitespace(c));
|
||||
char q;
|
||||
StringBuilder sb;
|
||||
switch (c) {
|
||||
case 0:
|
||||
throw syntaxError("Misshaped element");
|
||||
case '<':
|
||||
throw syntaxError("Misplaced '<'");
|
||||
case '>':
|
||||
return XML.GT;
|
||||
case '/':
|
||||
return XML.SLASH;
|
||||
case '=':
|
||||
return XML.EQ;
|
||||
case '!':
|
||||
return XML.BANG;
|
||||
case '?':
|
||||
return XML.QUEST;
|
||||
// Quoted string
|
||||
case '"':
|
||||
case '\'':
|
||||
q = c;
|
||||
sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
throw syntaxError("Unterminated string");
|
||||
}
|
||||
if (c == q) {
|
||||
return sb.toString();
|
||||
}
|
||||
if (c == '&') {
|
||||
sb.append(nextEntity('&'));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Name
|
||||
sb = new StringBuilder();
|
||||
for (; ; ) {
|
||||
sb.append(c);
|
||||
c = next();
|
||||
if (Character.isWhitespace(c)) {
|
||||
return sb.toString();
|
||||
}
|
||||
switch (c) {
|
||||
case 0:
|
||||
return sb.toString();
|
||||
case '>':
|
||||
case '/':
|
||||
case '=':
|
||||
case '!':
|
||||
case '?':
|
||||
case '[':
|
||||
case ']':
|
||||
back();
|
||||
return sb.toString();
|
||||
case '<':
|
||||
case '"':
|
||||
case '\'':
|
||||
throw syntaxError("Bad character in a name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip characters until past the requested string. If it is not found, we are left at the end of the source with a
|
||||
* result of false.
|
||||
*
|
||||
* @param to A string to skip past.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public boolean skipPast(final String to) throws JSONException {
|
||||
char c;
|
||||
int i;
|
||||
final int length = to.length();
|
||||
final char[] circle = new char[length];
|
||||
/*
|
||||
* First fill the circle buffer with as many characters as are in the
|
||||
* to string. If we reach an early end, bail.
|
||||
*/
|
||||
for (i = 0; i < length; i += 1) {
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
return false;
|
||||
}
|
||||
circle[i] = c;
|
||||
}
|
||||
/* We will loop, possibly for all of the remaining characters. */
|
||||
for (int offset = 0; ; ) {
|
||||
int j = offset;
|
||||
boolean b = true;
|
||||
/* Compare the circle buffer with the to string. */
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (circle[j] != to.charAt(i)) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
j += 1;
|
||||
if (j >= length) {
|
||||
j -= length;
|
||||
}
|
||||
}
|
||||
/* If we exit the loop with b intact, then victory is ours. */
|
||||
if (b) {
|
||||
return true;
|
||||
}
|
||||
/* Get the next character. If there isn't one, then defeat is ours. */
|
||||
c = next();
|
||||
if (c == 0) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Shove the character in the circle buffer and advance the
|
||||
* circle offset. The offset is mod n.
|
||||
*/
|
||||
circle[offset] = c;
|
||||
offset += 1;
|
||||
if (offset >= length) {
|
||||
offset -= length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
package com.github.intellectualsites.plotsquared.plot;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator;
|
||||
import com.github.intellectualsites.plotsquared.plot.logger.ILogger;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.BlockRegistry;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public interface IPlotMain extends ILogger {
|
||||
|
||||
/**
|
||||
* Log a message to console.
|
||||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
void log(String message);
|
||||
|
||||
/**
|
||||
* Get the `PlotSquared` directory.
|
||||
*
|
||||
* @return The plugin directory
|
||||
*/
|
||||
File getDirectory();
|
||||
|
||||
/**
|
||||
* Get the directory containing all the worlds.
|
||||
*
|
||||
* @return The directory containing the worlds
|
||||
*/
|
||||
File getWorldContainer();
|
||||
|
||||
/**
|
||||
* Wrap a player into a PlotPlayer object.
|
||||
*
|
||||
* @param player The player to convert to a PlotPlayer
|
||||
* @return A PlotPlayer
|
||||
*/
|
||||
PlotPlayer wrapPlayer(Object player);
|
||||
|
||||
/**
|
||||
* Disable the implementation.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If a full disable isn't feasibly, just disable what it can.
|
||||
* </ul>
|
||||
*/
|
||||
void disable();
|
||||
|
||||
/**
|
||||
* Completely shut down the plugin
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* Get the version of the PlotSquared being used.
|
||||
*
|
||||
* @return the plugin version
|
||||
*/
|
||||
int[] getPluginVersion();
|
||||
|
||||
/**
|
||||
* Get the version of the PlotSquared being used as a string.
|
||||
*
|
||||
* @return the plugin version as a string
|
||||
*/
|
||||
String getPluginVersionString();
|
||||
|
||||
/**
|
||||
* Usually PlotSquared
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default String getPluginName() {
|
||||
return "PlotSquared";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of Minecraft that is running.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int[] getServerVersion();
|
||||
|
||||
/**
|
||||
* Get the server implementation name and version
|
||||
*/
|
||||
String getServerImplementation();
|
||||
|
||||
/**
|
||||
* Get the NMS package prefix.
|
||||
*
|
||||
* @return The NMS package prefix
|
||||
*/
|
||||
String getNMSPackage();
|
||||
|
||||
/**
|
||||
* Get the schematic handler.
|
||||
*
|
||||
* @return The {@link SchematicHandler}
|
||||
*/
|
||||
SchematicHandler initSchematicHandler();
|
||||
|
||||
/**
|
||||
* Get the Chat Manager.
|
||||
*
|
||||
* @return The {@link ChatManager}
|
||||
*/
|
||||
ChatManager initChatManager();
|
||||
|
||||
/**
|
||||
* The task manager will run and manage Minecraft tasks.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
TaskManager getTaskManager();
|
||||
|
||||
/**
|
||||
* Run the task that will kill road mobs.
|
||||
*/
|
||||
void runEntityTask();
|
||||
|
||||
/**
|
||||
* Register the implementation specific commands.
|
||||
*/
|
||||
void registerCommands();
|
||||
|
||||
/**
|
||||
* Register the protection system.
|
||||
*/
|
||||
void registerPlayerEvents();
|
||||
|
||||
/**
|
||||
* Register inventory related events.
|
||||
*/
|
||||
void registerInventoryEvents();
|
||||
|
||||
/**
|
||||
* Register plot plus related events.
|
||||
*/
|
||||
void registerPlotPlusEvents();
|
||||
|
||||
/**
|
||||
* Register force field events.
|
||||
*/
|
||||
void registerForceFieldEvents();
|
||||
|
||||
/**
|
||||
* Register the WorldEdit hook.
|
||||
*/
|
||||
boolean initWorldEdit();
|
||||
|
||||
/**
|
||||
* Get the economy provider.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
EconHandler getEconomyHandler();
|
||||
|
||||
/**
|
||||
* Get the {@link QueueProvider} class.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
QueueProvider initBlockQueue();
|
||||
|
||||
/**
|
||||
* Get the {@link WorldUtil} class.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
WorldUtil initWorldUtil();
|
||||
|
||||
/**
|
||||
* Get the EventUtil class.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
EventUtil initEventUtil();
|
||||
|
||||
/**
|
||||
* Get the chunk manager.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
ChunkManager initChunkManager();
|
||||
|
||||
/**
|
||||
* Get the {@link SetupUtils} class.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
SetupUtils initSetupUtils();
|
||||
|
||||
/**
|
||||
* Get {@link HybridUtils} class.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
HybridUtils initHybridUtils();
|
||||
|
||||
/**
|
||||
* Start Metrics.
|
||||
*/
|
||||
void startMetrics();
|
||||
|
||||
/**
|
||||
* If a world is already loaded, set the generator (use NMS if required).
|
||||
*
|
||||
* @param world The world to set the generator
|
||||
*/
|
||||
void setGenerator(String world);
|
||||
|
||||
/**
|
||||
* Get the {@link UUIDHandlerImplementation} which will cache and
|
||||
* provide UUIDs.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
UUIDHandlerImplementation initUUIDHandler();
|
||||
|
||||
/**
|
||||
* Get the {@link InventoryUtil} class (used for implementation specific
|
||||
* inventory guis).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
InventoryUtil initInventoryUtil();
|
||||
|
||||
/**
|
||||
* Unregister a PlotPlayer from cache e.g. if they have logged off.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
void unregister(PlotPlayer player);
|
||||
|
||||
/**
|
||||
* Get the generator wrapper for a world (world) and generator (name).
|
||||
*
|
||||
* @param world
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
GeneratorWrapper<?> getGenerator(String world, String name);
|
||||
|
||||
GeneratorWrapper<?> wrapPlotGenerator(String world, IndependentPlotGenerator generator);
|
||||
|
||||
/**
|
||||
* Register the chunk processor which will clean out chunks that have too
|
||||
* many blockstates or entities.
|
||||
*/
|
||||
void registerChunkProcessor();
|
||||
|
||||
/**
|
||||
* Register the world initialization events (used to keep track of worlds
|
||||
* being generated).
|
||||
*/
|
||||
void registerWorldEvents();
|
||||
|
||||
/**
|
||||
* Usually HybridGen
|
||||
*
|
||||
* @return Default implementation generator
|
||||
*/
|
||||
IndependentPlotGenerator getDefaultGenerator();
|
||||
|
||||
/**
|
||||
* Get the class that will manage player titles.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
AbstractTitle initTitleManager();
|
||||
|
||||
List<String> getPluginIds();
|
||||
|
||||
BlockRegistry<?> getBlockRegistry();
|
||||
|
||||
LegacyMappings getLegacyMappings();
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package com.github.intellectualsites.plotsquared.plot;
|
||||
|
||||
public enum Platform {
|
||||
Bukkit, Sponge, Spigot
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@
|
||||
package com.github.intellectualsites.plotsquared.plot;
|
||||
|
||||
public class PlotVersion {
|
||||
public final int year, month, day, hash, build;
|
||||
|
||||
public PlotVersion(int year, int month, int day, int hash, int build) {
|
||||
this.year = year;
|
||||
this.month = month;
|
||||
this.day = day;
|
||||
this.hash = hash;
|
||||
this.build = build;
|
||||
}
|
||||
|
||||
public PlotVersion(String version, String commit, String date) {
|
||||
String[] split = version.substring(version.indexOf('=') + 1).split("\\.");
|
||||
this.build = Integer.parseInt(split[1]);
|
||||
this.hash = Integer.parseInt(commit.substring(commit.indexOf('=') + 1), 16);
|
||||
String[] split1 = date.substring(date.indexOf('=') + 1).split("\\.");
|
||||
this.year = Integer.parseInt(split1[0]);
|
||||
this.month = Integer.parseInt(split1[1]);
|
||||
this.day = Integer.parseInt(split1[2]);
|
||||
}
|
||||
|
||||
public static PlotVersion tryParse(String version, String commit, String date) {
|
||||
try {
|
||||
return new PlotVersion(version, commit, date);
|
||||
} catch (Exception ignore) {
|
||||
ignore.printStackTrace();
|
||||
return new PlotVersion(0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
if (hash == 0 && build == 0) {
|
||||
return "PlotSquared-" + year + "." + month + "." + day + "-SNAPSHOT";
|
||||
} else {
|
||||
return "PlotSquared-" + year + "." + month + "." + day + "-" + Integer.toHexString(hash)
|
||||
+ "-" + build;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNewer(PlotVersion other) {
|
||||
return other.build < this.build;
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.EventUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "add",
|
||||
description = "Allow a user to build in a plot while you are online",
|
||||
usage = "/plot add <player>", category = CommandCategory.SETTINGS, permission = "plots.add",
|
||||
requiredType = RequiredType.NONE) public class Add extends Command {
|
||||
|
||||
public Add() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(final PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
|
||||
final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
|
||||
checkTrue(plot.hasOwner(), C.PLOT_UNOWNED);
|
||||
checkTrue(plot.isOwner(player.getUUID()) || Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_TRUST), C.NO_PLOT_PERMS);
|
||||
checkTrue(args.length == 1, C.COMMAND_SYNTAX, getUsage());
|
||||
final Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
|
||||
checkTrue(!uuids.isEmpty(), C.INVALID_PLAYER, args[0]);
|
||||
Iterator<UUID> iter = uuids.iterator();
|
||||
int size = plot.getTrusted().size() + plot.getMembers().size();
|
||||
while (iter.hasNext()) {
|
||||
UUID uuid = iter.next();
|
||||
if (uuid == DBFunc.EVERYONE && !(
|
||||
Permissions.hasPermission(player, C.PERMISSION_TRUST_EVERYONE) || Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_TRUST))) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, MainUtil.getName(uuid));
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
if (plot.isOwner(uuid)) {
|
||||
MainUtil.sendMessage(player, C.ALREADY_OWNER, MainUtil.getName(uuid));
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
if (plot.getMembers().contains(uuid)) {
|
||||
MainUtil.sendMessage(player, C.ALREADY_ADDED, MainUtil.getName(uuid));
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
size += plot.getTrusted().contains(uuid) ? 0 : 1;
|
||||
}
|
||||
checkTrue(!uuids.isEmpty(), null);
|
||||
checkTrue(size <= plot.getArea().MAX_PLOT_MEMBERS || Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_TRUST), C.PLOT_MAX_MEMBERS);
|
||||
confirm.run(this, new Runnable() {
|
||||
@Override // Success
|
||||
public void run() {
|
||||
for (UUID uuid : uuids) {
|
||||
if (uuid != DBFunc.EVERYONE) {
|
||||
if (!plot.removeTrusted(uuid)) {
|
||||
if (plot.getDenied().contains(uuid)) {
|
||||
plot.removeDenied(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
plot.addMember(uuid);
|
||||
EventUtil.manager.callMember(player, plot, uuid, true);
|
||||
MainUtil.sendMessage(player, C.MEMBER_ADDED);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.StringWrapper;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MathMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
|
||||
@CommandDeclaration(command = "setalias", permission = "plots.alias",
|
||||
description = "Set the plot name", usage = "/plot alias <set|remove> <alias>",
|
||||
aliases = {"alias", "sa", "name", "rename", "setname", "seta", "nameplot"},
|
||||
category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE) public class Alias
|
||||
extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
|
||||
if (args.length == 0) {
|
||||
C.COMMAND_SYNTAX.send(player, "/plot alias <set|remove> <value>");
|
||||
return false;
|
||||
}
|
||||
|
||||
Location loc = player.getLocation();
|
||||
Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
|
||||
if (!plot.hasOwner()) {
|
||||
sendMessage(player, C.PLOT_NOT_CLAIMED);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!plot.isOwner(player.getUUID())) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = false;
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "set":
|
||||
if (args.length != 2) {
|
||||
C.COMMAND_SYNTAX.send(player, "/plot alias <set> <value>");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (canExecuteCommand(player, C.PERMISSION_ALIAS_SET, false) || canExecuteCommand(
|
||||
player, C.PERMISSION_ALIAS_SET_OBSOLETE, false)) {
|
||||
result = setAlias(player, plot, args[1]);
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION);
|
||||
}
|
||||
|
||||
break;
|
||||
case "remove":
|
||||
if (canExecuteCommand(player, C.PERMISSION_ALIAS_REMOVE, true)) {
|
||||
result = removeAlias(player, plot);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
C.COMMAND_SYNTAX.send(player, "/plot alias <set|remove> <alias>");
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private boolean setAlias(PlotPlayer player, Plot plot, String alias) {
|
||||
if (alias.isEmpty()) {
|
||||
C.COMMAND_SYNTAX.send(player, "/plot alias <set> <value>");
|
||||
return false;
|
||||
}
|
||||
if (alias.length() >= 50) {
|
||||
MainUtil.sendMessage(player, C.ALIAS_TOO_LONG);
|
||||
return false;
|
||||
}
|
||||
if (alias.contains(" ")) {
|
||||
C.NOT_VALID_VALUE.send(player);
|
||||
return false;
|
||||
}
|
||||
if (MathMan.isInteger(alias)) {
|
||||
C.NOT_VALID_VALUE.send(player);
|
||||
return false;
|
||||
}
|
||||
for (Plot p : PlotSquared.get().getPlots(plot.getArea())) {
|
||||
if (p.getAlias().equalsIgnoreCase(alias)) {
|
||||
MainUtil.sendMessage(player, C.ALIAS_IS_TAKEN);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (UUIDHandler.nameExists(new StringWrapper(alias)) || PlotSquared.get()
|
||||
.hasPlotArea(alias)) {
|
||||
MainUtil.sendMessage(player, C.ALIAS_IS_TAKEN);
|
||||
return false;
|
||||
}
|
||||
plot.setAlias(alias);
|
||||
MainUtil.sendMessage(player, C.ALIAS_SET_TO.s().replaceAll("%alias%", alias));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean removeAlias(PlotPlayer player, Plot plot) {
|
||||
plot.setAlias(null);
|
||||
MainUtil.sendMessage(player, C.ALIAS_REMOVED.s());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canExecuteCommand(PlotPlayer player, C caption, boolean sendMessage) {
|
||||
if (!Permissions.hasPermission(player, caption)) {
|
||||
if (sendMessage) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,469 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.configuration.ConfigurationSection;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Configuration;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.AugmentedUtils;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridPlotWorld;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@CommandDeclaration(command = "area", permission = "plots.area",
|
||||
category = CommandCategory.ADMINISTRATION, requiredType = RequiredType.NONE,
|
||||
description = "Create a new PlotArea", aliases = "world",
|
||||
usage = "/plot area <create|info|list|tp|regen>", confirmation = true) public class Area
|
||||
extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
if (args.length == 0) {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "c":
|
||||
case "setup":
|
||||
case "create":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_AREA_CREATE)) {
|
||||
C.NO_PERMISSION.send(player, C.PERMISSION_AREA_CREATE);
|
||||
return false;
|
||||
}
|
||||
switch (args.length) {
|
||||
case 1:
|
||||
C.COMMAND_SYNTAX
|
||||
.send(player, "/plot area create [world[:id]] [<modifier>=<value>]...");
|
||||
return false;
|
||||
case 2:
|
||||
switch (args[1].toLowerCase()) {
|
||||
case "pos1": { // Set position 1
|
||||
HybridPlotWorld area = player.getMeta("area_create_area");
|
||||
if (area == null) {
|
||||
C.COMMAND_SYNTAX.send(player,
|
||||
"/plot area create [world[:id]] [<modifier>=<value>]...");
|
||||
return false;
|
||||
}
|
||||
Location location = player.getLocation();
|
||||
player.setMeta("area_pos1", location);
|
||||
C.SET_ATTRIBUTE.send(player, "area_pos1",
|
||||
location.getX() + "," + location.getZ());
|
||||
MainUtil.sendMessage(player,
|
||||
"You will now set pos2: /plot area create pos2"
|
||||
+ "\nNote: The chosen plot size may result in the created area not exactly matching your second position.");
|
||||
return true;
|
||||
}
|
||||
case "pos2": // Set position 2 and finish creation for type=2 (partial)
|
||||
final HybridPlotWorld area = player.getMeta("area_create_area");
|
||||
if (area == null) {
|
||||
C.COMMAND_SYNTAX.send(player,
|
||||
"/plot area create [world[:id]] [<modifier>=<value>]...");
|
||||
return false;
|
||||
}
|
||||
Location pos1 = player.getLocation();
|
||||
Location pos2 = player.getMeta("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);
|
||||
final RegionWrapper region = new RegionWrapper(bx, tx, bz, tz);
|
||||
Set<PlotArea> areas =
|
||||
PlotSquared.get().getPlotAreas(area.worldname, region);
|
||||
if (!areas.isEmpty()) {
|
||||
C.CLUSTER_INTERSECTION
|
||||
.send(player, areas.iterator().next().toString());
|
||||
return false;
|
||||
}
|
||||
final SetupObject object = new SetupObject();
|
||||
object.world = area.worldname;
|
||||
object.id = area.id;
|
||||
object.terrain = area.TERRAIN;
|
||||
object.type = area.TYPE;
|
||||
object.min = new PlotId(1, 1);
|
||||
object.max = new PlotId(numX, numZ);
|
||||
object.plotManager = PlotSquared.imp().getPluginName();
|
||||
object.setupGenerator = PlotSquared.imp().getPluginName();
|
||||
object.step = area.getSettingNodes();
|
||||
final String path =
|
||||
"worlds." + area.worldname + ".areas." + area.id + '-'
|
||||
+ object.min + '-' + object.max;
|
||||
Runnable run = () -> {
|
||||
if (offsetX != 0) {
|
||||
PlotSquared.get().worlds
|
||||
.set(path + ".road.offset.x", offsetX);
|
||||
}
|
||||
if (offsetZ != 0) {
|
||||
PlotSquared.get().worlds
|
||||
.set(path + ".road.offset.z", offsetZ);
|
||||
}
|
||||
final String world = SetupUtils.manager.setupWorld(object);
|
||||
if (WorldUtil.IMP.isWorld(world)) {
|
||||
PlotSquared.get().loadWorld(world, null);
|
||||
C.SETUP_FINISHED.send(player);
|
||||
player.teleport(WorldUtil.IMP.getSpawn(world));
|
||||
if (area.TERRAIN != 3) {
|
||||
ChunkManager.largeRegionTask(world, region,
|
||||
new RunnableVal<ChunkLoc>() {
|
||||
@Override public void run(ChunkLoc value) {
|
||||
AugmentedUtils
|
||||
.generate(world, value.x, value.z,
|
||||
null);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
} else {
|
||||
MainUtil.sendMessage(player,
|
||||
"An error occurred while creating the world: "
|
||||
+ area.worldname);
|
||||
}
|
||||
};
|
||||
if (hasConfirmation(player)) {
|
||||
CmdConfirm.addPending(player,
|
||||
getCommandString() + " create pos2 (Creates world)", run);
|
||||
} else {
|
||||
run.run();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default: // Start creation
|
||||
final SetupObject object = new SetupObject();
|
||||
String[] split = args[1].split(":");
|
||||
String id;
|
||||
if (split.length == 2) {
|
||||
id = split[1];
|
||||
} else {
|
||||
id = null;
|
||||
}
|
||||
object.world = split[0];
|
||||
final HybridPlotWorld pa = new HybridPlotWorld(object.world, id,
|
||||
PlotSquared.get().IMP.getDefaultGenerator(), null, null);
|
||||
PlotArea other = PlotSquared.get().getPlotArea(pa.worldname, id);
|
||||
if (other != null && Objects.equals(pa.id, other.id)) {
|
||||
C.SETUP_WORLD_TAKEN.send(player, pa.toString());
|
||||
return false;
|
||||
}
|
||||
Set<PlotArea> areas = PlotSquared.get().getPlotAreas(pa.worldname);
|
||||
if (!areas.isEmpty()) {
|
||||
PlotArea area = areas.iterator().next();
|
||||
pa.TYPE = area.TYPE;
|
||||
}
|
||||
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) {
|
||||
C.COMMAND_SYNTAX.send(player, getCommandString()
|
||||
+ " create [world[:id]] [<modifier>=<value>]...");
|
||||
return false;
|
||||
}
|
||||
switch (pair[0].toLowerCase()) {
|
||||
case "s":
|
||||
case "size":
|
||||
pa.PLOT_WIDTH = Integer.parseInt(pair[1]);
|
||||
pa.SIZE = (short) (pa.PLOT_WIDTH + pa.ROAD_WIDTH);
|
||||
break;
|
||||
case "g":
|
||||
case "gap":
|
||||
pa.ROAD_WIDTH = Integer.parseInt(pair[1]);
|
||||
pa.SIZE = (short) (pa.PLOT_WIDTH + pa.ROAD_WIDTH);
|
||||
break;
|
||||
case "h":
|
||||
case "height":
|
||||
int value = Integer.parseInt(pair[1]);
|
||||
pa.PLOT_HEIGHT = value;
|
||||
pa.ROAD_HEIGHT = value;
|
||||
pa.WALL_HEIGHT = value;
|
||||
break;
|
||||
case "f":
|
||||
case "floor":
|
||||
pa.TOP_BLOCK = Configuration.BLOCK_BUCKET.parseString(pair[1]);
|
||||
break;
|
||||
case "m":
|
||||
case "main":
|
||||
pa.MAIN_BLOCK = Configuration.BLOCK_BUCKET.parseString(pair[1]);
|
||||
break;
|
||||
case "w":
|
||||
case "wall":
|
||||
pa.WALL_FILLING =
|
||||
Configuration.BLOCK_BUCKET.parseString(pair[1]);
|
||||
break;
|
||||
case "b":
|
||||
case "border":
|
||||
pa.WALL_BLOCK = Configuration.BLOCK_BUCKET.parseString(pair[1]);
|
||||
break;
|
||||
case "terrain":
|
||||
pa.TERRAIN = Integer.parseInt(pair[1]);
|
||||
object.terrain = pa.TERRAIN;
|
||||
break;
|
||||
case "type":
|
||||
pa.TYPE = Integer.parseInt(pair[1]);
|
||||
object.type = pa.TYPE;
|
||||
break;
|
||||
default:
|
||||
C.COMMAND_SYNTAX.send(player, getCommandString()
|
||||
+ " create [world[:id]] [<modifier>=<value>]...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (pa.TYPE != 2) {
|
||||
if (WorldUtil.IMP.isWorld(pa.worldname)) {
|
||||
C.SETUP_WORLD_TAKEN.send(player, pa.worldname);
|
||||
return false;
|
||||
}
|
||||
Runnable run = () -> {
|
||||
String path = "worlds." + pa.worldname;
|
||||
if (!PlotSquared.get().worlds.contains(path)) {
|
||||
PlotSquared.get().worlds.createSection(path);
|
||||
}
|
||||
ConfigurationSection section =
|
||||
PlotSquared.get().worlds.getConfigurationSection(path);
|
||||
pa.saveConfiguration(section);
|
||||
pa.loadConfiguration(section);
|
||||
object.plotManager = PlotSquared.imp().getPluginName();
|
||||
object.setupGenerator = PlotSquared.imp().getPluginName();
|
||||
String world = SetupUtils.manager.setupWorld(object);
|
||||
if (WorldUtil.IMP.isWorld(world)) {
|
||||
C.SETUP_FINISHED.send(player);
|
||||
player.teleport(WorldUtil.IMP.getSpawn(world));
|
||||
} else {
|
||||
MainUtil.sendMessage(player,
|
||||
"An error occurred while creating the world: "
|
||||
+ pa.worldname);
|
||||
}
|
||||
try {
|
||||
PlotSquared.get().worlds.save(PlotSquared.get().worldsFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
if (hasConfirmation(player)) {
|
||||
CmdConfirm.addPending(player,
|
||||
getCommandString() + ' ' + StringMan.join(args, " "), run);
|
||||
} else {
|
||||
run.run();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (pa.id == null) {
|
||||
C.COMMAND_SYNTAX.send(player, getCommandString()
|
||||
+ " create [world[:id]] [<modifier>=<value>]...");
|
||||
return false;
|
||||
}
|
||||
if (WorldUtil.IMP.isWorld(pa.worldname)) {
|
||||
if (!player.getLocation().getWorld().equals(pa.worldname)) {
|
||||
player.teleport(WorldUtil.IMP.getSpawn(pa.worldname));
|
||||
}
|
||||
} else {
|
||||
object.terrain = 0;
|
||||
object.type = 0;
|
||||
SetupUtils.manager.setupWorld(object);
|
||||
player.teleport(WorldUtil.IMP.getSpawn(pa.worldname));
|
||||
}
|
||||
player.setMeta("area_create_area", pa);
|
||||
MainUtil.sendMessage(player,
|
||||
"$1Go to the first corner and use: $2 " + getCommandString()
|
||||
+ " create pos1");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
case "i":
|
||||
case "info": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_AREA_INFO)) {
|
||||
C.NO_PERMISSION.send(player, C.PERMISSION_AREA_INFO);
|
||||
return false;
|
||||
}
|
||||
PlotArea area;
|
||||
switch (args.length) {
|
||||
case 1:
|
||||
area = player.getApplicablePlotArea();
|
||||
break;
|
||||
case 2:
|
||||
area = PlotSquared.get().getPlotAreaByString(args[1]);
|
||||
break;
|
||||
default:
|
||||
C.COMMAND_SYNTAX.send(player, getCommandString() + " info [area]");
|
||||
return false;
|
||||
}
|
||||
if (area == null) {
|
||||
if (args.length == 2) {
|
||||
C.NOT_VALID_PLOT_WORLD.send(player, args[1]);
|
||||
} else {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
}
|
||||
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.TYPE == 2) {
|
||||
PlotId min = area.getMin();
|
||||
PlotId max = area.getMax();
|
||||
name = area.worldname + ';' + area.id + ';' + min + ';' + max;
|
||||
int size = (max.x - min.x + 1) * (max.y - min.y + 1);
|
||||
percent = claimed == 0 ? 0 : size / (double) claimed;
|
||||
region = area.getRegion().toString();
|
||||
} else {
|
||||
name = area.worldname;
|
||||
percent = claimed == 0 ? 0 : 100d * claimed / Integer.MAX_VALUE;
|
||||
region = "N/A";
|
||||
}
|
||||
String value = "&r$1NAME: " + name + "\n$1Type: $2" + area.TYPE + "\n$1Terrain: $2"
|
||||
+ area.TERRAIN + "\n$1Usage: $2" + String.format("%.2f", percent) + '%'
|
||||
+ "\n$1Claimed: $2" + claimed + "\n$1Clusters: $2" + clusters + "\n$1Region: $2"
|
||||
+ region + "\n$1Generator: $2" + generator;
|
||||
MainUtil.sendMessage(player,
|
||||
C.PLOT_INFO_HEADER.s() + '\n' + value + '\n' + C.PLOT_INFO_FOOTER.s(), false);
|
||||
return true;
|
||||
}
|
||||
case "l":
|
||||
case "list":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_AREA_LIST)) {
|
||||
C.NO_PERMISSION.send(player, C.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:
|
||||
C.COMMAND_SYNTAX.send(player, getCommandString() + " list [#]");
|
||||
return false;
|
||||
}
|
||||
ArrayList<PlotArea> areas = new ArrayList<>(PlotSquared.get().getPlotAreas());
|
||||
paginate(player, areas, 8, page,
|
||||
new RunnableVal3<Integer, PlotArea, PlotMessage>() {
|
||||
@Override public void run(Integer i, PlotArea area, PlotMessage message) {
|
||||
String name;
|
||||
double percent;
|
||||
int claimed = area.getPlotCount();
|
||||
int clusters = area.getClusters().size();
|
||||
String region;
|
||||
String generator = String.valueOf(area.getGenerator());
|
||||
if (area.TYPE == 2) {
|
||||
PlotId min = area.getMin();
|
||||
PlotId max = area.getMax();
|
||||
name = area.worldname + ';' + area.id + ';' + min + ';' + max;
|
||||
int size = (max.x - min.x + 1) * (max.y - min.y + 1);
|
||||
percent = claimed == 0 ? 0 : size / (double) claimed;
|
||||
region = area.getRegion().toString();
|
||||
} else {
|
||||
name = area.worldname;
|
||||
percent = claimed == 0 ?
|
||||
0 :
|
||||
Short.MAX_VALUE * Short.MAX_VALUE / (double) claimed;
|
||||
region = "N/A";
|
||||
}
|
||||
PlotMessage tooltip = new PlotMessage().text("Claimed=").color("$1")
|
||||
.text(String.valueOf(claimed)).color("$2").text("\nUsage=")
|
||||
.color("$1").text(String.format("%.2f", percent) + '%').color("$2")
|
||||
.text("\nClusters=").color("$1").text(String.valueOf(clusters))
|
||||
.color("$2").text("\nRegion=").color("$1").text(region).color("$2")
|
||||
.text("\nGenerator=").color("$1").text(generator).color("$2");
|
||||
|
||||
// type / terrain
|
||||
String visit = "/plot area tp " + area.toString();
|
||||
message.text("[").color("$3").text(String.valueOf(i)).command(visit)
|
||||
.tooltip(visit).color("$1").text("]").color("$3").text(' ' + name)
|
||||
.tooltip(tooltip).command(getCommandString() + " info " + area)
|
||||
.color("$1").text(" - ").color("$2")
|
||||
.text(area.TYPE + ":" + area.TERRAIN).color("$3");
|
||||
}
|
||||
}, "/plot area list", C.AREA_LIST_HEADER_PAGED.s());
|
||||
return true;
|
||||
case "regen":
|
||||
case "clear":
|
||||
case "reset":
|
||||
case "regenerate": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_AREA_REGEN)) {
|
||||
C.NO_PERMISSION.send(player, C.PERMISSION_AREA_REGEN);
|
||||
return false;
|
||||
}
|
||||
final PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
if (area.TYPE != 2) {
|
||||
MainUtil.sendMessage(player,
|
||||
"$4Stop the server and delete: " + area.worldname + "/region");
|
||||
return false;
|
||||
}
|
||||
ChunkManager
|
||||
.largeRegionTask(area.worldname, area.getRegion(), new RunnableVal<ChunkLoc>() {
|
||||
@Override public void run(ChunkLoc value) {
|
||||
AugmentedUtils.generate(area.worldname, value.x, value.z, null);
|
||||
}
|
||||
}, () -> player.sendMessage("Regen complete"));
|
||||
return true;
|
||||
}
|
||||
case "goto":
|
||||
case "v":
|
||||
case "teleport":
|
||||
case "visit":
|
||||
case "tp":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_AREA_TP)) {
|
||||
C.NO_PERMISSION.send(player, C.PERMISSION_AREA_TP);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 2) {
|
||||
C.COMMAND_SYNTAX.send(player, "/plot visit [area]");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[1]);
|
||||
if (area == null) {
|
||||
C.NOT_VALID_PLOT_WORLD.send(player, args[1]);
|
||||
return false;
|
||||
}
|
||||
Location center;
|
||||
if (area.TYPE != 2) {
|
||||
center = WorldUtil.IMP.getSpawn(area.worldname);
|
||||
} else {
|
||||
RegionWrapper region = area.getRegion();
|
||||
center =
|
||||
new Location(area.worldname, region.minX + (region.maxX - region.minX) / 2,
|
||||
0, region.minZ + (region.maxZ - region.minZ) / 2);
|
||||
center.setY(1 + WorldUtil.IMP
|
||||
.getHighestBlock(area.worldname, center.getX(), center.getZ()));
|
||||
}
|
||||
player.teleport(center);
|
||||
return true;
|
||||
case "delete":
|
||||
case "remove":
|
||||
MainUtil.sendMessage(player,
|
||||
"$1World creation settings may be stored in multiple locations:"
|
||||
+ "\n$3 - $2Bukkit bukkit.yml" + "\n$3 - $2" + PlotSquared.imp()
|
||||
.getPluginName() + " settings.yml"
|
||||
+ "\n$3 - $2Multiverse worlds.yml (or any world management plugin)"
|
||||
+ "\n$1Stop the server and delete it from these locations.");
|
||||
return true;
|
||||
}
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Set;
|
||||
|
||||
@CommandDeclaration(command = "auto", permission = "plots.auto",
|
||||
category = CommandCategory.CLAIMING, requiredType = RequiredType.NONE,
|
||||
description = "Claim the nearest plot", aliases = "a", usage = "/plot auto [length,width]")
|
||||
public class Auto extends SubCommand {
|
||||
|
||||
@Deprecated public static PlotId getNextPlotId(PlotId id, int step) {
|
||||
return id.getNextId(step);
|
||||
}
|
||||
|
||||
private static boolean checkAllowedPlots(PlotPlayer player, PlotArea plotarea,
|
||||
@Nullable Integer allowed_plots, int size_x, int size_z) {
|
||||
if (allowed_plots == null)
|
||||
allowed_plots = player.getAllowedPlots();
|
||||
int currentPlots =
|
||||
Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(plotarea.worldname);
|
||||
int diff = currentPlots - allowed_plots;
|
||||
if (diff + size_x * size_z > 0) {
|
||||
if (diff < 0) {
|
||||
MainUtil.sendMessage(player, C.CANT_CLAIM_MORE_PLOTS_NUM, -diff + "");
|
||||
return false;
|
||||
} else if (player.hasPersistentMeta("grantedPlots")) {
|
||||
int grantedPlots =
|
||||
ByteArrayUtilities.bytesToInteger(player.getPersistentMeta("grantedPlots"));
|
||||
if (grantedPlots - diff < size_x * size_z) {
|
||||
player.removePersistentMeta("grantedPlots");
|
||||
MainUtil.sendMessage(player, C.CANT_CLAIM_MORE_PLOTS);
|
||||
return false;
|
||||
} else {
|
||||
int left = grantedPlots - diff - size_x * size_z;
|
||||
if (left == 0) {
|
||||
player.removePersistentMeta("grantedPlots");
|
||||
} else {
|
||||
player.setPersistentMeta("grantedPlots",
|
||||
ByteArrayUtilities.integerToBytes(left));
|
||||
}
|
||||
MainUtil.sendMessage(player, C.REMOVED_GRANTED_PLOT, "" + left,
|
||||
"" + (grantedPlots - left));
|
||||
}
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.CANT_CLAIM_MORE_PLOTS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teleport the player home, or claim a new plot
|
||||
*
|
||||
* @param player
|
||||
* @param area
|
||||
* @param start
|
||||
* @param schem
|
||||
*/
|
||||
public static void homeOrAuto(final PlotPlayer player, final PlotArea area, PlotId start,
|
||||
final String schem) {
|
||||
Set<Plot> plots = player.getPlots();
|
||||
if (!plots.isEmpty()) {
|
||||
plots.iterator().next().teleportPlayer(player);
|
||||
} else {
|
||||
autoClaimSafe(player, area, start, schem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim a new plot for a player
|
||||
*
|
||||
* @param player
|
||||
* @param area
|
||||
* @param start
|
||||
* @param schem
|
||||
*/
|
||||
public static void autoClaimSafe(final PlotPlayer player, final PlotArea area, PlotId start,
|
||||
final String schem) {
|
||||
autoClaimSafe(player, area, start, schem, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim a new plot for a player
|
||||
*
|
||||
* @param player
|
||||
* @param area
|
||||
* @param start
|
||||
* @param schem
|
||||
*/
|
||||
public static void autoClaimSafe(final PlotPlayer player, final PlotArea area, PlotId start,
|
||||
final String schem, @Nullable final Integer allowed_plots) {
|
||||
player.setMeta(Auto.class.getName(), true);
|
||||
autoClaimFromDatabase(player, area, start, new RunnableVal<Plot>() {
|
||||
@Override public void run(final Plot plot) {
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override public void run(Object ignore) {
|
||||
player.deleteMeta(Auto.class.getName());
|
||||
if (plot == null) {
|
||||
MainUtil.sendMessage(player, C.NO_FREE_PLOTS);
|
||||
} else if (checkAllowedPlots(player, area, allowed_plots, 1, 1)) {
|
||||
plot.claim(player, true, schem, false);
|
||||
if (area.AUTO_MERGE) {
|
||||
plot.autoMerge(-1, Integer.MAX_VALUE, player.getUUID(), true);
|
||||
}
|
||||
} else {
|
||||
DBFunc.delete(plot);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void autoClaimFromDatabase(final PlotPlayer player, final PlotArea area,
|
||||
PlotId start, final RunnableVal<Plot> whenDone) {
|
||||
final Plot plot = area.getNextFreePlot(player, start);
|
||||
if (plot == null) {
|
||||
whenDone.run(null);
|
||||
return;
|
||||
}
|
||||
whenDone.value = plot;
|
||||
plot.owner = player.getUUID();
|
||||
DBFunc.createPlotSafe(plot, whenDone, new Runnable() {
|
||||
@Override public void run() {
|
||||
autoClaimFromDatabase(player, area, plot.getId(), whenDone);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
PlotArea plotarea = player.getApplicablePlotArea();
|
||||
if (plotarea == null) {
|
||||
if (EconHandler.manager != null) {
|
||||
for (PlotArea area : PlotSquared.get().getPlotAreaManager().getAllPlotAreas()) {
|
||||
if (EconHandler.manager
|
||||
.hasPermission(area.worldname, player.getName(), "plots.auto")) {
|
||||
if (plotarea != null) {
|
||||
plotarea = null;
|
||||
break;
|
||||
}
|
||||
plotarea = area;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (plotarea == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_PLOT_WORLD);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int size_x = 1;
|
||||
int size_z = 1;
|
||||
String schematic = null;
|
||||
if (args.length > 0) {
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_AUTO_MEGA)) {
|
||||
try {
|
||||
String[] split = args[0].split(",|;");
|
||||
size_x = Integer.parseInt(split[0]);
|
||||
size_z = Integer.parseInt(split[1]);
|
||||
if (size_x < 1 || size_z < 1) {
|
||||
MainUtil.sendMessage(player, "&cError: size<=0");
|
||||
}
|
||||
if (args.length > 1) {
|
||||
schematic = args[1];
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
size_x = 1;
|
||||
size_z = 1;
|
||||
schematic = args[0];
|
||||
// PlayerFunctions.sendMessage(plr,
|
||||
// "&cError: Invalid size (X,Y)");
|
||||
// return false;
|
||||
}
|
||||
} else {
|
||||
schematic = args[0];
|
||||
// PlayerFunctions.sendMessage(plr, C.NO_PERMISSION);
|
||||
// return false;
|
||||
}
|
||||
}
|
||||
if (size_x * size_z > Settings.Claim.MAX_AUTO_AREA) {
|
||||
MainUtil.sendMessage(player, C.CANT_CLAIM_MORE_PLOTS_NUM,
|
||||
Settings.Claim.MAX_AUTO_AREA + "");
|
||||
return false;
|
||||
}
|
||||
final int allowed_plots = player.getAllowedPlots();
|
||||
if (player.getMeta(Auto.class.getName(), false) || !checkAllowedPlots(player, plotarea,
|
||||
allowed_plots, size_x, size_z))
|
||||
return false;
|
||||
|
||||
if (schematic != null && !schematic.isEmpty()) {
|
||||
if (!plotarea.SCHEMATICS.contains(schematic.toLowerCase())) {
|
||||
sendMessage(player, C.SCHEMATIC_INVALID, "non-existent: " + schematic);
|
||||
return true;
|
||||
}
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLAIM_SCHEMATIC.f(schematic))
|
||||
&& !Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_SCHEMATIC)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLAIM_SCHEMATIC.f(schematic));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (EconHandler.manager != null && plotarea.USE_ECONOMY) {
|
||||
Expression<Double> costExp = plotarea.PRICES.get("claim");
|
||||
double cost = costExp.evaluate((double) (Settings.Limit.GLOBAL ?
|
||||
player.getPlotCount() :
|
||||
player.getPlotCount(plotarea.worldname)));
|
||||
cost = (size_x * size_z) * cost;
|
||||
if (cost > 0d) {
|
||||
if (EconHandler.manager.getMoney(player) < cost) {
|
||||
sendMessage(player, C.CANNOT_AFFORD_PLOT, "" + cost);
|
||||
return true;
|
||||
}
|
||||
EconHandler.manager.withdrawMoney(player, cost);
|
||||
sendMessage(player, C.REMOVED_BALANCE, cost + "");
|
||||
}
|
||||
}
|
||||
// TODO handle type 2 the same as normal worlds!
|
||||
if (size_x == 1 && size_z == 1) {
|
||||
autoClaimSafe(player, plotarea, null, schematic, allowed_plots);
|
||||
return true;
|
||||
} else {
|
||||
if (plotarea.TYPE == 2) {
|
||||
MainUtil.sendMessage(player, C.NO_FREE_PLOTS);
|
||||
return false;
|
||||
}
|
||||
while (true) {
|
||||
PlotId start = plotarea.getMeta("lastPlot", new PlotId(0, 0)).getNextId(1);
|
||||
PlotId end = new PlotId(start.x + size_x - 1, start.y + size_z - 1);
|
||||
if (plotarea.canClaim(player, start, end)) {
|
||||
plotarea.setMeta("lastPlot", start);
|
||||
for (int i = start.x; i <= end.x; i++) {
|
||||
for (int j = start.y; j <= end.y; j++) {
|
||||
Plot plot = plotarea.getPlotAbs(new PlotId(i, j));
|
||||
boolean teleport = i == end.x && j == end.y;
|
||||
plot.claim(player, teleport, null);
|
||||
}
|
||||
}
|
||||
if (!plotarea.mergePlots(MainUtil.getPlotSelectionIds(start, end), true)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
plotarea.setMeta("lastPlot", start);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
|
||||
|
||||
@CommandDeclaration(command = "setbiome", permission = "plots.set.biome",
|
||||
description = "Set the plot biome", usage = "/plot biome [biome]",
|
||||
aliases = {"biome", "sb", "setb", "b"}, category = CommandCategory.APPEARANCE,
|
||||
requiredType = RequiredType.NONE) public class Biome extends SetCommand {
|
||||
|
||||
@Override public boolean set(final PlotPlayer player, final Plot plot, final String value) {
|
||||
int biome = WorldUtil.IMP.getBiomeFromString(value);
|
||||
if (biome == -1) {
|
||||
String biomes =
|
||||
StringMan.join(WorldUtil.IMP.getBiomeList(), C.BLOCK_LIST_SEPARATER.s());
|
||||
C.NEED_BIOME.send(player);
|
||||
MainUtil.sendMessage(player, C.SUBCOMMAND_SET_OPTIONS_HEADER.s() + biomes);
|
||||
return false;
|
||||
}
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
plot.addRunning();
|
||||
plot.setBiome(value.toUpperCase(), new Runnable() {
|
||||
@Override public void run() {
|
||||
plot.removeRunning();
|
||||
MainUtil.sendMessage(player, C.BIOME_SET_TO.s() + value.toLowerCase());
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.EconHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@CommandDeclaration(command = "buy", description = "Buy the plot you are standing on",
|
||||
usage = "/plot buy", permission = "plots.buy", category = CommandCategory.CLAIMING,
|
||||
requiredType = RequiredType.NONE) public class Buy extends Command {
|
||||
|
||||
public Buy() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(final PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
final RunnableVal2<Command, CommandResult> whenDone) {
|
||||
check(EconHandler.manager, C.ECON_DISABLED);
|
||||
final Plot plot;
|
||||
if (args.length != 0) {
|
||||
checkTrue(args.length == 1, C.COMMAND_SYNTAX, getUsage());
|
||||
plot = check(MainUtil.getPlotFromString(player, args[0], true), null);
|
||||
} else {
|
||||
plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
|
||||
}
|
||||
checkTrue(plot.hasOwner(), C.PLOT_UNOWNED);
|
||||
checkTrue(!plot.isOwner(player.getUUID()), C.CANNOT_BUY_OWN);
|
||||
Set<Plot> plots = plot.getConnectedPlots();
|
||||
checkTrue(player.getPlotCount() + plots.size() <= player.getAllowedPlots(),
|
||||
C.CANT_CLAIM_MORE_PLOTS);
|
||||
Optional<Double> flag = plot.getFlag(Flags.PRICE);
|
||||
if (!flag.isPresent()) {
|
||||
throw new CommandException(C.NOT_FOR_SALE);
|
||||
}
|
||||
final double price = flag.get();
|
||||
checkTrue(player.getMoney() >= price, C.CANNOT_AFFORD_PLOT);
|
||||
player.withdraw(price);
|
||||
confirm.run(this, new Runnable() {
|
||||
@Override // Success
|
||||
public void run() {
|
||||
C.REMOVED_BALANCE.send(player, price);
|
||||
EconHandler.manager
|
||||
.depositMoney(UUIDHandler.getUUIDWrapper().getOfflinePlayer(plot.owner), price);
|
||||
PlotPlayer owner = UUIDHandler.getPlayer(plot.owner);
|
||||
if (owner != null) {
|
||||
C.PLOT_SOLD.send(owner, plot.getId(), player.getName(), price);
|
||||
}
|
||||
plot.removeFlag(Flags.PRICE);
|
||||
plot.setOwner(player.getUUID());
|
||||
C.CLAIMED.send(player);
|
||||
whenDone.run(Buy.this, CommandResult.SUCCESS);
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override // Failure
|
||||
public void run() {
|
||||
player.deposit(price);
|
||||
whenDone.run(Buy.this, CommandResult.FAILURE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
|
||||
@CommandDeclaration(command = "chat", description = "Toggle plot chat on or off",
|
||||
usage = "/plot chat [on|off]", permission = "plots.chat", category = CommandCategory.CHAT,
|
||||
requiredType = RequiredType.NONE) public class Chat extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
MainCommand.getInstance().toggle.chat(this, player, new String[0], null, null);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.ByteArrayUtilities;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.EconHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
|
||||
@CommandDeclaration(command = "claim", aliases = "c",
|
||||
description = "Claim the current plot you're standing on", category = CommandCategory.CLAIMING,
|
||||
requiredType = RequiredType.NONE, permission = "plots.claim", usage = "/plot claim")
|
||||
public class Claim extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
String schematic = "";
|
||||
if (args.length >= 1) {
|
||||
schematic = args[0];
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
final Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
int currentPlots =
|
||||
Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(loc.getWorld());
|
||||
int grants = 0;
|
||||
if (currentPlots >= player.getAllowedPlots()) {
|
||||
if (player.hasPersistentMeta("grantedPlots")) {
|
||||
grants =
|
||||
ByteArrayUtilities.bytesToInteger(player.getPersistentMeta("grantedPlots"));
|
||||
if (grants <= 0) {
|
||||
player.removePersistentMeta("grantedPlots");
|
||||
return sendMessage(player, C.CANT_CLAIM_MORE_PLOTS);
|
||||
}
|
||||
} else {
|
||||
return sendMessage(player, C.CANT_CLAIM_MORE_PLOTS);
|
||||
}
|
||||
}
|
||||
if (!plot.canClaim(player)) {
|
||||
return sendMessage(player, C.PLOT_IS_CLAIMED);
|
||||
}
|
||||
final PlotArea area = plot.getArea();
|
||||
if (!schematic.isEmpty()) {
|
||||
if (area.SCHEMATIC_CLAIM_SPECIFY) {
|
||||
if (!area.SCHEMATICS.contains(schematic.toLowerCase())) {
|
||||
return sendMessage(player, C.SCHEMATIC_INVALID, "non-existent: " + schematic);
|
||||
}
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLAIM_SCHEMATIC.f(schematic))
|
||||
&& !Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_SCHEMATIC)) {
|
||||
return sendMessage(player, C.NO_SCHEMATIC_PERMISSION, schematic);
|
||||
}
|
||||
}
|
||||
}
|
||||
int border = area.getBorder();
|
||||
if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border) {
|
||||
return !sendMessage(player, C.BORDER);
|
||||
}
|
||||
if ((EconHandler.manager != null) && area.USE_ECONOMY) {
|
||||
Expression<Double> costExr = area.PRICES.get("claim");
|
||||
double cost = costExr.evaluate((double) currentPlots);
|
||||
if (cost > 0d) {
|
||||
if (EconHandler.manager.getMoney(player) < cost) {
|
||||
return sendMessage(player, C.CANNOT_AFFORD_PLOT, "" + cost);
|
||||
}
|
||||
EconHandler.manager.withdrawMoney(player, cost);
|
||||
sendMessage(player, C.REMOVED_BALANCE, cost + "");
|
||||
}
|
||||
}
|
||||
if (grants > 0) {
|
||||
if (grants == 1) {
|
||||
player.removePersistentMeta("grantedPlots");
|
||||
} else {
|
||||
player.setPersistentMeta("grantedPlots",
|
||||
ByteArrayUtilities.integerToBytes(grants - 1));
|
||||
}
|
||||
sendMessage(player, C.REMOVED_GRANTED_PLOT, "1", "" + (grants - 1));
|
||||
}
|
||||
if (plot.canClaim(player)) {
|
||||
plot.owner = player.getUUID();
|
||||
final String finalSchematic = schematic;
|
||||
DBFunc.createPlotSafe(plot, () -> TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override public void run(Object value) {
|
||||
plot.claim(player, true, finalSchematic, false);
|
||||
if (area.AUTO_MERGE) {
|
||||
plot.autoMerge(-1, Integer.MAX_VALUE, player.getUUID(), true);
|
||||
}
|
||||
}
|
||||
}), () -> sendMessage(player, C.PLOT_NOT_CLAIMED));
|
||||
return true;
|
||||
} else {
|
||||
sendMessage(player, C.PLOT_NOT_CLAIMED);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.FlagManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
|
||||
|
||||
@CommandDeclaration(command = "clear", description = "Clear the plot you stand on",
|
||||
permission = "plots.clear", category = CommandCategory.APPEARANCE, usage = "/plot clear",
|
||||
aliases = "reset", confirmation = true) public class Clear extends Command {
|
||||
|
||||
// Note: To clear a specific plot use /plot <plot> clear
|
||||
// The syntax also works with any command: /plot <plot> <command>
|
||||
|
||||
public Clear() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(final PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
|
||||
checkTrue(args.length == 0, C.COMMAND_SYNTAX, getUsage());
|
||||
final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
|
||||
checkTrue(plot.isOwner(player.getUUID()) || Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_CLEAR), C.NO_PLOT_PERMS);
|
||||
checkTrue(plot.getRunning() == 0, C.WAIT_FOR_TIMER);
|
||||
checkTrue(!Settings.Done.RESTRICT_BUILDING || !Flags.DONE.isSet(plot) || Permissions
|
||||
.hasPermission(player, C.PERMISSION_CONTINUE), C.DONE_ALREADY_DONE);
|
||||
confirm.run(this, new Runnable() {
|
||||
@Override public void run() {
|
||||
final long start = System.currentTimeMillis();
|
||||
boolean result = plot.clear(true, false, new Runnable() {
|
||||
@Override public void run() {
|
||||
plot.unlink();
|
||||
GlobalBlockQueue.IMP.addTask(new Runnable() {
|
||||
@Override public void run() {
|
||||
plot.removeRunning();
|
||||
// If the state changes, then mark it as no longer done
|
||||
if (plot.getFlag(Flags.DONE).isPresent()) {
|
||||
FlagManager.removePlotFlag(plot, Flags.DONE);
|
||||
}
|
||||
if (plot.getFlag(Flags.ANALYSIS).isPresent()) {
|
||||
FlagManager.removePlotFlag(plot, Flags.ANALYSIS);
|
||||
}
|
||||
MainUtil.sendMessage(player, C.CLEARING_DONE,
|
||||
"" + (System.currentTimeMillis() - start));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
} else {
|
||||
plot.addRunning();
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,612 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "cluster", aliases = "clusters",
|
||||
category = CommandCategory.ADMINISTRATION, requiredType = RequiredType.NONE,
|
||||
permission = "plots.cluster", description = "Manage a plot cluster") public class Cluster
|
||||
extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
|
||||
// list, create, delete, resize, invite, kick, leave, helpers, tp, sethome
|
||||
if (args.length == 0) {
|
||||
// return arguments
|
||||
MainUtil.sendMessage(player, C.CLUSTER_AVAILABLE_ARGS);
|
||||
return false;
|
||||
}
|
||||
String sub = args[0].toLowerCase();
|
||||
switch (sub) {
|
||||
case "l":
|
||||
case "list": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_LIST)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_LIST);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster list");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
Set<PlotCluster> clusters = area.getClusters();
|
||||
MainUtil.sendMessage(player, C.CLUSTER_LIST_HEADING, clusters.size() + "");
|
||||
for (PlotCluster cluster : clusters) {
|
||||
// Ignore unmanaged clusters
|
||||
String name = "'" + cluster.getName() + "' : " + cluster.toString();
|
||||
if (player.getUUID().equals(cluster.owner)) {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_LIST_ELEMENT, "&a" + name);
|
||||
} else if (cluster.helpers.contains(player.getUUID())) {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_LIST_ELEMENT, "&3" + name);
|
||||
} else if (cluster.invited.contains(player.getUUID())) {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_LIST_ELEMENT, "&9" + name);
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_LIST_ELEMENT, cluster.toString());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "c":
|
||||
case "create": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_CREATE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_CREATE);
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 4) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot cluster create <name> <id-bot> <id-top>");
|
||||
return false;
|
||||
}
|
||||
int currentClusters = Settings.Limit.GLOBAL ?
|
||||
player.getClusterCount() :
|
||||
player.getPlotCount(player.getLocation().getWorld());
|
||||
if (currentClusters >= player.getAllowedPlots()) {
|
||||
return sendMessage(player, C.CANT_CLAIM_MORE_CLUSTERS);
|
||||
}
|
||||
// check pos1 / pos2
|
||||
PlotId pos1 = PlotId.fromString(args[2]);
|
||||
PlotId pos2 = PlotId.fromString(args[3]);
|
||||
if (pos1 == null || pos2 == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_ID);
|
||||
return false;
|
||||
}
|
||||
// check if name is taken
|
||||
String name = args[1];
|
||||
if (area.getCluster(name) != null) {
|
||||
MainUtil.sendMessage(player, C.ALIAS_IS_TAKEN);
|
||||
return false;
|
||||
}
|
||||
if (pos2.x < pos1.x || pos2.y < pos1.y) {
|
||||
PlotId tmp = new PlotId(Math.min(pos1.x, pos2.x), Math.min(pos1.y, pos2.y));
|
||||
pos2 = new PlotId(Math.max(pos1.x, pos2.x), Math.max(pos1.y, pos2.y));
|
||||
pos1 = tmp;
|
||||
}
|
||||
//check if overlap
|
||||
PlotCluster cluster = area.getFirstIntersectingCluster(pos1, pos2);
|
||||
if (cluster != null) {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_INTERSECTION, cluster.getName());
|
||||
return false;
|
||||
}
|
||||
// Check if it occupies existing plots
|
||||
if (!area.contains(pos1) || !area.contains(pos2)) {
|
||||
C.CLUSTER_OUTSIDE.send(player, area);
|
||||
return false;
|
||||
}
|
||||
Set<Plot> plots = area.getPlotSelectionOwned(pos1, pos2);
|
||||
if (!plots.isEmpty()) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_CREATE_OTHER)) {
|
||||
UUID uuid = player.getUUID();
|
||||
for (Plot plot : plots) {
|
||||
if (!plot.isOwner(uuid)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_CREATE_OTHER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check allowed cluster size
|
||||
cluster = new PlotCluster(area, pos1, pos2, player.getUUID());
|
||||
int current;
|
||||
if (Settings.Limit.GLOBAL) {
|
||||
current = player.getPlayerClusterCount();
|
||||
} else {
|
||||
current = player.getPlayerClusterCount(player.getLocation().getWorld());
|
||||
}
|
||||
int allowed = Permissions.hasPermissionRange(player, C.PERMISSION_CLUSTER_SIZE,
|
||||
Settings.Limit.MAX_PLOTS);
|
||||
if (current + cluster.getArea() > allowed) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_SIZE + "." + (current + cluster.getArea()));
|
||||
return false;
|
||||
}
|
||||
// create cluster
|
||||
cluster.settings.setAlias(name);
|
||||
area.addCluster(cluster);
|
||||
DBFunc.createCluster(cluster);
|
||||
// Add any existing plots to the current cluster
|
||||
for (Plot plot : plots) {
|
||||
if (plot.hasOwner()) {
|
||||
if (!cluster.isAdded(plot.owner)) {
|
||||
cluster.invited.add(plot.owner);
|
||||
DBFunc.setInvited(cluster, plot.owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player, C.CLUSTER_ADDED);
|
||||
return true;
|
||||
}
|
||||
case "disband":
|
||||
case "del":
|
||||
case "delete": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_DELETE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_DELETE);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 1 && args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster delete [name]");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster;
|
||||
if (args.length == 2) {
|
||||
cluster = area.getCluster(args[1]);
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.INVALID_CLUSTER, args[1]);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!cluster.owner.equals(player.getUUID())) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_DELETE_OTHER)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_DELETE_OTHER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DBFunc.delete(cluster);
|
||||
MainUtil.sendMessage(player, C.CLUSTER_DELETED);
|
||||
return true;
|
||||
}
|
||||
case "res":
|
||||
case "resize": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_RESIZE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_RESIZE);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 3) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot cluster resize <pos1> <pos2>");
|
||||
return false;
|
||||
}
|
||||
// check pos1 / pos2
|
||||
PlotId pos1 = PlotId.fromString(args[1]);
|
||||
PlotId pos2 = PlotId.fromString(args[2]);
|
||||
if (pos1 == null || pos2 == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_ID);
|
||||
return false;
|
||||
}
|
||||
if (pos2.x < pos1.x || pos2.y < pos1.y) {
|
||||
pos1 = new PlotId(Math.min(pos1.x, pos2.x), Math.min(pos1.y, pos2.y));
|
||||
pos2 = new PlotId(Math.max(pos1.x, pos2.x), Math.max(pos1.y, pos2.y));
|
||||
}
|
||||
// check if in cluster
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
if (!cluster.hasHelperRights(player.getUUID())) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_RESIZE_OTHER)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_RESIZE_OTHER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//check if overlap
|
||||
PlotCluster intersect = area.getFirstIntersectingCluster(pos1, pos2);
|
||||
if (intersect != null) {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_INTERSECTION, intersect.getName());
|
||||
return false;
|
||||
}
|
||||
Set<Plot> existing = area.getPlotSelectionOwned(cluster.getP1(), cluster.getP2());
|
||||
Set<Plot> newPlots = area.getPlotSelectionOwned(pos1, pos2);
|
||||
// Set<Plot> removed = (HashSet<Plot>) existing.clone();
|
||||
Set<Plot> removed = new HashSet<>(existing);
|
||||
|
||||
removed.removeAll(newPlots);
|
||||
// Check expand / shrink
|
||||
if (!removed.isEmpty()) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_RESIZE_SHRINK)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_RESIZE_SHRINK);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
newPlots.removeAll(existing);
|
||||
if (!newPlots.isEmpty()) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_RESIZE_EXPAND)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_RESIZE_EXPAND);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Check allowed cluster size
|
||||
int current;
|
||||
if (Settings.Limit.GLOBAL) {
|
||||
current = player.getPlayerClusterCount();
|
||||
} else {
|
||||
current = player.getPlayerClusterCount(player.getLocation().getWorld());
|
||||
}
|
||||
current -= cluster.getArea() + (1 + pos2.x - pos1.x) * (1 + pos2.y - pos1.y);
|
||||
int allowed = Permissions
|
||||
.hasPermissionRange(player, C.PERMISSION_CLUSTER, Settings.Limit.MAX_PLOTS);
|
||||
if (current + cluster.getArea() > allowed) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER.s() + "." + (current + cluster.getArea()));
|
||||
return false;
|
||||
}
|
||||
// resize cluster
|
||||
DBFunc.resizeCluster(cluster, pos1, pos2);
|
||||
MainUtil.sendMessage(player, C.CLUSTER_RESIZED);
|
||||
return true;
|
||||
}
|
||||
case "add":
|
||||
case "inv":
|
||||
case "invite": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_INVITE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_INVITE);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster invite <player>");
|
||||
return false;
|
||||
}
|
||||
// check if in cluster
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
if (!cluster.hasHelperRights(player.getUUID())) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_INVITE_OTHER)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_INVITE_OTHER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// check uuid
|
||||
UUID uuid = UUIDHandler.getUUID(args[1], null);
|
||||
if (uuid == null) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[2]);
|
||||
return false;
|
||||
}
|
||||
if (!cluster.isAdded(uuid)) {
|
||||
// add the user if not added
|
||||
cluster.invited.add(uuid);
|
||||
DBFunc.setInvited(cluster, uuid);
|
||||
PlotPlayer player2 = UUIDHandler.getPlayer(uuid);
|
||||
if (player2 != null) {
|
||||
MainUtil.sendMessage(player2, C.CLUSTER_INVITED, cluster.getName());
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player, C.CLUSTER_ADDED_USER);
|
||||
return true;
|
||||
}
|
||||
case "k":
|
||||
case "remove":
|
||||
case "kick": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_KICK)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_KICK);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster kick <player>");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
if (!cluster.hasHelperRights(player.getUUID())) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_KICK_OTHER)) {
|
||||
MainUtil
|
||||
.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_KICK_OTHER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// check uuid
|
||||
UUID uuid = UUIDHandler.getUUID(args[1], null);
|
||||
if (uuid == null) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[1]);
|
||||
return false;
|
||||
}
|
||||
// Can't kick if the player is yourself, the owner, or not added to the cluster
|
||||
if (uuid.equals(player.getUUID()) || uuid.equals(cluster.owner) || !cluster
|
||||
.isAdded(uuid)) {
|
||||
MainUtil.sendMessage(player, C.CANNOT_KICK_PLAYER, cluster.getName());
|
||||
return false;
|
||||
}
|
||||
if (cluster.helpers.contains(uuid)) {
|
||||
cluster.helpers.remove(uuid);
|
||||
DBFunc.removeHelper(cluster, uuid);
|
||||
}
|
||||
cluster.invited.remove(uuid);
|
||||
DBFunc.removeInvited(cluster, uuid);
|
||||
PlotPlayer player2 = UUIDHandler.getPlayer(uuid);
|
||||
if (player2 != null) {
|
||||
MainUtil.sendMessage(player2, C.CLUSTER_REMOVED, cluster.getName());
|
||||
}
|
||||
for (Plot plot : new ArrayList<>(
|
||||
PlotSquared.get().getPlots(player2.getLocation().getWorld(), uuid))) {
|
||||
PlotCluster current = plot.getCluster();
|
||||
if (current != null && current.equals(cluster)) {
|
||||
plot.unclaim();
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player2, C.CLUSTER_KICKED_USER);
|
||||
return true;
|
||||
}
|
||||
case "quit":
|
||||
case "leave": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_LEAVE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_LEAVE);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 1 && args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster leave [name]");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster;
|
||||
if (args.length == 2) {
|
||||
cluster = area.getCluster(args[1]);
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.INVALID_CLUSTER, args[1]);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
UUID uuid = player.getUUID();
|
||||
if (!cluster.isAdded(uuid)) {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_NOT_ADDED);
|
||||
return false;
|
||||
}
|
||||
if (uuid.equals(cluster.owner)) {
|
||||
MainUtil.sendMessage(player, C.CLUSTER_CANNOT_LEAVE);
|
||||
return false;
|
||||
}
|
||||
if (cluster.helpers.contains(uuid)) {
|
||||
cluster.helpers.remove(uuid);
|
||||
DBFunc.removeHelper(cluster, uuid);
|
||||
}
|
||||
cluster.invited.remove(uuid);
|
||||
DBFunc.removeInvited(cluster, uuid);
|
||||
MainUtil.sendMessage(player, C.CLUSTER_REMOVED, cluster.getName());
|
||||
for (Plot plot : new ArrayList<>(
|
||||
PlotSquared.get().getPlots(player.getLocation().getWorld(), uuid))) {
|
||||
PlotCluster current = plot.getCluster();
|
||||
if (current != null && current.equals(cluster)) {
|
||||
plot.unclaim();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "members":
|
||||
case "admin":
|
||||
case "helper":
|
||||
case "helpers": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_HELPERS)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_HELPERS);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 3) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot cluster helpers <add|remove> <player>");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
UUID uuid = UUIDHandler.getUUID(args[2], null);
|
||||
if (uuid == null) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[2]);
|
||||
return false;
|
||||
}
|
||||
if (args[1].equalsIgnoreCase("add")) {
|
||||
cluster.helpers.add(uuid);
|
||||
DBFunc.setHelper(cluster, uuid);
|
||||
return MainUtil.sendMessage(player, C.CLUSTER_ADDED_HELPER);
|
||||
}
|
||||
if (args[1].equalsIgnoreCase("remove")) {
|
||||
cluster.helpers.remove(uuid);
|
||||
DBFunc.removeHelper(cluster, uuid);
|
||||
return MainUtil.sendMessage(player, C.CLUSTER_REMOVED_HELPER);
|
||||
}
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot cluster helpers <add|remove> <player>");
|
||||
return false;
|
||||
}
|
||||
case "spawn":
|
||||
case "home":
|
||||
case "tp": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_TP)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_TP);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster tp <name>");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster = area.getCluster(args[1]);
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.INVALID_CLUSTER, args[1]);
|
||||
return false;
|
||||
}
|
||||
UUID uuid = player.getUUID();
|
||||
if (!cluster.isAdded(uuid)) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_TP_OTHER)) {
|
||||
MainUtil
|
||||
.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_TP_OTHER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
player.teleport(cluster.getHome());
|
||||
return MainUtil.sendMessage(player, C.CLUSTER_TELEPORTING);
|
||||
}
|
||||
case "i":
|
||||
case "info":
|
||||
case "show":
|
||||
case "information": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_INFO)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_INFO);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 1 && args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster info [name]");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster;
|
||||
if (args.length == 2) {
|
||||
cluster = area.getCluster(args[1]);
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.INVALID_CLUSTER, args[1]);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
String id = cluster.toString();
|
||||
String owner = UUIDHandler.getName(cluster.owner);
|
||||
if (owner == null) {
|
||||
owner = "unknown";
|
||||
}
|
||||
String name = cluster.getName();
|
||||
String size = (cluster.getP2().x - cluster.getP1().x + 1) + "x" + (
|
||||
cluster.getP2().y - cluster.getP1().y + 1);
|
||||
String rights = cluster.isAdded(player.getUUID()) + "";
|
||||
String message = C.CLUSTER_INFO.s();
|
||||
message = message.replaceAll("%id%", id);
|
||||
message = message.replaceAll("%owner%", owner);
|
||||
message = message.replaceAll("%name%", name);
|
||||
message = message.replaceAll("%size%", size);
|
||||
message = message.replaceAll("%rights%", rights);
|
||||
MainUtil.sendMessage(player, message);
|
||||
return true;
|
||||
}
|
||||
case "sh":
|
||||
case "setspawn":
|
||||
case "sethome":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_SETHOME)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_CLUSTER_SETHOME);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 1 && args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot cluster sethome");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area == null) {
|
||||
C.NOT_IN_PLOT_WORLD.send(player);
|
||||
return false;
|
||||
}
|
||||
PlotCluster cluster = area.getCluster(player.getLocation());
|
||||
if (cluster == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_CLUSTER);
|
||||
return false;
|
||||
}
|
||||
if (!cluster.hasHelperRights(player.getUUID())) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_CLUSTER_SETHOME_OTHER)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_CLUSTER_SETHOME_OTHER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Location base = cluster.getClusterBottom();
|
||||
Location relative = player.getLocation().subtract(base.getX(), 0, base.getZ());
|
||||
BlockLoc blockloc = new BlockLoc(relative.getX(), relative.getY(), relative.getZ());
|
||||
cluster.settings.setPosition(blockloc);
|
||||
DBFunc.setPosition(cluster,
|
||||
relative.getX() + "," + relative.getY() + "," + relative.getZ());
|
||||
return MainUtil.sendMessage(player, C.POSITION_SET);
|
||||
}
|
||||
MainUtil.sendMessage(player, C.CLUSTER_AVAILABLE_ARGS);
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
/**
|
||||
* CommandCategory.
|
||||
*/
|
||||
public enum CommandCategory {
|
||||
/**
|
||||
* Claiming CommandConfig.
|
||||
* Such as: /plot claim
|
||||
*/
|
||||
CLAIMING("Claiming"), /**
|
||||
* Teleportation CommandConfig.
|
||||
* Such as: /plot visit
|
||||
*/
|
||||
TELEPORT("Teleport"), /**
|
||||
* Protection.
|
||||
*/
|
||||
SETTINGS("Protection"), /**
|
||||
* Chat.
|
||||
*/
|
||||
CHAT("Chat"), /**
|
||||
* Web.
|
||||
*/
|
||||
SCHEMATIC("Web"), /**
|
||||
* Cosmetic.
|
||||
*/
|
||||
APPEARANCE("Cosmetic"), /**
|
||||
* Information CommandConfig.
|
||||
* Such as: /plot info
|
||||
*/
|
||||
INFO("Info"), /**
|
||||
* Debug CommandConfig.
|
||||
* Such as: /plot debug
|
||||
*/
|
||||
DEBUG("Debug"), /**
|
||||
* Administration commands.
|
||||
*/
|
||||
ADMINISTRATION("Admin");
|
||||
/**
|
||||
* The category name (Readable).
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name readable name
|
||||
*/
|
||||
CommandCategory(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.comment.CommentInbox;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.comment.PlotComment;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.CommentManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@CommandDeclaration(command = "comment", aliases = {"msg"}, description = "Comment on a plot",
|
||||
category = CommandCategory.CHAT, requiredType = RequiredType.NONE, permission = "plots.comment")
|
||||
public class Comment extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
if (args.length < 2) {
|
||||
sendMessage(player, C.COMMENT_SYNTAX,
|
||||
StringMan.join(CommentManager.inboxes.keySet(), "|"));
|
||||
return false;
|
||||
}
|
||||
CommentInbox inbox = CommentManager.inboxes.get(args[0].toLowerCase());
|
||||
if (inbox == null) {
|
||||
sendMessage(player, C.COMMENT_SYNTAX,
|
||||
StringMan.join(CommentManager.inboxes.keySet(), "|"));
|
||||
return false;
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
PlotId id = PlotId.fromString(args[1]);
|
||||
Plot plot = MainUtil.getPlotFromString(player, args[1], false);
|
||||
int index;
|
||||
if (plot == null) {
|
||||
index = 1;
|
||||
plot = loc.getPlotAbs();
|
||||
} else {
|
||||
if (args.length < 4) {
|
||||
sendMessage(player, C.COMMENT_SYNTAX,
|
||||
StringMan.join(CommentManager.inboxes.keySet(), "|"));
|
||||
return false;
|
||||
}
|
||||
index = 2;
|
||||
}
|
||||
if (!inbox.canWrite(plot, player)) {
|
||||
sendMessage(player, C.NO_PERM_INBOX, "");
|
||||
return false;
|
||||
}
|
||||
String message = StringMan.join(Arrays.copyOfRange(args, index, args.length), " ");
|
||||
PlotComment comment =
|
||||
new PlotComment(loc.getWorld(), id, message, player.getName(), inbox.toString(),
|
||||
System.currentTimeMillis());
|
||||
boolean result = inbox.addComment(plot, comment);
|
||||
if (!result) {
|
||||
sendMessage(player, C.NO_PLOT_INBOX, "");
|
||||
sendMessage(player, C.COMMENT_SYNTAX,
|
||||
StringMan.join(CommentManager.inboxes.keySet(), "|"));
|
||||
return false;
|
||||
}
|
||||
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
|
||||
PlotPlayer pp = entry.getValue();
|
||||
if (pp.getAttribute("chatspy")) {
|
||||
MainUtil.sendMessage(pp, "/plot comment " + StringMan.join(args, " "));
|
||||
}
|
||||
}
|
||||
sendMessage(player, C.COMMENT_ADDED);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MathMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@CommandDeclaration(command = "condense", permission = "plots.admin",
|
||||
description = "Condense a plotworld", category = CommandCategory.ADMINISTRATION,
|
||||
requiredType = RequiredType.CONSOLE) public class Condense extends SubCommand {
|
||||
|
||||
public static boolean TASK = false;
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
if (args.length != 2 && args.length != 3) {
|
||||
MainUtil.sendMessage(player, "/plot condense <area> <start|stop|info> [radius]");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]);
|
||||
if (area == null || !WorldUtil.IMP.isWorld(area.worldname)) {
|
||||
MainUtil.sendMessage(player, "INVALID AREA");
|
||||
return false;
|
||||
}
|
||||
switch (args[1].toLowerCase()) {
|
||||
case "start": {
|
||||
if (args.length == 2) {
|
||||
MainUtil.sendMessage(player,
|
||||
"/plot condense " + area.toString() + " start <radius>");
|
||||
return false;
|
||||
}
|
||||
if (Condense.TASK) {
|
||||
MainUtil.sendMessage(player, "TASK ALREADY STARTED");
|
||||
return false;
|
||||
}
|
||||
if (!MathMan.isInteger(args[2])) {
|
||||
MainUtil.sendMessage(player, "INVALID RADIUS");
|
||||
return false;
|
||||
}
|
||||
int radius = Integer.parseInt(args[2]);
|
||||
ArrayList<Plot> plots = new ArrayList<>(PlotSquared.get().getPlots(area));
|
||||
// remove non base plots
|
||||
Iterator<Plot> iterator = plots.iterator();
|
||||
int maxSize = 0;
|
||||
ArrayList<Integer> sizes = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
Plot plot = iterator.next();
|
||||
if (!plot.isBasePlot()) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
int size = plot.getConnectedPlots().size();
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
sizes.add(size - 1);
|
||||
}
|
||||
// Sort plots by size (buckets?)]
|
||||
//noinspection unchecked
|
||||
ArrayList<Plot>[] buckets = new ArrayList[maxSize];
|
||||
for (int i = 0; i < plots.size(); i++) {
|
||||
Plot plot = plots.get(i);
|
||||
int size = sizes.get(i);
|
||||
ArrayList<Plot> array = buckets[size];
|
||||
if (array == null) {
|
||||
array = new ArrayList<>();
|
||||
buckets[size] = array;
|
||||
}
|
||||
array.add(plot);
|
||||
}
|
||||
final ArrayList<Plot> allPlots = new ArrayList<>(plots.size());
|
||||
for (int i = buckets.length - 1; i >= 0; i--) {
|
||||
ArrayList<Plot> array = buckets[i];
|
||||
if (array != null) {
|
||||
allPlots.addAll(array);
|
||||
}
|
||||
}
|
||||
int size = allPlots.size();
|
||||
int minimumRadius = (int) Math.ceil(Math.sqrt(size) / 2 + 1);
|
||||
if (radius < minimumRadius) {
|
||||
MainUtil.sendMessage(player, "RADIUS TOO SMALL");
|
||||
return false;
|
||||
}
|
||||
List<PlotId> toMove = new ArrayList<>(getPlots(allPlots, radius));
|
||||
final List<PlotId> free = new ArrayList<>();
|
||||
PlotId start = new PlotId(0, 0);
|
||||
while (start.x <= minimumRadius && start.y <= minimumRadius) {
|
||||
Plot plot = area.getPlotAbs(start);
|
||||
if (plot != null && !plot.hasOwner()) {
|
||||
free.add(plot.getId());
|
||||
}
|
||||
start = Auto.getNextPlotId(start, 1);
|
||||
}
|
||||
if (free.isEmpty() || toMove.isEmpty()) {
|
||||
MainUtil.sendMessage(player, "NO FREE PLOTS FOUND");
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, "TASK STARTED...");
|
||||
Runnable run = new Runnable() {
|
||||
@Override public void run() {
|
||||
if (!Condense.TASK) {
|
||||
MainUtil.sendMessage(player, "TASK CANCELLED.");
|
||||
}
|
||||
if (allPlots.isEmpty()) {
|
||||
Condense.TASK = false;
|
||||
MainUtil.sendMessage(player,
|
||||
"TASK COMPLETE. PLEASE VERIFY THAT NO NEW PLOTS HAVE BEEN CLAIMED DURING TASK.");
|
||||
return;
|
||||
}
|
||||
final Runnable task = this;
|
||||
final Plot origin = allPlots.remove(0);
|
||||
int i = 0;
|
||||
while (free.size() > i) {
|
||||
final Plot possible = origin.getArea().getPlotAbs(free.get(i));
|
||||
if (possible.hasOwner()) {
|
||||
free.remove(i);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
final AtomicBoolean result = new AtomicBoolean(false);
|
||||
result.set(origin.move(possible, () -> {
|
||||
if (result.get()) {
|
||||
MainUtil.sendMessage(player,
|
||||
"Moving: " + origin + " -> " + possible);
|
||||
TaskManager.runTaskLater(task, 1);
|
||||
}
|
||||
}, false));
|
||||
if (result.get()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (free.isEmpty()) {
|
||||
Condense.TASK = false;
|
||||
MainUtil.sendMessage(player, "TASK FAILED. NO FREE PLOTS FOUND!");
|
||||
return;
|
||||
}
|
||||
if (i >= free.size()) {
|
||||
MainUtil.sendMessage(player, "SKIPPING COMPLEX PLOT: " + origin);
|
||||
}
|
||||
}
|
||||
};
|
||||
Condense.TASK = true;
|
||||
TaskManager.runTaskAsync(run);
|
||||
return true;
|
||||
}
|
||||
case "stop":
|
||||
if (!Condense.TASK) {
|
||||
MainUtil.sendMessage(player, "TASK ALREADY STOPPED");
|
||||
return false;
|
||||
}
|
||||
Condense.TASK = false;
|
||||
MainUtil.sendMessage(player, "TASK STOPPED");
|
||||
return true;
|
||||
case "info":
|
||||
if (args.length == 2) {
|
||||
MainUtil.sendMessage(player,
|
||||
"/plot condense " + area.toString() + " info <radius>");
|
||||
return false;
|
||||
}
|
||||
if (!MathMan.isInteger(args[2])) {
|
||||
MainUtil.sendMessage(player, "INVALID RADIUS");
|
||||
return false;
|
||||
}
|
||||
int radius = Integer.parseInt(args[2]);
|
||||
Collection<Plot> plots = area.getPlots();
|
||||
int size = plots.size();
|
||||
int minimumRadius = (int) Math.ceil(Math.sqrt(size) / 2 + 1);
|
||||
if (radius < minimumRadius) {
|
||||
MainUtil.sendMessage(player, "RADIUS TOO SMALL");
|
||||
return false;
|
||||
}
|
||||
int maxMove = getPlots(plots, minimumRadius).size();
|
||||
int userMove = getPlots(plots, radius).size();
|
||||
MainUtil.sendMessage(player, "=== DEFAULT EVAL ===");
|
||||
MainUtil.sendMessage(player, "MINIMUM RADIUS: " + minimumRadius);
|
||||
MainUtil.sendMessage(player, "MAXIMUM MOVES: " + maxMove);
|
||||
MainUtil.sendMessage(player, "=== INPUT EVAL ===");
|
||||
MainUtil.sendMessage(player, "INPUT RADIUS: " + radius);
|
||||
MainUtil.sendMessage(player, "ESTIMATED MOVES: " + userMove);
|
||||
MainUtil.sendMessage(player,
|
||||
"ESTIMATED TIME: No idea, times will drastically change based on the system performance and load");
|
||||
MainUtil.sendMessage(player, "&e - Radius is measured in plot width");
|
||||
return true;
|
||||
}
|
||||
MainUtil.sendMessage(player,
|
||||
"/plot condense " + area.worldname + " <start|stop|info> [radius]");
|
||||
return false;
|
||||
}
|
||||
|
||||
public Set<PlotId> getPlots(Collection<Plot> plots, int radius) {
|
||||
HashSet<PlotId> outside = new HashSet<>();
|
||||
for (Plot plot : plots) {
|
||||
if (plot.getId().x > radius || plot.getId().x < -radius || plot.getId().y > radius
|
||||
|| plot.getId().y < -radius) {
|
||||
outside.add(plot.getId());
|
||||
}
|
||||
}
|
||||
return outside;
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.CmdInstance;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.CmdConfirm;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
|
||||
@CommandDeclaration(command = "confirm", permission = "plots.use",
|
||||
description = "Confirm an action", category = CommandCategory.INFO) public class Confirm
|
||||
extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
CmdInstance command = CmdConfirm.getPending(player);
|
||||
if (command == null) {
|
||||
MainUtil.sendMessage(player, C.FAILED_CONFIRM);
|
||||
return false;
|
||||
}
|
||||
CmdConfirm.removePending(player);
|
||||
if ((System.currentTimeMillis() - command.timestamp)
|
||||
> Settings.Confirmation.CONFIRMATION_TIMEOUT_SECONDS * 1000) {
|
||||
MainUtil.sendMessage(player, C.EXPIRED_CONFIRM);
|
||||
return false;
|
||||
}
|
||||
TaskManager.runTask(command.command);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
|
||||
@CommandDeclaration(command = "continue",
|
||||
description = "Continue a plot that was previously marked as done",
|
||||
permission = "plots.continue", category = CommandCategory.SETTINGS,
|
||||
requiredType = RequiredType.NONE) public class Continue extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
Plot plot = player.getCurrentPlot();
|
||||
if ((plot == null) || !plot.hasOwner()) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_CONTINUE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (!plot.hasFlag(Flags.DONE)) {
|
||||
MainUtil.sendMessage(player, C.DONE_NOT_DONE);
|
||||
return false;
|
||||
}
|
||||
int size = plot.getConnectedPlots().size();
|
||||
if (Settings.Done.COUNTS_TOWARDS_LIMIT && (player.getAllowedPlots()
|
||||
< player.getPlotCount() + size)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_ADMIN_COMMAND_CONTINUE);
|
||||
return false;
|
||||
}
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
plot.removeFlag(Flags.DONE);
|
||||
MainUtil.sendMessage(player, C.DONE_REMOVED);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
|
||||
@CommandDeclaration(command = "copy", permission = "plots.copy", aliases = {"copypaste"},
|
||||
category = CommandCategory.CLAIMING, description = "Copy a plot", usage = "/plot copy <X;Z>",
|
||||
requiredType = RequiredType.NONE) public class Copy extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
Plot plot1 = loc.getPlotAbs();
|
||||
if (plot1 == null) {
|
||||
return !MainUtil.sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot1.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN.s())) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
Plot plot2 = MainUtil.getPlotFromString(player, args[0], true);
|
||||
if (plot2 == null) {
|
||||
return false;
|
||||
}
|
||||
if (plot1.equals(plot2)) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_ID);
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
if (!plot1.getArea().isCompatible(plot2.getArea())) {
|
||||
C.PLOTWORLD_INCOMPATIBLE.send(player);
|
||||
return false;
|
||||
}
|
||||
if (plot1.copy(plot2, new Runnable() {
|
||||
@Override public void run() {
|
||||
MainUtil.sendMessage(player, C.COPY_SUCCESS);
|
||||
}
|
||||
})) {
|
||||
return true;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.REQUIRES_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridPlotWorld;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
@CommandDeclaration(command = "createroadschematic", aliases = {"crs"},
|
||||
category = CommandCategory.ADMINISTRATION, requiredType = RequiredType.NONE,
|
||||
permission = "plots.createroadschematic",
|
||||
description = "Add a road schematic to your world using the roads around your current plot",
|
||||
usage = "/plot createroadschematic") public class CreateRoadSchematic extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!(loc.getPlotArea() instanceof HybridPlotWorld)) {
|
||||
return sendMessage(player, C.NOT_IN_PLOT_WORLD);
|
||||
}
|
||||
HybridUtils.manager.setupRoadSchematic(plot);
|
||||
MainUtil.sendMessage(player,
|
||||
"$1Saved new road schematic. To test the road, fly to a few other plots and use /plot debugroadregen");
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.MySQL;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.SQLManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.SQLite;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@CommandDeclaration(command = "database", aliases = {"convert"},
|
||||
category = CommandCategory.ADMINISTRATION, permission = "plots.database",
|
||||
description = "Convert/Backup Storage", requiredType = RequiredType.CONSOLE,
|
||||
usage = "/plot database [area] <sqlite|mysql|import>") public class Database
|
||||
extends SubCommand {
|
||||
|
||||
public static void insertPlots(final SQLManager manager, final List<Plot> plots,
|
||||
final PlotPlayer player) {
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
try {
|
||||
ArrayList<Plot> ps = new ArrayList<>(plots);
|
||||
MainUtil.sendMessage(player, "&6Starting...");
|
||||
manager.createPlotsAndData(ps, () -> {
|
||||
MainUtil.sendMessage(player, "&6Database conversion finished!");
|
||||
manager.close();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
MainUtil
|
||||
.sendMessage(player, "Failed to insert plot objects, see stacktrace for info");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
if (args.length < 1) {
|
||||
MainUtil.sendMessage(player, "/plot database [area] <sqlite|mysql|import>");
|
||||
return false;
|
||||
}
|
||||
List<Plot> plots;
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]);
|
||||
if (area != null) {
|
||||
plots = PlotSquared.get().sortPlotsByTemp(area.getPlots());
|
||||
args = Arrays.copyOfRange(args, 1, args.length);
|
||||
} else {
|
||||
plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getPlots());
|
||||
}
|
||||
if (args.length < 1) {
|
||||
MainUtil.sendMessage(player, "/plot database [world] <sqlite|mysql|import>");
|
||||
MainUtil.sendMessage(player, "[arg] indicates an optional argument");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
com.github.intellectualsites.plotsquared.plot.database.Database implementation;
|
||||
String prefix = "";
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "import":
|
||||
if (args.length < 2) {
|
||||
MainUtil
|
||||
.sendMessage(player, "/plot database import <sqlite file> [prefix]");
|
||||
return false;
|
||||
}
|
||||
File file = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(),
|
||||
args[1].endsWith(".db") ? args[1] : args[1] + ".db");
|
||||
if (!file.exists()) {
|
||||
MainUtil.sendMessage(player, "&6Database does not exist: " + file);
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, "&6Starting...");
|
||||
implementation = new SQLite(file);
|
||||
SQLManager manager =
|
||||
new SQLManager(implementation, args.length == 3 ? args[2] : "", true);
|
||||
HashMap<String, HashMap<PlotId, Plot>> map = manager.getPlots();
|
||||
plots = new ArrayList<>();
|
||||
for (Entry<String, HashMap<PlotId, Plot>> entry : map.entrySet()) {
|
||||
String areaname = entry.getKey();
|
||||
PlotArea pa = PlotSquared.get().getPlotAreaByString(areaname);
|
||||
if (pa != null) {
|
||||
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
|
||||
Plot plot = entry2.getValue();
|
||||
if (pa.getOwnedPlotAbs(plot.getId()) != null) {
|
||||
if (pa instanceof SinglePlotArea) {
|
||||
Plot newPlot = pa.getNextFreePlot(null, plot.getId());
|
||||
if (newPlot != null) {
|
||||
PlotId newId = newPlot.getId();
|
||||
PlotId id = plot.getId();
|
||||
File worldFile =
|
||||
new File(PlotSquared.imp().getWorldContainer(),
|
||||
id.toCommaSeparatedString());
|
||||
if (worldFile.exists()) {
|
||||
File newFile =
|
||||
new File(PlotSquared.imp().getWorldContainer(),
|
||||
newId.toCommaSeparatedString());
|
||||
worldFile.renameTo(newFile);
|
||||
}
|
||||
id.x = newId.x;
|
||||
id.y = newId.y;
|
||||
id.recalculateHash();
|
||||
plot.setArea(pa);
|
||||
plots.add(plot);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player,
|
||||
"Skipping duplicate plot: " + plot + " | id=" + plot.temp);
|
||||
continue;
|
||||
}
|
||||
plot.setArea(pa);
|
||||
plots.add(plot);
|
||||
}
|
||||
} else {
|
||||
HashMap<PlotId, Plot> plotmap = PlotSquared.get().plots_tmp
|
||||
.computeIfAbsent(areaname, k -> new HashMap<>());
|
||||
plotmap.putAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
DBFunc.createPlotsAndData(plots,
|
||||
() -> MainUtil.sendMessage(player, "&6Database conversion finished!"));
|
||||
return true;
|
||||
case "mysql":
|
||||
if (args.length < 6) {
|
||||
return MainUtil.sendMessage(player,
|
||||
"/plot database mysql [host] [port] [username] [password] [database] {prefix}");
|
||||
}
|
||||
String host = args[1];
|
||||
String port = args[2];
|
||||
String username = args[3];
|
||||
String password = args[4];
|
||||
String database = args[5];
|
||||
if (args.length > 6) {
|
||||
prefix = args[6];
|
||||
}
|
||||
implementation = new MySQL(host, port, database, username, password);
|
||||
break;
|
||||
case "sqlite":
|
||||
if (args.length < 2) {
|
||||
return MainUtil.sendMessage(player, "/plot database sqlite [file]");
|
||||
}
|
||||
File sqliteFile =
|
||||
MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), args[1] + ".db");
|
||||
implementation = new SQLite(sqliteFile);
|
||||
break;
|
||||
default:
|
||||
return MainUtil.sendMessage(player, "/plot database [sqlite/mysql]");
|
||||
}
|
||||
try {
|
||||
SQLManager manager = new SQLManager(implementation, prefix, true);
|
||||
Database.insertPlots(manager, plots, player);
|
||||
return true;
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
MainUtil.sendMessage(player, "$1Failed to save plots, read stacktrace for info");
|
||||
MainUtil.sendMessage(player,
|
||||
"&d==== Here is an ugly stacktrace, if you are interested in those things ===");
|
||||
e.printStackTrace();
|
||||
MainUtil.sendMessage(player, "&d==== End of stacktrace ====");
|
||||
MainUtil
|
||||
.sendMessage(player, "$1Please make sure you are using the correct arguments!");
|
||||
return false;
|
||||
}
|
||||
} catch (ClassNotFoundException | SQLException e) {
|
||||
MainUtil.sendMessage(player, "$1Failed to open connection, read stacktrace for info");
|
||||
MainUtil.sendMessage(player,
|
||||
"&d==== Here is an ugly stacktrace, if you are interested in those things ===");
|
||||
e.printStackTrace();
|
||||
MainUtil.sendMessage(player, "&d==== End of stacktrace ====");
|
||||
MainUtil.sendMessage(player, "$1Please make sure you are using the correct arguments!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
|
||||
@CommandDeclaration(command = "debug", category = CommandCategory.DEBUG,
|
||||
description = "Show debug information", usage = "/plot debug [msg]", permission = "plots.admin")
|
||||
public class Debug extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
if ((args.length > 0) && args[0].equalsIgnoreCase("msg")) {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
for (C caption : C.values()) {
|
||||
msg.append(caption.s()).append("\n");
|
||||
}
|
||||
MainUtil.sendMessage(player, msg.toString());
|
||||
return true;
|
||||
}
|
||||
StringBuilder information = new StringBuilder();
|
||||
String header = C.DEBUG_HEADER.s();
|
||||
String line = C.DEBUG_LINE.s();
|
||||
String section = C.DEBUG_SECTION.s();
|
||||
information.append(header);
|
||||
information.append(getSection(section, "PlotArea"));
|
||||
information.append(
|
||||
getLine(line, "Plot Worlds", StringMan.join(PlotSquared.get().getPlotAreas(), ", ")));
|
||||
information.append(getLine(line, "Owned Plots", PlotSquared.get().getPlots().size()));
|
||||
information.append(getSection(section, "Messages"));
|
||||
information.append(getLine(line, "Total Messages", C.values().length));
|
||||
information.append(getLine(line, "View all captions", "/plot debug msg"));
|
||||
MainUtil.sendMessage(player, information.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getSection(String line, String val) {
|
||||
return line.replaceAll("%val%", val) + "\n";
|
||||
}
|
||||
|
||||
private String getLine(String line, String var, Object val) {
|
||||
return line.replaceAll("%var%", var).replaceAll("%val%", "" + val) + "\n";
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "debugallowunsafe",
|
||||
description = "Allow unsafe actions until toggled off", usage = "/plot debugallowunsafe",
|
||||
category = CommandCategory.DEBUG, requiredType = RequiredType.NONE,
|
||||
permission = "plots.debugallowunsafe") public class DebugAllowUnsafe extends SubCommand {
|
||||
|
||||
public static final List<UUID> unsafeAllowed = new ArrayList<>();
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
|
||||
if (unsafeAllowed.contains(player.getUUID())) {
|
||||
unsafeAllowed.remove(player.getUUID());
|
||||
sendMessage(player, C.DEBUGALLOWUNSAFE_OFF);
|
||||
} else {
|
||||
unsafeAllowed.add(player.getUUID());
|
||||
sendMessage(player, C.DEBUGALLOWUNSAFE_ON);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
|
||||
import com.google.common.collect.BiMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "debugclaimtest", description =
|
||||
"If you accidentally delete your database, this command will attempt to restore all plots based on the data from plot signs. "
|
||||
+ "Execution time may vary", category = CommandCategory.DEBUG,
|
||||
requiredType = RequiredType.CONSOLE, permission = "plots.debugclaimtest")
|
||||
public class DebugClaimTest extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
if (args.length < 3) {
|
||||
return !MainUtil.sendMessage(null,
|
||||
"If you accidentally delete your database, this command will attempt to restore all plots based on the data from the "
|
||||
+ "plot signs. \n\n&cMissing world arg /plot debugclaimtest {world} {PlotId min} {PlotId max}");
|
||||
}
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]);
|
||||
if (area == null || !WorldUtil.IMP.isWorld(area.worldname)) {
|
||||
C.NOT_VALID_PLOT_WORLD.send(player, args[0]);
|
||||
return false;
|
||||
}
|
||||
PlotId min, max;
|
||||
try {
|
||||
args[1].split(";");
|
||||
args[2].split(";");
|
||||
min = PlotId.fromString(args[1]);
|
||||
max = PlotId.fromString(args[2]);
|
||||
} catch (Exception ignored) {
|
||||
return !MainUtil.sendMessage(player,
|
||||
"&cInvalid min/max values. &7The values are to Plot IDs in the format &cX;Y &7where X;Y are the plot coords\nThe conversion "
|
||||
+ "will only check the plots in the selected area.");
|
||||
}
|
||||
MainUtil.sendMessage(player,
|
||||
"&3Sign Block&8->&3Plot&8: &7Beginning sign to plot conversion. This may take a while...");
|
||||
MainUtil.sendMessage(player,
|
||||
"&3Sign Block&8->&3Plot&8: Found an excess of 250,000 chunks. Limiting search radius... (~3.8 min)");
|
||||
PlotManager manager = area.getPlotManager();
|
||||
ArrayList<Plot> plots = new ArrayList<>();
|
||||
for (PlotId id : MainUtil.getPlotSelectionIds(min, max)) {
|
||||
Plot plot = area.getPlotAbs(id);
|
||||
if (plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, " - &cDB Already contains: " + plot.getId());
|
||||
continue;
|
||||
}
|
||||
Location loc = manager.getSignLoc(area, plot);
|
||||
ChunkLoc chunk = new ChunkLoc(loc.getX() >> 4, loc.getZ() >> 4);
|
||||
boolean result = ChunkManager.manager.loadChunk(area.worldname, chunk, false);
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
String[] lines = WorldUtil.IMP.getSign(loc);
|
||||
if (lines != null) {
|
||||
String line = lines[2];
|
||||
if (line != null && line.length() > 2) {
|
||||
line = line.substring(2);
|
||||
BiMap<StringWrapper, UUID> map = UUIDHandler.getUuidMap();
|
||||
UUID uuid = map.get(new StringWrapper(line));
|
||||
if (uuid == null) {
|
||||
for (Map.Entry<StringWrapper, UUID> stringWrapperUUIDEntry : map
|
||||
.entrySet()) {
|
||||
if (stringWrapperUUIDEntry.getKey().value.toLowerCase()
|
||||
.startsWith(line.toLowerCase())) {
|
||||
uuid = stringWrapperUUIDEntry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uuid == null) {
|
||||
uuid = UUIDHandler.getUUID(line, null);
|
||||
}
|
||||
if (uuid != null) {
|
||||
MainUtil
|
||||
.sendMessage(player, " - &aFound plot: " + plot.getId() + " : " + line);
|
||||
plot.setOwner(uuid);
|
||||
plots.add(plot);
|
||||
} else {
|
||||
MainUtil.sendMessage(player,
|
||||
" - &cInvalid PlayerName: " + plot.getId() + " : " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!plots.isEmpty()) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&3Sign Block&8->&3Plot&8: &7Updating '" + plots.size() + "' plots!");
|
||||
DBFunc.createPlotsAndData(plots, new Runnable() {
|
||||
@Override public void run() {
|
||||
MainUtil.sendMessage(player, "&6Database update finished!");
|
||||
}
|
||||
});
|
||||
for (Plot plot : plots) {
|
||||
plot.create();
|
||||
}
|
||||
MainUtil.sendMessage(player, "&3Sign Block&8->&3Plot&8: &7Complete!");
|
||||
} else {
|
||||
MainUtil.sendMessage(player, "No plots were found for the given search.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,429 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.FlagManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
|
||||
import com.github.intellectualsites.plotsquared.plot.listener.WEManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpireManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.expiry.PlotAnalysis;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import javax.script.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
|
||||
@CommandDeclaration(command = "debugexec", permission = "plots.admin",
|
||||
description = "Mutli-purpose debug command", aliases = {"exec", "$"},
|
||||
category = CommandCategory.DEBUG) public class DebugExec extends SubCommand {
|
||||
private ScriptEngine engine;
|
||||
private Bindings scope;
|
||||
|
||||
public DebugExec() {
|
||||
try {
|
||||
if (PlotSquared.get() != null) {
|
||||
File file = new File(PlotSquared.get().IMP.getDirectory(),
|
||||
Settings.Paths.SCRIPTS + File.separator + "start.js");
|
||||
if (file.exists()) {
|
||||
init();
|
||||
String script = StringMan.join(Files.readLines(new File(new File(
|
||||
PlotSquared.get().IMP.getDirectory() + File.separator
|
||||
+ Settings.Paths.SCRIPTS), "start.js"), StandardCharsets.UTF_8),
|
||||
System.getProperty("line.separator"));
|
||||
this.scope.put("THIS", this);
|
||||
this.scope.put("PlotPlayer", ConsolePlayer.getConsole());
|
||||
this.engine.eval(script, this.scope);
|
||||
}
|
||||
}
|
||||
} catch (IOException | ScriptException ignored) {
|
||||
ignored.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ScriptEngine getEngine() {
|
||||
if (this.engine == null) {
|
||||
init();
|
||||
}
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
public Bindings getScope() {
|
||||
return this.scope;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (this.engine != null) {
|
||||
return;
|
||||
}
|
||||
this.engine = new ScriptEngineManager(null).getEngineByName("nashorn");
|
||||
if (this.engine == null) {
|
||||
this.engine = new ScriptEngineManager(null).getEngineByName("JavaScript");
|
||||
}
|
||||
ScriptContext context = new SimpleScriptContext();
|
||||
this.scope = context.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
|
||||
// stuff
|
||||
this.scope.put("MainUtil", new MainUtil());
|
||||
this.scope.put("Settings", new Settings());
|
||||
this.scope.put("StringMan", new StringMan());
|
||||
this.scope.put("MathMan", new MathMan());
|
||||
this.scope.put("FlagManager", new FlagManager());
|
||||
|
||||
// Classes
|
||||
this.scope.put("Location", Location.class);
|
||||
this.scope.put("PlotBlock", PlotBlock.class);
|
||||
this.scope.put("Plot", Plot.class);
|
||||
this.scope.put("PlotId", PlotId.class);
|
||||
this.scope.put("Runnable", Runnable.class);
|
||||
this.scope.put("RunnableVal", RunnableVal.class);
|
||||
|
||||
// Instances
|
||||
this.scope.put("PS", PlotSquared.get());
|
||||
this.scope.put("GlobalBlockQueue", GlobalBlockQueue.IMP);
|
||||
this.scope.put("ExpireManager", ExpireManager.IMP);
|
||||
if (PlotSquared.get().worldedit != null) {
|
||||
this.scope.put("WEManager", new WEManager());
|
||||
}
|
||||
this.scope.put("TaskManager", TaskManager.IMP);
|
||||
this.scope.put("TitleManager", AbstractTitle.TITLE_CLASS);
|
||||
this.scope.put("ConsolePlayer", ConsolePlayer.getConsole());
|
||||
this.scope.put("SchematicHandler", SchematicHandler.manager);
|
||||
this.scope.put("ChunkManager", ChunkManager.manager);
|
||||
this.scope.put("BlockManager", WorldUtil.IMP);
|
||||
this.scope.put("SetupUtils", SetupUtils.manager);
|
||||
this.scope.put("EventUtil", EventUtil.manager);
|
||||
this.scope.put("EconHandler", EconHandler.manager);
|
||||
this.scope.put("UUIDHandler", UUIDHandler.implementation);
|
||||
this.scope.put("DBFunc", DBFunc.dbManager);
|
||||
this.scope.put("HybridUtils", HybridUtils.manager);
|
||||
this.scope.put("IMP", PlotSquared.get().IMP);
|
||||
this.scope.put("MainCommand", MainCommand.getInstance());
|
||||
|
||||
// enums
|
||||
for (Enum<?> value : C.values()) {
|
||||
this.scope.put("C_" + value.name(), value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
List<String> allowed_params = Arrays
|
||||
.asList("analyze", "calibrate-analysis", "remove-flag", "stop-expire", "start-expire",
|
||||
"seen", "list-scripts", "start-rgar", "stop-rgar", "help", "addcmd", "runasync",
|
||||
"run", "allcmd", "all");
|
||||
if (args.length > 0) {
|
||||
String arg = args[0].toLowerCase();
|
||||
String script;
|
||||
boolean async = false;
|
||||
switch (arg) {
|
||||
case "analyze": {
|
||||
Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_PLOT);
|
||||
return false;
|
||||
}
|
||||
PlotAnalysis analysis = plot.getComplexity(null);
|
||||
if (analysis != null) {
|
||||
MainUtil.sendMessage(player, "Changes/column: " + analysis.changes / 1.0);
|
||||
return true;
|
||||
}
|
||||
MainUtil.sendMessage(player, "$1Starting task...");
|
||||
HybridUtils.manager.analyzePlot(plot, new RunnableVal<PlotAnalysis>() {
|
||||
@Override public void run(PlotAnalysis value) {
|
||||
MainUtil.sendMessage(player,
|
||||
"$1Done: $2Use $3/plot debugexec analyze$2 for more information");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
case "calibrate-analysis":
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot debugexec analyze <threshold>");
|
||||
MainUtil.sendMessage(player,
|
||||
"$1<threshold> $2= $1The percentage of plots you want to clear (100 clears 100% of plots so no point calibrating "
|
||||
+ "it)");
|
||||
return false;
|
||||
}
|
||||
double threshold;
|
||||
try {
|
||||
threshold = Integer.parseInt(args[1]) / 100d;
|
||||
} catch (NumberFormatException ignored) {
|
||||
MainUtil.sendMessage(player, "$2Invalid threshold: " + args[1]);
|
||||
MainUtil.sendMessage(player,
|
||||
"$1<threshold> $2= $1The percentage of plots you want to clear as a number between 0 - 100");
|
||||
return false;
|
||||
}
|
||||
PlotAnalysis.calcOptimalModifiers(() -> MainUtil
|
||||
.sendMessage(player, "$1Thank you for calibrating plot expiry"), threshold);
|
||||
return true;
|
||||
case "stop-expire":
|
||||
if (ExpireManager.IMP == null || !ExpireManager.IMP.cancelTask()) {
|
||||
return MainUtil.sendMessage(player, "Task already halted");
|
||||
}
|
||||
return MainUtil.sendMessage(player, "Cancelled task.");
|
||||
case "remove-flag":
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot debugexec remove-flag <flag>");
|
||||
return false;
|
||||
}
|
||||
String flag = args[1];
|
||||
for (Plot plot : PlotSquared.get().getBasePlots()) {
|
||||
Flag<?> flag1 = FlagManager.getFlag(flag);
|
||||
if (plot.getFlag(flag1).isPresent()) {
|
||||
plot.removeFlag(flag1);
|
||||
}
|
||||
}
|
||||
return MainUtil.sendMessage(player, "Cleared flag: " + flag);
|
||||
case "start-rgar": {
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&cInvalid syntax: /plot debugexec start-rgar <world>");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[1]);
|
||||
if (area == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_WORLD, args[1]);
|
||||
return false;
|
||||
}
|
||||
boolean result;
|
||||
if (HybridUtils.regions != null) {
|
||||
result =
|
||||
HybridUtils.manager.scheduleRoadUpdate(area, HybridUtils.regions, 0);
|
||||
} else {
|
||||
result = HybridUtils.manager.scheduleRoadUpdate(area, 0);
|
||||
}
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&cCannot schedule mass schematic update! (Is one already in progress?)");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "stop-rgar":
|
||||
if (!HybridUtils.UPDATE) {
|
||||
MainUtil.sendMessage(player, "&cTask not running!");
|
||||
return false;
|
||||
}
|
||||
HybridUtils.UPDATE = false;
|
||||
MainUtil.sendMessage(player, "&cCancelling task... (Please wait)");
|
||||
return true;
|
||||
case "start-expire":
|
||||
if (ExpireManager.IMP == null) {
|
||||
ExpireManager.IMP = new ExpireManager();
|
||||
}
|
||||
if (ExpireManager.IMP.runAutomatedTask()) {
|
||||
return MainUtil.sendMessage(player, "Started plot expiry task");
|
||||
} else {
|
||||
return MainUtil.sendMessage(player, "Plot expiry task already started");
|
||||
}
|
||||
case "seen":
|
||||
if (args.length != 2) {
|
||||
return MainUtil.sendMessage(player, "Use /plot debugexec seen <player>");
|
||||
}
|
||||
UUID uuid = UUIDHandler.getUUID(args[1], null);
|
||||
if (uuid == null) {
|
||||
return MainUtil.sendMessage(player, "Player not found: " + args[1]);
|
||||
}
|
||||
OfflinePlotPlayer op = UUIDHandler.getUUIDWrapper().getOfflinePlayer(uuid);
|
||||
if (op == null || op.getLastPlayed() == 0) {
|
||||
return MainUtil
|
||||
.sendMessage(player, "Player hasn't connected before: " + args[1]);
|
||||
}
|
||||
Timestamp stamp = new Timestamp(op.getLastPlayed());
|
||||
Date date = new Date(stamp.getTime());
|
||||
MainUtil.sendMessage(player, "PLAYER: " + args[1]);
|
||||
MainUtil.sendMessage(player, "UUID: " + uuid);
|
||||
MainUtil.sendMessage(player, "Object: " + date.toGMTString());
|
||||
MainUtil.sendMessage(player, "GMT: " + date.toGMTString());
|
||||
MainUtil.sendMessage(player, "Local: " + date.toLocaleString());
|
||||
return true;
|
||||
case "h":
|
||||
case "he":
|
||||
case "?":
|
||||
case "help":
|
||||
MainUtil.sendMessage(player,
|
||||
"Possible sub commands: /plot debugexec <" + StringMan
|
||||
.join(allowed_params, "|") + ">");
|
||||
return false;
|
||||
case "addcmd":
|
||||
try {
|
||||
final String cmd = StringMan.join(Files.readLines(MainUtil.getFile(new File(
|
||||
PlotSquared.get().IMP.getDirectory() + File.separator
|
||||
+ Settings.Paths.SCRIPTS), args[1]), StandardCharsets.UTF_8),
|
||||
System.getProperty("line.separator"));
|
||||
new Command(MainCommand.getInstance(), true, args[1].split("\\.")[0], null,
|
||||
RequiredType.NONE, CommandCategory.DEBUG) {
|
||||
@Override public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) {
|
||||
try {
|
||||
DebugExec.this.scope.put("PlotPlayer", player);
|
||||
DebugExec.this.scope.put("args", args);
|
||||
DebugExec.this.engine.eval(cmd, DebugExec.this.scope);
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
MainUtil.sendMessage(player, C.COMMAND_WENT_WRONG);
|
||||
}
|
||||
}
|
||||
};
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
MainUtil
|
||||
.sendMessage(player, C.COMMAND_SYNTAX, "/plot debugexec addcmd <file>");
|
||||
return false;
|
||||
}
|
||||
case "runasync":
|
||||
async = true;
|
||||
case "run":
|
||||
try {
|
||||
script = StringMan.join(Files.readLines(MainUtil.getFile(new File(
|
||||
PlotSquared.get().IMP.getDirectory() + File.separator
|
||||
+ Settings.Paths.SCRIPTS), args[1]), StandardCharsets.UTF_8),
|
||||
System.getProperty("line.separator"));
|
||||
if (args.length > 2) {
|
||||
HashMap<String, String> replacements = new HashMap<>();
|
||||
for (int i = 2; i < args.length; i++) {
|
||||
replacements.put("%s" + (i - 2), args[i]);
|
||||
}
|
||||
script = StringMan.replaceFromMap(script, replacements);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case "list-scripts":
|
||||
String path = PlotSquared.get().IMP.getDirectory() + File.separator
|
||||
+ Settings.Paths.SCRIPTS;
|
||||
File folder = new File(path);
|
||||
File[] filesArray = folder.listFiles();
|
||||
|
||||
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:
|
||||
C.COMMAND_SYNTAX.send(player, "/plot debugexec list-scripts [#]");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<File> allFiles = Arrays.asList(filesArray);
|
||||
paginate(player, allFiles, 8, page,
|
||||
new RunnableVal3<Integer, File, PlotMessage>() {
|
||||
|
||||
@Override public void run(Integer i, File file, PlotMessage message) {
|
||||
String name = file.getName();
|
||||
message.text("[").color("$3").text(String.valueOf(i)).color("$1")
|
||||
.text("]").color("$3").text(' ' + name).color("$1");
|
||||
}
|
||||
}, "/plot debugexec list-scripts", "List of scripts");
|
||||
return true;
|
||||
case "allcmd":
|
||||
if (args.length < 3) {
|
||||
C.COMMAND_SYNTAX
|
||||
.send(player, "/plot debugexec allcmd <condition> <command>");
|
||||
return false;
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
Command cmd = MainCommand.getInstance().getCommand(args[3]);
|
||||
String[] params = Arrays.copyOfRange(args, 4, args.length);
|
||||
if ("true".equals(args[1])) {
|
||||
Location loc = player.getMeta(PlotPlayer.META_LOCATION);
|
||||
Plot plot = player.getMeta(PlotPlayer.META_LAST_PLOT);
|
||||
for (Plot current : PlotSquared.get().getBasePlots()) {
|
||||
player.setMeta(PlotPlayer.META_LOCATION, current.getBottomAbs());
|
||||
player.setMeta(PlotPlayer.META_LAST_PLOT, current);
|
||||
cmd.execute(player, params, null, null);
|
||||
}
|
||||
if (loc == null) {
|
||||
player.deleteMeta(PlotPlayer.META_LOCATION);
|
||||
} else {
|
||||
player.setMeta(PlotPlayer.META_LOCATION, loc);
|
||||
}
|
||||
if (plot == null) {
|
||||
player.deleteMeta(PlotPlayer.META_LAST_PLOT);
|
||||
} else {
|
||||
player.setMeta(PlotPlayer.META_LAST_PLOT, plot);
|
||||
}
|
||||
player.sendMessage("&c> " + (System.currentTimeMillis() - start));
|
||||
return true;
|
||||
}
|
||||
init();
|
||||
this.scope.put("_2", params);
|
||||
this.scope.put("_3", cmd);
|
||||
script =
|
||||
"_1=PS.getBasePlots().iterator();while(_1.hasNext()){plot=_1.next();if("
|
||||
+ args[1]
|
||||
+ "){PlotPlayer.setMeta(\"location\",plot.getBottomAbs());PlotPlayer.setMeta(\"lastplot\",plot);_3.onCommand"
|
||||
+ "(PlotPlayer,_2)}}";
|
||||
|
||||
break;
|
||||
case "all":
|
||||
if (args.length < 3) {
|
||||
C.COMMAND_SYNTAX.send(player, "/plot debugexec all <condition> <code>");
|
||||
return false;
|
||||
}
|
||||
script =
|
||||
"_1=PS.getBasePlots().iterator();while(_1.hasNext()){plot=_1.next();if("
|
||||
+ args[1] + "){" + StringMan
|
||||
.join(Arrays.copyOfRange(args, 2, args.length), " ") + "}}";
|
||||
|
||||
break;
|
||||
default:
|
||||
script = StringMan.join(args, " ");
|
||||
}
|
||||
if (!(player instanceof ConsolePlayer)) {
|
||||
MainUtil.sendMessage(player, C.NOT_CONSOLE);
|
||||
return false;
|
||||
}
|
||||
init();
|
||||
this.scope.put("PlotPlayer", player);
|
||||
PlotSquared.debug("> " + script);
|
||||
try {
|
||||
if (async) {
|
||||
final String toExec = script;
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
long start = System.currentTimeMillis();
|
||||
Object result = null;
|
||||
try {
|
||||
result = DebugExec.this.engine.eval(toExec, DebugExec.this.scope);
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
PlotSquared
|
||||
.log("> " + (System.currentTimeMillis() - start) + "ms -> " + result);
|
||||
});
|
||||
} else {
|
||||
long start = System.currentTimeMillis();
|
||||
Object result = this.engine.eval(script, this.scope);
|
||||
PlotSquared
|
||||
.log("> " + (System.currentTimeMillis() - start) + "ms -> " + result);
|
||||
}
|
||||
return true;
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Argument;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@CommandDeclaration(command = "debugfixflags", usage = "/plot debugfixflags <world>",
|
||||
permission = "plots.debugfixflags", description = "Attempt to fix all flags for a world",
|
||||
requiredType = RequiredType.CONSOLE, category = CommandCategory.DEBUG)
|
||||
public class DebugFixFlags extends SubCommand {
|
||||
|
||||
public DebugFixFlags() {
|
||||
super(Argument.String);
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]);
|
||||
if (area == null || !WorldUtil.IMP.isWorld(area.worldname)) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_WORLD, args[0]);
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, "&8--- &6Starting task &8 ---");
|
||||
for (Plot plot : area.getPlots()) {
|
||||
HashMap<Flag<?>, Object> flags = plot.getFlags();
|
||||
Iterator<Entry<Flag<?>, Object>> i = flags.entrySet().iterator();
|
||||
boolean changed = false;
|
||||
while (i.hasNext()) {
|
||||
if (i.next().getKey() == null) {
|
||||
changed = true;
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
DBFunc.setFlags(plot, plot.getFlags());
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player, "&aDone!");
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "debugimportworlds", permission = "plots.admin",
|
||||
description = "Import worlds by player name", requiredType = RequiredType.CONSOLE,
|
||||
category = CommandCategory.TELEPORT) public class DebugImportWorlds extends Command {
|
||||
public DebugImportWorlds() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
|
||||
// UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8))
|
||||
PlotAreaManager pam = PlotSquared.get().getPlotAreaManager();
|
||||
if (!(pam instanceof SinglePlotAreaManager)) {
|
||||
player.sendMessage("Must be a single plot area!");
|
||||
return;
|
||||
}
|
||||
SinglePlotArea area = ((SinglePlotAreaManager) pam).getArea();
|
||||
PlotId id = new PlotId(0, 0);
|
||||
File container = PlotSquared.imp().getWorldContainer();
|
||||
for (File folder : container.listFiles()) {
|
||||
String name = folder.getName();
|
||||
if (!WorldUtil.IMP.isWorld(name) && PlotId.fromString(name) == null) {
|
||||
UUID uuid = UUIDHandler.getUUID(name, null);
|
||||
if (uuid == null) {
|
||||
uuid =
|
||||
UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
while (new File(container, id.toCommaSeparatedString()).exists()) {
|
||||
id = Auto.getNextPlotId(id, 1);
|
||||
}
|
||||
File newDir = new File(container, id.toCommaSeparatedString());
|
||||
if (folder.renameTo(newDir)) {
|
||||
area.getPlot(id).setOwner(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
player.sendMessage("Done!");
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
|
||||
@CommandDeclaration(command = "debugloadtest", permission = "plots.debugloadtest",
|
||||
description = "This debug command will force the reload of all plots in the DB",
|
||||
usage = "/plot debugloadtest", category = CommandCategory.DEBUG,
|
||||
requiredType = RequiredType.CONSOLE) public class DebugLoadTest extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
PlotSquared.get().plots_tmp = DBFunc.getPlots();
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.IncendoPaster;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@CommandDeclaration(command = "debugpaste", aliases = "dp", usage = "/plot debugpaste",
|
||||
description = "Upload settings.yml, worlds.yml, PlotSquared.use_THIS.yml and your latest.log to https://incendo.org",
|
||||
permission = "plots.debugpaste", category = CommandCategory.DEBUG) public class DebugPaste
|
||||
extends SubCommand {
|
||||
|
||||
private static String readFile(@NonNull final File file) throws IOException {
|
||||
final StringBuilder content = new StringBuilder();
|
||||
final List<String> lines = new ArrayList<>();
|
||||
try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
for (int i = Math.max(0, lines.size() - 1000); i < lines.size(); i++) {
|
||||
content.append(lines.get(i)).append("\n");
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
try {
|
||||
final IncendoPaster incendoPaster = new IncendoPaster("plotsquared");
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(
|
||||
"# Welcome to this paste\n# It is meant to provide us at IntellectualSites with better information about your "
|
||||
+ "problem\n\n");
|
||||
b.append("# Server Information\n");
|
||||
b.append("server.version: ").append(PlotSquared.get().IMP.getServerImplementation())
|
||||
.append("\n");
|
||||
b.append("online_mode: ").append(UUIDHandler.getUUIDWrapper()).append(';')
|
||||
.append(!Settings.UUID.OFFLINE).append('\n');
|
||||
b.append("plugins:");
|
||||
for (String id : PlotSquared.get().IMP.getPluginIds()) {
|
||||
String[] split = id.split(":");
|
||||
String[] split2 = split[0].split(";");
|
||||
String enabled = split.length == 2 ? split[1] : "unknown";
|
||||
String name = split2[0];
|
||||
String version = split2.length == 2 ? split2[1] : "unknown";
|
||||
b.append("\n ").append(name).append(":\n ").append("version: '")
|
||||
.append(version).append('\'').append("\n enabled: ").append(enabled);
|
||||
}
|
||||
b.append("\n\n# YAY! Now, let's see what we can find in your JVM\n");
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
b.append("memory.free: ").append(runtime.freeMemory()).append('\n');
|
||||
b.append("memory.max: ").append(runtime.maxMemory()).append('\n');
|
||||
b.append("java.specification.version: '")
|
||||
.append(System.getProperty("java.specification.version")).append("'\n");
|
||||
b.append("java.vendor: '").append(System.getProperty("java.vendor")).append("'\n");
|
||||
b.append("java.version: '").append(System.getProperty("java.version"))
|
||||
.append("'\n");
|
||||
b.append("os.arch: '").append(System.getProperty("os.arch")).append("'\n");
|
||||
b.append("os.name: '").append(System.getProperty("os.name")).append("'\n");
|
||||
b.append("os.version: '").append(System.getProperty("os.version")).append("'\n\n");
|
||||
b.append("# Okay :D Great. You are now ready to create your bug report!");
|
||||
b.append(
|
||||
"\n# You can do so at https://github.com/IntellectualSites/PlotSquared/issues");
|
||||
b.append("\n# or via our Discord at https://discord.gg/ngZCzbU");
|
||||
|
||||
incendoPaster.addFile(new IncendoPaster.PasteFile("information", b.toString()));
|
||||
|
||||
try {
|
||||
final File logFile =
|
||||
new File(PlotSquared.get().IMP.getDirectory(), "../../logs/latest.log");
|
||||
if (Files.size(logFile.toPath()) > 14_000_000) {
|
||||
throw new IOException("Too big...");
|
||||
}
|
||||
incendoPaster
|
||||
.addFile(new IncendoPaster.PasteFile("latest.log", readFile(logFile)));
|
||||
} catch (IOException ignored) {
|
||||
MainUtil
|
||||
.sendMessage(player, "&clatest.log is too big to be pasted, will ignore");
|
||||
}
|
||||
|
||||
try {
|
||||
incendoPaster.addFile(new IncendoPaster.PasteFile("settings.yml",
|
||||
readFile(PlotSquared.get().configFile)));
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
MainUtil.sendMessage(player, "&cSkipping settings.yml because it's empty");
|
||||
}
|
||||
try {
|
||||
incendoPaster.addFile(new IncendoPaster.PasteFile("worlds.yml",
|
||||
readFile(PlotSquared.get().worldsFile)));
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
MainUtil.sendMessage(player, "&cSkipping worlds.yml because it's empty");
|
||||
}
|
||||
try {
|
||||
incendoPaster.addFile(new IncendoPaster.PasteFile("PlotSquared.use_THIS.yml",
|
||||
readFile(PlotSquared.get().translationFile)));
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&cSkipping PlotSquared.use_THIS.yml because it's empty");
|
||||
}
|
||||
|
||||
try {
|
||||
final String rawResponse = incendoPaster.upload();
|
||||
final JsonObject jsonObject =
|
||||
new JsonParser().parse(rawResponse).getAsJsonObject();
|
||||
|
||||
if (jsonObject.has("created")) {
|
||||
final String pasteId = jsonObject.get("paste_id").getAsString();
|
||||
final String link =
|
||||
String.format("https://incendo.org/paste/view/%s", pasteId);
|
||||
player.sendMessage(C.DEBUG_REPORT_CREATED.s().replace("%url%", link));
|
||||
} else {
|
||||
final String responseMessage = jsonObject.get("response").getAsString();
|
||||
MainUtil.sendMessage(player, String
|
||||
.format("&cFailed to create the debug paste: %s", responseMessage));
|
||||
}
|
||||
} catch (final Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
MainUtil.sendMessage(player,
|
||||
"&cFailed to create the debug paste: " + throwable.getMessage());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridPlotManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridPlotWorld;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
@CommandDeclaration(command = "debugroadregen", usage = "/plot debugroadregen",
|
||||
requiredType = RequiredType.NONE,
|
||||
description = "Regenerate all roads based on the road schematic",
|
||||
category = CommandCategory.DEBUG, permission = "plots.debugroadregen")
|
||||
public class DebugRoadRegen extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
PlotArea plotArea = loc.getPlotArea();
|
||||
if (!(plotArea instanceof HybridPlotWorld)) {
|
||||
return sendMessage(player, C.NOT_IN_PLOT_WORLD);
|
||||
}
|
||||
Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
C.NOT_IN_PLOT.send(player);
|
||||
} else if (plot.isMerged()) {
|
||||
C.REQUIRES_UNMERGED.send(player);
|
||||
} else {
|
||||
HybridPlotManager manager = (HybridPlotManager) plotArea.getPlotManager();
|
||||
manager.createRoadEast(plotArea, plot);
|
||||
manager.createRoadSouth(plotArea, plot);
|
||||
manager.createRoadSouthEast(plotArea, plot);
|
||||
MainUtil.sendMessage(player, "&6Regenerating plot south/east roads: " + plot.getId()
|
||||
+ "\n&6 - Result: &aSuccess");
|
||||
MainUtil.sendMessage(player, "&cTo regenerate all roads: /plot regenallroads");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@CommandDeclaration(command = "debugsavetest", permission = "plots.debugsavetest",
|
||||
category = CommandCategory.DEBUG, requiredType = RequiredType.CONSOLE,
|
||||
usage = "/plot debugsavetest",
|
||||
description = "This command will force the recreation of all plots in the DB")
|
||||
public class DebugSaveTest extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
ArrayList<Plot> plots = new ArrayList<Plot>();
|
||||
plots.addAll(PlotSquared.get().getPlots());
|
||||
MainUtil.sendMessage(player, "&6Starting `DEBUGSAVETEST`");
|
||||
DBFunc.createPlotsAndData(plots, new Runnable() {
|
||||
@Override public void run() {
|
||||
MainUtil.sendMessage(player, "&6Database sync finished!");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
|
||||
@CommandDeclaration(command = "delete", permission = "plots.delete",
|
||||
description = "Delete the plot you stand on", usage = "/plot delete",
|
||||
aliases = {"dispose", "del"}, category = CommandCategory.CLAIMING,
|
||||
requiredType = RequiredType.NONE, confirmation = true) public class Delete extends SubCommand {
|
||||
|
||||
// Note: To delete a specific plot use /plot <plot> delete
|
||||
// The syntax also works with any command: /plot <plot> <command>
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
final Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
return !sendMessage(player, C.PLOT_UNOWNED);
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_DELETE)) {
|
||||
return !sendMessage(player, C.NO_PLOT_PERMS);
|
||||
}
|
||||
final PlotArea plotArea = plot.getArea();
|
||||
final java.util.Set<Plot> plots = plot.getConnectedPlots();
|
||||
final int currentPlots =
|
||||
Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(loc.getWorld());
|
||||
Runnable run = new Runnable() {
|
||||
@Override public void run() {
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return;
|
||||
}
|
||||
final long start = System.currentTimeMillis();
|
||||
boolean result = plot.deletePlot(new Runnable() {
|
||||
@Override public void run() {
|
||||
plot.removeRunning();
|
||||
if ((EconHandler.manager != null) && plotArea.USE_ECONOMY) {
|
||||
Expression<Double> valueExr = plotArea.PRICES.get("sell");
|
||||
double value = plots.size() * valueExr.evaluate((double) currentPlots);
|
||||
if (value > 0d) {
|
||||
EconHandler.manager.depositMoney(player, value);
|
||||
sendMessage(player, C.ADDED_BALANCE, String.valueOf(value));
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player, C.DELETING_DONE,
|
||||
System.currentTimeMillis() - start);
|
||||
}
|
||||
});
|
||||
if (result) {
|
||||
plot.addRunning();
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (hasConfirmation(player)) {
|
||||
CmdConfirm.addPending(player, getCommandString() + ' ' + plot.getId(), run);
|
||||
} else {
|
||||
TaskManager.runTask(run);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Argument;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "deny", aliases = {"d", "ban"},
|
||||
description = "Deny a user from a plot", usage = "/plot deny <player>",
|
||||
category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE) public class Deny
|
||||
extends SubCommand {
|
||||
|
||||
public Deny() {
|
||||
super(Argument.PlayerName);
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
|
||||
Location location = player.getLocation();
|
||||
Plot plot = location.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_DENY)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return true;
|
||||
}
|
||||
Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
|
||||
if (uuids.isEmpty()) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[0]);
|
||||
return false;
|
||||
}
|
||||
Iterator<UUID> iter = uuids.iterator();
|
||||
while (iter.hasNext()) {
|
||||
UUID uuid = iter.next();
|
||||
if (uuid == DBFunc.EVERYONE && !(
|
||||
Permissions.hasPermission(player, C.PERMISSION_DENY_EVERYONE) || Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_DENY))) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, MainUtil.getName(uuid));
|
||||
continue;
|
||||
}
|
||||
if (plot.isOwner(uuid)) {
|
||||
MainUtil.sendMessage(player, C.ALREADY_OWNER, MainUtil.getName(uuid));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plot.getDenied().contains(uuid)) {
|
||||
MainUtil.sendMessage(player, C.ALREADY_ADDED, MainUtil.getName(uuid));
|
||||
return false;
|
||||
}
|
||||
if (uuid != DBFunc.EVERYONE) {
|
||||
plot.removeMember(uuid);
|
||||
plot.removeTrusted(uuid);
|
||||
}
|
||||
plot.addDenied(uuid);
|
||||
EventUtil.manager.callDenied(player, plot, uuid, true);
|
||||
if (!uuid.equals(DBFunc.EVERYONE)) {
|
||||
handleKick(UUIDHandler.getPlayer(uuid), plot);
|
||||
} else {
|
||||
for (PlotPlayer plotPlayer : plot.getPlayersInPlot()) {
|
||||
handleKick(plotPlayer, plot);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!uuids.isEmpty()) {
|
||||
MainUtil.sendMessage(player, C.DENIED_ADDED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleKick(PlotPlayer player, Plot plot) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
if (!plot.equals(player.getCurrentPlot())) {
|
||||
return;
|
||||
}
|
||||
if (player.hasPermission("plots.admin.entry.denied")) {
|
||||
return;
|
||||
}
|
||||
if (player.getGameMode() == PlotGameMode.SPECTATOR) {
|
||||
player.stopSpectating();
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
Location spawn = WorldUtil.IMP.getSpawn(loc.getWorld());
|
||||
MainUtil.sendMessage(player, C.YOU_GOT_DENIED);
|
||||
if (plot.equals(spawn.getPlot())) {
|
||||
Location newSpawn =
|
||||
WorldUtil.IMP.getSpawn(PlotSquared.get().getPlotAreaManager().getAllWorlds()[0]);
|
||||
if (plot.equals(newSpawn.getPlot())) {
|
||||
// Kick from server if you can't be teleported to spawn
|
||||
player.kick(C.YOU_GOT_DENIED.s());
|
||||
} else {
|
||||
player.teleport(newSpawn);
|
||||
}
|
||||
} else {
|
||||
player.teleport(spawn);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.FlagManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
@CommandDeclaration(command = "setdescription", permission = "plots.set.desc",
|
||||
description = "Set the plot description", usage = "/plot desc <description>",
|
||||
aliases = {"desc", "setdesc", "setd", "description"}, category = CommandCategory.SETTINGS,
|
||||
requiredType = RequiredType.NONE) public class Desc extends SetCommand {
|
||||
|
||||
@Override public boolean set(PlotPlayer player, Plot plot, String desc) {
|
||||
if (desc.isEmpty()) {
|
||||
plot.removeFlag(Flags.DESCRIPTION);
|
||||
MainUtil.sendMessage(player, C.DESC_UNSET);
|
||||
return true;
|
||||
}
|
||||
boolean result = FlagManager.addPlotFlag(plot, Flags.DESCRIPTION, desc);
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.FLAG_NOT_ADDED);
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.DESC_SET);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpireManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.expiry.PlotAnalysis;
|
||||
|
||||
@CommandDeclaration(command = "done", aliases = {"submit"}, description = "Mark a plot as done",
|
||||
permission = "plots.done", category = CommandCategory.SETTINGS,
|
||||
requiredType = RequiredType.NONE) public class Done extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
final Plot plot = loc.getPlotAbs();
|
||||
if ((plot == null) || !plot.hasOwner()) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_DONE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (plot.hasFlag(Flags.DONE)) {
|
||||
MainUtil.sendMessage(player, C.DONE_ALREADY_DONE);
|
||||
return false;
|
||||
}
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
plot.addRunning();
|
||||
MainUtil.sendMessage(player, C.GENERATING_LINK);
|
||||
final Settings.Auto_Clear doneRequirements = Settings.AUTO_CLEAR.get("done");
|
||||
if (ExpireManager.IMP == null || doneRequirements == null) {
|
||||
finish(plot, player, true);
|
||||
plot.removeRunning();
|
||||
} else {
|
||||
HybridUtils.manager.analyzePlot(plot, new RunnableVal<PlotAnalysis>() {
|
||||
@Override public void run(PlotAnalysis value) {
|
||||
plot.removeRunning();
|
||||
boolean result =
|
||||
value.getComplexity(doneRequirements) <= doneRequirements.THRESHOLD;
|
||||
finish(plot, player, result);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void finish(Plot plot, PlotPlayer pp, boolean success) {
|
||||
if (success) {
|
||||
long flagValue = System.currentTimeMillis() / 1000;
|
||||
plot.setFlag(Flags.DONE, flagValue);
|
||||
MainUtil.sendMessage(pp, C.DONE_SUCCESS);
|
||||
} else {
|
||||
MainUtil.sendMessage(pp, C.DONE_INSUFFICIENT_COMPLEXITY);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
@CommandDeclaration(usage = "/plot download [schematic|world]", command = "download",
|
||||
aliases = {"dl"}, category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE,
|
||||
description = "Download your plot", permission = "plots.download") public class Download
|
||||
extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
String world = player.getLocation().getWorld();
|
||||
if (!PlotSquared.get().hasPlotArea(world)) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT_WORLD);
|
||||
}
|
||||
final Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if ((Settings.Done.REQUIRED_FOR_DOWNLOAD && (!plot.getFlag(Flags.DONE).isPresent()))
|
||||
&& !Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_DOWNLOAD)) {
|
||||
MainUtil.sendMessage(player, C.DONE_NOT_DONE);
|
||||
return false;
|
||||
}
|
||||
if ((!plot.isOwner(player.getUUID())) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN.s())) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
if (args.length == 0 || (args.length == 1 && StringMan
|
||||
.isEqualIgnoreCaseToAny(args[0], "sch", "schem", "schematic"))) {
|
||||
if (plot.getVolume() > Integer.MAX_VALUE) {
|
||||
C.SCHEMATIC_TOO_LARGE.send(player);
|
||||
return false;
|
||||
}
|
||||
plot.addRunning();
|
||||
SchematicHandler.manager.getCompoundTag(plot, new RunnableVal<CompoundTag>() {
|
||||
@Override public void run(CompoundTag value) {
|
||||
plot.removeRunning();
|
||||
SchematicHandler.manager.upload(value, null, null, new RunnableVal<URL>() {
|
||||
@Override public void run(URL url) {
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(player, C.GENERATING_LINK_FAILED);
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(player, url.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (args.length == 1 && StringMan
|
||||
.isEqualIgnoreCaseToAny(args[0], "mcr", "world", "mca")) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_DOWNLOAD_WORLD)) {
|
||||
C.NO_PERMISSION.send(player, C.PERMISSION_DOWNLOAD_WORLD);
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, "&cNote: The `.mca` files are 512x512");
|
||||
plot.addRunning();
|
||||
WorldUtil.IMP.saveWorld(world);
|
||||
WorldUtil.IMP.upload(plot, null, null, new RunnableVal<URL>() {
|
||||
@Override public void run(URL url) {
|
||||
plot.removeRunning();
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(player, C.GENERATING_LINK_FAILED);
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(player, url.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.GENERATING_LINK);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,299 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotBlock;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@CommandDeclaration(command = "setflag", aliases = {"f", "flag", "setf", "setflag"},
|
||||
usage = "/plot flag <set|remove|add|list|info> <flag> <value>", description = "Set plot flags",
|
||||
category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE,
|
||||
permission = "plots.flag") public class FlagCmd extends SubCommand {
|
||||
|
||||
private boolean checkPermValue(PlotPlayer player, Flag flag, String key, String value) {
|
||||
key = key.toLowerCase();
|
||||
value = value.toLowerCase();
|
||||
String perm = C.PERMISSION_SET_FLAG_KEY_VALUE.f(key.toLowerCase(), value.toLowerCase());
|
||||
if (flag instanceof IntegerFlag && MathMan.isInteger(value)) {
|
||||
try {
|
||||
int numeric = Integer.parseInt(value);
|
||||
perm = perm.substring(0, perm.length() - value.length() - 1);
|
||||
if (numeric > 0) {
|
||||
int checkRange = PlotSquared.get().getPlatform().equalsIgnoreCase("bukkit") ?
|
||||
numeric :
|
||||
Settings.Limit.MAX_PLOTS;
|
||||
final boolean result = player.hasPermissionRange(perm, checkRange) >= numeric;
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_SET_FLAG_KEY_VALUE
|
||||
.f(key.toLowerCase(), value.toLowerCase()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
} else if (flag instanceof PlotBlockListFlag) {
|
||||
final PlotBlockListFlag blockListFlag = (PlotBlockListFlag) flag;
|
||||
final HashSet<PlotBlock> parsedBlocks = blockListFlag.parseValue(value);
|
||||
for (final PlotBlock block : parsedBlocks) {
|
||||
final String permission = C.PERMISSION_SET_FLAG_KEY_VALUE
|
||||
.f(key.toLowerCase(), block.getRawId().toString().toLowerCase());
|
||||
final boolean result = Permissions.hasPermission(player, permission);
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_SET_FLAG_KEY_VALUE.f(key.toLowerCase(), value.toLowerCase()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
final boolean result = Permissions.hasPermission(player, perm);
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_SET_FLAG_KEY_VALUE.f(key.toLowerCase(), value.toLowerCase()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
|
||||
/*
|
||||
* plot flag set fly true
|
||||
* plot flag remove fly
|
||||
* plot flag remove use 1,3
|
||||
* plot flag add use 2,4
|
||||
* plot flag list
|
||||
*/
|
||||
if (args.length == 0) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag <set|remove|add|list|info>");
|
||||
return false;
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_PLOT);
|
||||
return false;
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
sendMessage(player, C.PLOT_NOT_CLAIMED);
|
||||
return false;
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_SET_FLAG_OTHER)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_SET_FLAG_OTHER);
|
||||
return false;
|
||||
}
|
||||
Flag<?> flag = null;
|
||||
if (args.length > 1) {
|
||||
flag = FlagManager.getFlag(args[1]);
|
||||
if (flag == null || flag.isReserved()) {
|
||||
boolean suggested = false;
|
||||
try {
|
||||
StringComparison<Flag<?>> stringComparison =
|
||||
new StringComparison<>(args[1], Flags.getFlags());
|
||||
String best = stringComparison.getBestMatch();
|
||||
if (best != null) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_FLAG_SUGGESTED, best);
|
||||
suggested = true;
|
||||
}
|
||||
} catch (final Exception ignored) { /* Happens sometimes because of mean code */ }
|
||||
if (!suggested) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_FLAG);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "info": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_SET_FLAG)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.flag.info");
|
||||
return false;
|
||||
}
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag info <flag>");
|
||||
return false;
|
||||
}
|
||||
// flag key
|
||||
MainUtil.sendMessage(player, C.FLAG_KEY, flag.getName());
|
||||
// flag type
|
||||
MainUtil.sendMessage(player, C.FLAG_TYPE, flag.getClass().getSimpleName());
|
||||
// Flag type description
|
||||
MainUtil.sendMessage(player, C.FLAG_DESC, flag.getValueDescription());
|
||||
return true;
|
||||
}
|
||||
case "set": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_SET_FLAG)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_SET_FLAG);
|
||||
return false;
|
||||
}
|
||||
if (args.length < 3) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag set <flag> <value>");
|
||||
return false;
|
||||
}
|
||||
String value = StringMan.join(Arrays.copyOfRange(args, 2, args.length), " ");
|
||||
if (!checkPermValue(player, flag, args[1], value)) {
|
||||
return false;
|
||||
}
|
||||
Object parsed = flag.parseValue(value);
|
||||
if (parsed == null) {
|
||||
MainUtil.sendMessage(player, "&c" + flag.getValueDescription());
|
||||
return false;
|
||||
}
|
||||
boolean result = plot.setFlag(flag, parsed);
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.FLAG_NOT_ADDED);
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.FLAG_ADDED);
|
||||
return true;
|
||||
}
|
||||
case "remove": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_FLAG_REMOVE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_FLAG_REMOVE);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 2 && args.length != 3) {
|
||||
MainUtil
|
||||
.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag remove <flag> [values]");
|
||||
return false;
|
||||
}
|
||||
if (!Permissions
|
||||
.hasPermission(player, C.PERMISSION_SET_FLAG_KEY.f(args[1].toLowerCase()))) {
|
||||
if (args.length != 3) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_SET_FLAG_KEY.f(args[1].toLowerCase()));
|
||||
return false;
|
||||
}
|
||||
for (String entry : args[2].split(",")) {
|
||||
if (!checkPermValue(player, flag, args[1], entry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (args.length == 3 && flag instanceof ListFlag) {
|
||||
String value = StringMan.join(Arrays.copyOfRange(args, 2, args.length), " ");
|
||||
Optional<? extends Collection> flag1 =
|
||||
plot.getFlag((Flag<? extends Collection<?>>) flag);
|
||||
if (flag1.isPresent()) {
|
||||
boolean o = flag1.get().removeAll((Collection) flag.parseValue(value));
|
||||
if (o) {
|
||||
if (flag1.get().isEmpty()) {
|
||||
final boolean result = plot.removeFlag(flag);
|
||||
if (result) {
|
||||
MainUtil.sendMessage(player, C.FLAG_REMOVED);
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.FLAG_NOT_REMOVED);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.FLAG_REMOVED);
|
||||
}
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.FLAG_NOT_REMOVED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DBFunc.setFlags(plot, plot.getFlags());
|
||||
return true;
|
||||
} else {
|
||||
boolean result = plot.removeFlag(flag);
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.FLAG_NOT_REMOVED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (flag == Flags.TIME) {
|
||||
player.setTime(Long.MAX_VALUE);
|
||||
} else if (flag == Flags.WEATHER) {
|
||||
player.setWeather(PlotWeather.RESET);
|
||||
}
|
||||
MainUtil.sendMessage(player, C.FLAG_REMOVED);
|
||||
return true;
|
||||
}
|
||||
case "add":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_FLAG_ADD)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_FLAG_ADD);
|
||||
return false;
|
||||
}
|
||||
if (args.length < 3) {
|
||||
MainUtil
|
||||
.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag add <flag> <values>");
|
||||
return false;
|
||||
}
|
||||
for (String entry : args[2].split(",")) {
|
||||
if (!checkPermValue(player, flag, args[1], entry)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
String value = StringMan.join(Arrays.copyOfRange(args, 2, args.length), " ");
|
||||
Object parsed = flag.parseValue(value);
|
||||
if (parsed == null) {
|
||||
MainUtil.sendMessage(player, "&c" + flag.getValueDescription());
|
||||
return false;
|
||||
}
|
||||
Object val = parsed;
|
||||
if (flag instanceof ListFlag) {
|
||||
Optional<? extends Collection> flag1 =
|
||||
plot.getFlag((Flag<? extends Collection<?>>) flag);
|
||||
if (flag1.isPresent()) {
|
||||
boolean o = flag1.get().addAll((Collection) parsed);
|
||||
if (o) {
|
||||
MainUtil.sendMessage(player, C.FLAG_ADDED);
|
||||
val = flag1.get();
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.FLAG_NOT_ADDED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean result = plot.setFlag(flag, val);
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, C.FLAG_NOT_ADDED);
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.FLAG_ADDED);
|
||||
return true;
|
||||
case "list":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_FLAG_LIST)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_FLAG_LIST);
|
||||
return false;
|
||||
}
|
||||
if (args.length > 1) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag list");
|
||||
return false;
|
||||
}
|
||||
HashMap<String, ArrayList<String>> flags = new HashMap<>();
|
||||
for (Flag<?> flag1 : Flags.getFlags()) {
|
||||
String type = flag1.getClass().getSimpleName();
|
||||
if (!flags.containsKey(type)) {
|
||||
flags.put(type, new ArrayList<>());
|
||||
}
|
||||
flags.get(type).add(flag1.getName());
|
||||
}
|
||||
StringBuilder message = new StringBuilder();
|
||||
String prefix = "";
|
||||
for (Map.Entry<String, ArrayList<String>> entry : flags.entrySet()) {
|
||||
String category = entry.getKey();
|
||||
List<String> flagNames = entry.getValue();
|
||||
Collections.sort(flagNames);
|
||||
message.append(prefix).append("&6").append(category).append(": &7")
|
||||
.append(StringMan.join(flagNames, ", "));
|
||||
prefix = "\n";
|
||||
}
|
||||
MainUtil.sendMessage(player, message.toString());
|
||||
return true;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot flag <set|remove|add|list|info>");
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GenerateDocs {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new WE_Anywhere();
|
||||
List<Command> commands = MainCommand.getInstance().getCommands();
|
||||
GenerateDocs.log("### Want to document some commands?");
|
||||
GenerateDocs.log(" - This page is automatically generated");
|
||||
GenerateDocs
|
||||
.log(" - Fork the project and add a javadoc comment to one of the command classes");
|
||||
GenerateDocs.log(" - Then do a pull request and it will be added to this page");
|
||||
GenerateDocs.log("");
|
||||
GenerateDocs.log("# Contents");
|
||||
for (CommandCategory category : CommandCategory.values()) {
|
||||
GenerateDocs.log("###### " + category.name());
|
||||
for (Command command : MainCommand.getInstance().getCommands(category, null)) {
|
||||
GenerateDocs.log(" - [/plot " + command.getId()
|
||||
+ "](https://github.com/IntellectualSites/PlotSquared/wiki/Commands#" + command
|
||||
.getId() + ") ");
|
||||
}
|
||||
GenerateDocs.log("");
|
||||
}
|
||||
GenerateDocs.log("# Commands");
|
||||
for (Command command : commands) {
|
||||
GenerateDocs.printCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printCommand(Command command) {
|
||||
try {
|
||||
String clazz = command.getClass().getSimpleName();
|
||||
String name = command.getId();
|
||||
|
||||
// Header
|
||||
String source =
|
||||
"https://github.com/IntellectualSites/PlotSquared/tree/master/Core/src/main/java/com/intellectualcrafters/plot/commands/"
|
||||
+ clazz + ".java";
|
||||
GenerateDocs.log("## [" + name.toUpperCase() + "](" + source + ") ");
|
||||
|
||||
File file = new File(
|
||||
"Core/src/main/java/com/intellectualcrafters/plot/commands/" + clazz + ".java");
|
||||
List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
|
||||
List<String> perms = GenerateDocs.getPerms(name, lines);
|
||||
List<String> usages = GenerateDocs.getUsage(name, lines);
|
||||
String comment = GenerateDocs.getComments(lines);
|
||||
|
||||
GenerateDocs.log("#### Description");
|
||||
GenerateDocs.log('`' + command.getDescription() + '`');
|
||||
if (!comment.isEmpty()) {
|
||||
GenerateDocs.log("##### Comments");
|
||||
GenerateDocs.log("``` java");
|
||||
GenerateDocs.log(comment);
|
||||
GenerateDocs.log("```");
|
||||
}
|
||||
|
||||
GenerateDocs.log("#### Usage ");
|
||||
String mainUsage = command.getUsage().replaceAll("\\{label\\}", "plot");
|
||||
if (!usages.isEmpty() && !usages.get(0).equalsIgnoreCase(mainUsage)) {
|
||||
GenerateDocs.log("##### Primary ");
|
||||
GenerateDocs.log(" - `" + mainUsage + "` ");
|
||||
GenerateDocs.log("");
|
||||
GenerateDocs.log("##### Other ");
|
||||
GenerateDocs.log(" - `" + StringMan.join(usages, "`\n - `") + "` ");
|
||||
GenerateDocs.log("");
|
||||
} else {
|
||||
GenerateDocs.log('`' + mainUsage + "` ");
|
||||
}
|
||||
|
||||
if (command.getRequiredType() != RequiredType.NONE) {
|
||||
GenerateDocs.log("#### Required callers");
|
||||
GenerateDocs.log('`' + command.getRequiredType().name() + '`');
|
||||
}
|
||||
|
||||
List<String> aliases = command.getAliases();
|
||||
if (!aliases.isEmpty()) {
|
||||
GenerateDocs.log("#### Aliases");
|
||||
GenerateDocs.log('`' + StringMan.getString(command.getAliases()) + '`');
|
||||
}
|
||||
|
||||
GenerateDocs.log("#### Permissions");
|
||||
if (!perms.isEmpty()) {
|
||||
GenerateDocs.log("##### Primary");
|
||||
GenerateDocs.log(" - `" + command.getPermission() + "` ");
|
||||
GenerateDocs.log("");
|
||||
GenerateDocs.log("##### Other");
|
||||
GenerateDocs.log(" - `" + StringMan.join(perms, "`\n - `") + '`');
|
||||
GenerateDocs.log("");
|
||||
} else {
|
||||
GenerateDocs.log('`' + command.getPermission() + "` ");
|
||||
}
|
||||
GenerateDocs.log("***");
|
||||
GenerateDocs.log("");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getUsage(String cmd, List<String> lines) {
|
||||
Pattern p = Pattern.compile("\"([^\"]*)\"");
|
||||
HashSet<String> usages = new HashSet<>();
|
||||
for (String line : lines) {
|
||||
if (line.contains("COMMAND_SYNTAX") && !line.contains("getUsage()")) {
|
||||
Matcher m = p.matcher(line);
|
||||
String prefix = "";
|
||||
StringBuilder usage = new StringBuilder();
|
||||
while (m.find()) {
|
||||
String match = m.group(1);
|
||||
usage.append(prefix).append(match);
|
||||
prefix = " <arg> ";
|
||||
}
|
||||
if (usage.length() != 0) {
|
||||
usages.add(usage.toString().trim().replaceAll(" ", " ")
|
||||
.replaceAll("\\{label\\}", "plot"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(usages);
|
||||
}
|
||||
|
||||
public static List<String> getPerms(String cmd, List<String> lines) {
|
||||
HashSet<String> perms = new HashSet<>();
|
||||
Pattern p = Pattern.compile("\"([^\"]*)\"");
|
||||
Pattern p2 = Pattern.compile("C.PERMISSION_\\s*(\\w+)");
|
||||
String last = null;
|
||||
for (String line : lines) {
|
||||
|
||||
Matcher m2 = p2.matcher(line);
|
||||
while (m2.find()) {
|
||||
perms.add(C.valueOf("PERMISSION_" + m2.group(1)).s());
|
||||
}
|
||||
if (line.contains("Permissions.hasPermission(")) {
|
||||
String[] split = line.split("Permissions.hasPermission");
|
||||
split = Arrays.copyOfRange(split, 1, split.length);
|
||||
for (String method : split) {
|
||||
String perm = method.split("[,|)]")[1].trim();
|
||||
if (!perm.equalsIgnoreCase(perm)) {
|
||||
if (perm.startsWith("C.")) {
|
||||
perm = C.valueOf(perm.split("\\.")[1]).s();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
perm = perm.substring(1, perm.length() - 1);
|
||||
}
|
||||
perms.add(perm);
|
||||
}
|
||||
Matcher m = p.matcher(line);
|
||||
while (m.find()) {
|
||||
String perm = m.group(1);
|
||||
if (perm.endsWith(".")) {
|
||||
perm += "<arg>";
|
||||
}
|
||||
if (perm.startsWith(".")) {
|
||||
perms.remove(last);
|
||||
perms.add(last + perm);
|
||||
} else if (perm.contains(".")) {
|
||||
last = perm;
|
||||
perms.add(perm);
|
||||
}
|
||||
}
|
||||
} else if (line.contains("Permissions.hasPermissionRange")) {
|
||||
String[] split = line.split("Permissions.hasPermissionRange");
|
||||
split = Arrays.copyOfRange(split, 1, split.length);
|
||||
for (String method : split) {
|
||||
String perm = method.split("[,|)]")[1].trim();
|
||||
if (!perm.equalsIgnoreCase(perm)) {
|
||||
if (perm.startsWith("C.")) {
|
||||
perm = C.valueOf(perm.split("\\.")[1]).s();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
perm = perm.substring(1, perm.length() - 1);
|
||||
}
|
||||
perms.add(perm + ".<#>");
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (cmd.toLowerCase()) {
|
||||
case "auto":
|
||||
case "claim":
|
||||
perms.add("plots.plot.<#>");
|
||||
break;
|
||||
}
|
||||
return new ArrayList<>(perms);
|
||||
}
|
||||
|
||||
public static String getComments(List<String> lines) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String line : lines) {
|
||||
line = line.trim();
|
||||
if (line.startsWith("/** ") || line.startsWith("*/ ") || line.startsWith("* ")) {
|
||||
line =
|
||||
line.replaceAll("/[*][*] ", "").replaceAll("[*]/ ", "").replaceAll("[*] ", "")
|
||||
.trim();
|
||||
result.append(line + '\n');
|
||||
}
|
||||
}
|
||||
return result.toString().trim();
|
||||
}
|
||||
|
||||
public static void log(String s) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.ByteArrayUtilities;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "grant", category = CommandCategory.CLAIMING,
|
||||
usage = "/plot grant <check|add> [player]", permission = "plots.grant",
|
||||
requiredType = RequiredType.NONE) public class Grant extends Command {
|
||||
|
||||
public Grant() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(final PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
|
||||
checkTrue(args.length >= 1 && args.length <= 2, C.COMMAND_SYNTAX, getUsage());
|
||||
final String arg0 = args[0].toLowerCase();
|
||||
switch (arg0) {
|
||||
case "add":
|
||||
case "check":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_GRANT.f(arg0))) {
|
||||
C.NO_PERMISSION.send(player, C.PERMISSION_GRANT.f(arg0));
|
||||
return;
|
||||
}
|
||||
if (args.length > 2) {
|
||||
break;
|
||||
}
|
||||
final UUID uuid =
|
||||
args.length == 2 ? UUIDHandler.getUUIDFromString(args[1]) : player.getUUID();
|
||||
if (uuid == null) {
|
||||
C.INVALID_PLAYER.send(player, args[1]);
|
||||
return;
|
||||
}
|
||||
MainUtil.getPersistentMeta(uuid, "grantedPlots", new RunnableVal<byte[]>() {
|
||||
@Override public void run(byte[] array) {
|
||||
if (arg0.equals("check")) { // check
|
||||
int granted =
|
||||
array == null ? 0 : ByteArrayUtilities.bytesToInteger(array);
|
||||
C.GRANTED_PLOTS.send(player, granted);
|
||||
} else { // add
|
||||
int amount =
|
||||
1 + (array == null ? 0 : ByteArrayUtilities.bytesToInteger(array));
|
||||
boolean replace = array != null;
|
||||
String key = "grantedPlots";
|
||||
byte[] rawData = ByteArrayUtilities.integerToBytes(amount);
|
||||
PlotPlayer online = UUIDHandler.getPlayer(uuid);
|
||||
if (online != null) {
|
||||
online.setPersistentMeta(key, rawData);
|
||||
} else {
|
||||
DBFunc.addPersistentMeta(uuid, key, rawData, replace);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MathMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.helpmenu.HelpMenu;
|
||||
|
||||
@CommandDeclaration(command = "help", description = "Get this help menu", aliases = {"he", "?"},
|
||||
category = CommandCategory.INFO, usage = "help [category|#]", permission = "plots.use")
|
||||
public class Help extends Command {
|
||||
public Help(Command parent) {
|
||||
super(parent, true);
|
||||
}
|
||||
|
||||
@Override public boolean canExecute(PlotPlayer player, boolean message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) {
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
displayHelp(player, null, 0);
|
||||
return;
|
||||
case 1:
|
||||
if (MathMan.isInteger(args[0])) {
|
||||
try {
|
||||
displayHelp(player, null, Integer.parseInt(args[0]));
|
||||
} catch (NumberFormatException ignored) {
|
||||
displayHelp(player, null, 1);
|
||||
}
|
||||
} else {
|
||||
displayHelp(player, args[0], 1);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
if (MathMan.isInteger(args[1])) {
|
||||
try {
|
||||
displayHelp(player, args[0], Integer.parseInt(args[1]));
|
||||
} catch (NumberFormatException ignored) {
|
||||
displayHelp(player, args[0], 1);
|
||||
}
|
||||
}
|
||||
return;
|
||||
default:
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
}
|
||||
}
|
||||
|
||||
public void displayHelp(PlotPlayer player, String cat, int page) {
|
||||
CommandCategory catEnum = null;
|
||||
if (cat != null) {
|
||||
if (!StringMan.isEqualIgnoreCase(cat, "all")) {
|
||||
for (CommandCategory c : CommandCategory.values()) {
|
||||
if (StringMan.isEqualIgnoreCaseToAny(cat, c.name(), c.toString())) {
|
||||
catEnum = c;
|
||||
cat = c.name();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (catEnum == null) {
|
||||
cat = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cat == null && page == 0) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(C.HELP_HEADER.s());
|
||||
for (CommandCategory c : CommandCategory.values()) {
|
||||
builder.append("\n" + StringMan
|
||||
.replaceAll(C.HELP_INFO_ITEM.s(), "%category%", c.toString().toLowerCase(),
|
||||
"%category_desc%", c.toString()));
|
||||
}
|
||||
builder.append("\n").append(C.HELP_INFO_ITEM.s().replaceAll("%category%", "all")
|
||||
.replaceAll("%category_desc%", "Display all commands"));
|
||||
builder.append("\n" + C.HELP_FOOTER.s());
|
||||
MainUtil.sendMessage(player, builder.toString(), false);
|
||||
return;
|
||||
}
|
||||
page--;
|
||||
new HelpMenu(player).setCategory(catEnum).getCommands().generateMaxPages()
|
||||
.generatePage(page, getParent().toString()).render();
|
||||
}
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.comment.CommentInbox;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.comment.PlotComment;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.CommentManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@CommandDeclaration(command = "inbox", description = "Review the comments for a plot",
|
||||
usage = "/plot inbox [inbox] [delete <index>|clear|page]", permission = "plots.inbox",
|
||||
category = CommandCategory.CHAT, requiredType = RequiredType.NONE) public class Inbox
|
||||
extends SubCommand {
|
||||
|
||||
public void displayComments(PlotPlayer player, List<PlotComment> oldComments, int page) {
|
||||
if (oldComments == null || oldComments.isEmpty()) {
|
||||
MainUtil.sendMessage(player, C.INBOX_EMPTY);
|
||||
return;
|
||||
}
|
||||
PlotComment[] comments = oldComments.toArray(new PlotComment[oldComments.size()]);
|
||||
if (page < 0) {
|
||||
page = 0;
|
||||
}
|
||||
// Get the total pages
|
||||
// int totalPages = ((int) Math.ceil(12 *
|
||||
int totalPages = (int) Math.ceil(comments.length / 12);
|
||||
if (page > totalPages) {
|
||||
page = totalPages;
|
||||
}
|
||||
// Only display 12 per page
|
||||
int max = page * 12 + 12;
|
||||
if (max > comments.length) {
|
||||
max = comments.length;
|
||||
}
|
||||
StringBuilder string = new StringBuilder();
|
||||
string.append(StringMan
|
||||
.replaceAll(C.COMMENT_LIST_HEADER_PAGED.s(), "%amount%", comments.length, "%cur",
|
||||
page + 1, "%max", totalPages + 1, "%word", "all") + '\n');
|
||||
|
||||
// This might work xD
|
||||
for (int x = page * 12; x < max; x++) {
|
||||
PlotComment comment = comments[x];
|
||||
String color;
|
||||
if (player.getName().equals(comment.senderName)) {
|
||||
color = "&a";
|
||||
} else {
|
||||
color = "&7";
|
||||
}
|
||||
string.append("&8[&7#").append(x + 1).append("&8][&7").append(comment.world).append(';')
|
||||
.append(comment.id).append("&8][&6").append(comment.senderName).append("&8]")
|
||||
.append(color).append(comment.comment).append('\n');
|
||||
}
|
||||
MainUtil.sendMessage(player, string.toString());
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
final Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
sendMessage(player, C.NOT_IN_PLOT);
|
||||
return false;
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if (args.length == 0) {
|
||||
sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot inbox [inbox] [delete <index>|clear|page]");
|
||||
for (final CommentInbox inbox : CommentManager.inboxes.values()) {
|
||||
if (inbox.canRead(plot, player)) {
|
||||
if (!inbox.getComments(plot, new RunnableVal<List<PlotComment>>() {
|
||||
@Override public void run(List<PlotComment> value) {
|
||||
if (value != null) {
|
||||
int total = 0;
|
||||
int unread = 0;
|
||||
for (PlotComment comment : value) {
|
||||
total++;
|
||||
if (comment.timestamp > CommentManager
|
||||
.getTimestamp(player, inbox.toString())) {
|
||||
unread++;
|
||||
}
|
||||
}
|
||||
if (total != 0) {
|
||||
String color;
|
||||
if (unread > 0) {
|
||||
color = "&c";
|
||||
} else {
|
||||
color = "";
|
||||
}
|
||||
sendMessage(player, C.INBOX_ITEM,
|
||||
color + inbox.toString() + " (" + total + '/' + unread
|
||||
+ ')');
|
||||
return;
|
||||
}
|
||||
}
|
||||
sendMessage(player, C.INBOX_ITEM, inbox.toString());
|
||||
}
|
||||
})) {
|
||||
sendMessage(player, C.INBOX_ITEM, inbox.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
final CommentInbox inbox = CommentManager.inboxes.get(args[0].toLowerCase());
|
||||
if (inbox == null) {
|
||||
sendMessage(player, C.INVALID_INBOX,
|
||||
StringMan.join(CommentManager.inboxes.keySet(), ", "));
|
||||
return false;
|
||||
}
|
||||
player.setMeta("inbox:" + inbox.toString(), System.currentTimeMillis());
|
||||
final int page;
|
||||
if (args.length > 1) {
|
||||
switch (args[1].toLowerCase()) {
|
||||
case "delete":
|
||||
if (!inbox.canModify(plot, player)) {
|
||||
sendMessage(player, C.NO_PERM_INBOX_MODIFY);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 3) {
|
||||
sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot inbox " + inbox.toString() + " delete <index>");
|
||||
}
|
||||
final int index;
|
||||
try {
|
||||
index = Integer.parseInt(args[2]);
|
||||
if (index < 1) {
|
||||
sendMessage(player, C.NOT_VALID_INBOX_INDEX, index + "");
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot inbox " + inbox.toString() + " delete <index>");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!inbox.getComments(plot, new RunnableVal<List<PlotComment>>() {
|
||||
@Override public void run(List<PlotComment> value) {
|
||||
if (index > value.size()) {
|
||||
sendMessage(player, C.NOT_VALID_INBOX_INDEX, index + "");
|
||||
return;
|
||||
}
|
||||
PlotComment comment = value.get(index - 1);
|
||||
inbox.removeComment(plot, comment);
|
||||
plot.getSettings().removeComment(comment);
|
||||
MainUtil.sendMessage(player, C.COMMENT_REMOVED, comment.comment);
|
||||
}
|
||||
})) {
|
||||
sendMessage(player, C.NOT_IN_PLOT);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case "clear":
|
||||
if (!inbox.canModify(plot, player)) {
|
||||
sendMessage(player, C.NO_PERM_INBOX_MODIFY);
|
||||
}
|
||||
inbox.clearInbox(plot);
|
||||
Optional<ArrayList<PlotComment>> comments =
|
||||
plot.getSettings().getComments(inbox.toString());
|
||||
comments
|
||||
.ifPresent(plotComments -> plot.getSettings().removeComments(plotComments));
|
||||
MainUtil.sendMessage(player, C.COMMENT_REMOVED, "*");
|
||||
return true;
|
||||
default:
|
||||
try {
|
||||
page = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException ignored) {
|
||||
sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot inbox [inbox] [delete <index>|clear|page]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
page = 1;
|
||||
}
|
||||
if (!inbox.canRead(plot, player)) {
|
||||
sendMessage(player, C.NO_PERM_INBOX);
|
||||
return false;
|
||||
}
|
||||
if (!inbox.getComments(plot, new RunnableVal<List<PlotComment>>() {
|
||||
@Override public void run(List<PlotComment> value) {
|
||||
displayComments(player, value, page);
|
||||
}
|
||||
})) {
|
||||
sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpireManager;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "info", aliases = "i", description = "Display plot info",
|
||||
usage = "/plot info <id>", category = CommandCategory.INFO) public class Info
|
||||
extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
Plot plot;
|
||||
String arg;
|
||||
if (args.length > 0) {
|
||||
arg = args[0];
|
||||
switch (arg) {
|
||||
case "trusted":
|
||||
case "alias":
|
||||
case "inv":
|
||||
case "biome":
|
||||
case "denied":
|
||||
case "flags":
|
||||
case "id":
|
||||
case "size":
|
||||
case "members":
|
||||
case "seen":
|
||||
case "owner":
|
||||
case "rating":
|
||||
plot = MainUtil.getPlotFromString(player, null, false);
|
||||
break;
|
||||
default:
|
||||
plot = MainUtil.getPlotFromString(player, arg, false);
|
||||
if (args.length == 2) {
|
||||
arg = args[1];
|
||||
} else {
|
||||
arg = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (plot == null) {
|
||||
plot = player.getCurrentPlot();
|
||||
}
|
||||
} else {
|
||||
arg = null;
|
||||
plot = player.getCurrentPlot();
|
||||
}
|
||||
if (plot == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_PLOT.s());
|
||||
return false;
|
||||
}
|
||||
if (arg != null) {
|
||||
if (args.length == 1) {
|
||||
args = new String[0];
|
||||
} else {
|
||||
args = new String[] {args[1]};
|
||||
}
|
||||
}
|
||||
if (args.length == 1 && args[0].equalsIgnoreCase("inv")) {
|
||||
PlotInventory inv = new PlotInventory(player) {
|
||||
@Override public boolean onClick(int index) {
|
||||
// TODO InfoInventory not implemented yet!!!!!!!!
|
||||
// See plot rating or musicsubcommand on examples
|
||||
return false;
|
||||
}
|
||||
};
|
||||
UUID uuid = player.getUUID();
|
||||
String name = MainUtil.getName(plot.owner);
|
||||
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cPlot Info",
|
||||
"&cID: &6" + plot.getId().toString(), "&cOwner: &6" + name,
|
||||
"&cAlias: &6" + plot.getAlias(),
|
||||
"&cBiome: &6" + plot.getBiome().replaceAll("_", "").toLowerCase(),
|
||||
"&cCan Build: &6" + plot.isAdded(uuid),
|
||||
"&cSeen: &6" + MainUtil.secToTime((int) (ExpireManager.IMP.getAge(plot) / 1000)),
|
||||
"&cIs Denied: &6" + plot.isDenied(uuid)));
|
||||
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cTrusted",
|
||||
"&cAmount: &6" + plot.getTrusted().size(),
|
||||
"&8Click to view a list of the trusted users"));
|
||||
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cMembers",
|
||||
"&cAmount: &6" + plot.getMembers().size(),
|
||||
"&8Click to view a list of plot members"));
|
||||
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cDenied", "&cDenied",
|
||||
"&cAmount: &6" + plot.getDenied().size(),
|
||||
"&8Click to view a list of denied players"));
|
||||
inv.setItem(1, new PlotItemStack(388, (short) 0, 1, "&cFlags", "&cFlags",
|
||||
"&cAmount: &6" + plot.getFlags().size(), "&8Click to view a list of plot flags"));
|
||||
inv.openInventory();
|
||||
return true;
|
||||
}
|
||||
boolean hasOwner = plot.hasOwner();
|
||||
// Wildcard player {added}
|
||||
boolean containsEveryone = plot.getTrusted().contains(DBFunc.EVERYONE);
|
||||
boolean trustedEveryone = plot.getMembers().contains(DBFunc.EVERYONE);
|
||||
// Unclaimed?
|
||||
if (!hasOwner && !containsEveryone && !trustedEveryone) {
|
||||
MainUtil
|
||||
.sendMessage(player, C.PLOT_INFO_UNCLAIMED, plot.getId().x + ";" + plot.getId().y);
|
||||
return true;
|
||||
}
|
||||
String info = C.PLOT_INFO.s();
|
||||
boolean full;
|
||||
if (arg != null) {
|
||||
info = getCaption(arg);
|
||||
if (info == null) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&6Categories&7: &amembers&7, &aalias&7, &abiome&7, &aseen&7, &adenied&7, &aflags&7, &aid&7, &asize&7, &atrusted&7, "
|
||||
+ "&aowner&7, &arating");
|
||||
return false;
|
||||
}
|
||||
full = true;
|
||||
} else {
|
||||
full = false;
|
||||
}
|
||||
MainUtil.format(info, plot, player, full, new RunnableVal<String>() {
|
||||
@Override public void run(String value) {
|
||||
MainUtil.sendMessage(player,
|
||||
C.PLOT_INFO_HEADER.s() + '\n' + value + '\n' + C.PLOT_INFO_FOOTER.s(), false);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getCaption(String string) {
|
||||
switch (string) {
|
||||
case "trusted":
|
||||
return C.PLOT_INFO_TRUSTED.s();
|
||||
case "alias":
|
||||
return C.PLOT_INFO_ALIAS.s();
|
||||
case "biome":
|
||||
return C.PLOT_INFO_BIOME.s();
|
||||
case "denied":
|
||||
return C.PLOT_INFO_DENIED.s();
|
||||
case "flags":
|
||||
return C.PLOT_INFO_FLAGS.s();
|
||||
case "id":
|
||||
return C.PLOT_INFO_ID.s();
|
||||
case "size":
|
||||
return C.PLOT_INFO_SIZE.s();
|
||||
case "members":
|
||||
return C.PLOT_INFO_MEMBERS.s();
|
||||
case "owner":
|
||||
return C.PLOT_INFO_OWNER.s();
|
||||
case "rating":
|
||||
return C.PLOT_INFO_RATING.s();
|
||||
case "seen":
|
||||
return C.PLOT_INFO_SEEN.s();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Argument;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "kick", aliases = {"k"}, description = "Kick a player from your plot",
|
||||
permission = "plots.kick", usage = "/plot kick <player>", category = CommandCategory.TELEPORT,
|
||||
requiredType = RequiredType.NONE) public class Kick extends SubCommand {
|
||||
|
||||
public Kick() {
|
||||
super(Argument.PlayerName);
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
Location location = player.getLocation();
|
||||
Plot plot = location.getPlot();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if ((!plot.hasOwner() || !plot.isOwner(player.getUUID())) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_KICK)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
|
||||
if (uuids.isEmpty()) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[0]);
|
||||
return false;
|
||||
}
|
||||
Set<PlotPlayer> players = new HashSet<>();
|
||||
for (UUID uuid : uuids) {
|
||||
if (uuid == DBFunc.EVERYONE) {
|
||||
for (PlotPlayer pp : plot.getPlayersInPlot()) {
|
||||
if (pp == player || Permissions
|
||||
.hasPermission(pp, C.PERMISSION_ADMIN_ENTRY_DENIED)) {
|
||||
continue;
|
||||
}
|
||||
players.add(pp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
PlotPlayer pp = UUIDHandler.getPlayer(uuid);
|
||||
if (pp != null) {
|
||||
players.add(pp);
|
||||
}
|
||||
}
|
||||
players.remove(player); // Don't ever kick the calling player
|
||||
if (players.isEmpty()) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[0]);
|
||||
return false;
|
||||
}
|
||||
for (PlotPlayer player2 : players) {
|
||||
if (!plot.equals(player2.getCurrentPlot())) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[0]);
|
||||
return false;
|
||||
}
|
||||
if (Permissions.hasPermission(player2, C.PERMISSION_ADMIN_ENTRY_DENIED)) {
|
||||
C.CANNOT_KICK_PLAYER.send(player, player2.getName());
|
||||
return false;
|
||||
}
|
||||
Location spawn = WorldUtil.IMP.getSpawn(location.getWorld());
|
||||
C.YOU_GOT_KICKED.send(player2);
|
||||
if (plot.equals(spawn.getPlot())) {
|
||||
Location newSpawn = WorldUtil.IMP
|
||||
.getSpawn(PlotSquared.get().getPlotAreaManager().getAllWorlds()[0]);
|
||||
if (plot.equals(newSpawn.getPlot())) {
|
||||
// Kick from server if you can't be teleported to spawn
|
||||
player2.kick(C.YOU_GOT_KICKED.s());
|
||||
} else {
|
||||
player2.plotkick(newSpawn);
|
||||
}
|
||||
} else {
|
||||
player2.plotkick(spawn);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.EventUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "leave",
|
||||
description = "Removes self from being trusted or a member of the plot",
|
||||
permission = "plots.leave", category = CommandCategory.CLAIMING,
|
||||
requiredType = RequiredType.NONE) public class Leave extends Command {
|
||||
public Leave() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
|
||||
final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
|
||||
checkTrue(plot.hasOwner(), C.PLOT_UNOWNED);
|
||||
checkTrue(plot.isAdded(player.getUUID()), C.NO_PLOT_PERMS);
|
||||
checkTrue(args.length == 0, C.COMMAND_SYNTAX, getUsage());
|
||||
if (plot.isOwner(player.getUUID())) {
|
||||
checkTrue(plot.hasOwner(), C.ALREADY_OWNER);
|
||||
// TODO setowner, other
|
||||
} else {
|
||||
UUID uuid = player.getUUID();
|
||||
if (plot.isAdded(uuid)) {
|
||||
if (plot.removeTrusted(uuid)) {
|
||||
EventUtil.manager.callTrusted(player, plot, uuid, false);
|
||||
}
|
||||
if (plot.removeMember(uuid)) {
|
||||
EventUtil.manager.callMember(player, plot, uuid, false);
|
||||
}
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[0]);
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.REMOVED_PLAYERS, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,397 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared.SortType;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpireManager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@CommandDeclaration(command = "list", aliases = {"l", "find", "search"}, description = "List plots",
|
||||
permission = "plots.list", category = CommandCategory.INFO,
|
||||
usage = "/plot list <forsale|mine|shared|world|top|all|unowned|unknown|player|world|done|fuzzy <search...>> [#]")
|
||||
public class ListCmd extends SubCommand {
|
||||
|
||||
private String[] getArgumentList(PlotPlayer player) {
|
||||
List<String> args = new ArrayList<>();
|
||||
if (EconHandler.manager != null && Permissions
|
||||
.hasPermission(player, C.PERMISSION_LIST_FORSALE)) {
|
||||
args.add("forsale");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_MINE)) {
|
||||
args.add("mine");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_SHARED)) {
|
||||
args.add("shared");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_WORLD)) {
|
||||
args.add("world");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_TOP)) {
|
||||
args.add("top");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_ALL)) {
|
||||
args.add("all");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_UNOWNED)) {
|
||||
args.add("unowned");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_UNKNOWN)) {
|
||||
args.add("unknown");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_PLAYER)) {
|
||||
args.add("<player>");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_WORLD)) {
|
||||
args.add("<world>");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_DONE)) {
|
||||
args.add("done");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_EXPIRED)) {
|
||||
args.add("expired");
|
||||
}
|
||||
if (Permissions.hasPermission(player, C.PERMISSION_LIST_FUZZY)) {
|
||||
args.add("fuzzy <search...>");
|
||||
}
|
||||
return args.toArray(new String[args.size()]);
|
||||
}
|
||||
|
||||
public void noArgs(PlotPlayer player) {
|
||||
MainUtil.sendMessage(player,
|
||||
C.SUBCOMMAND_SET_OPTIONS_HEADER.s() + Arrays.toString(getArgumentList(player)));
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
if (args.length < 1) {
|
||||
noArgs(player);
|
||||
return false;
|
||||
}
|
||||
int page = 0;
|
||||
if (args.length > 1) {
|
||||
try {
|
||||
page = Integer.parseInt(args[args.length - 1]);
|
||||
--page;
|
||||
if (page < 0) {
|
||||
page = 0;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
page = -1;
|
||||
}
|
||||
}
|
||||
|
||||
List<Plot> plots = null;
|
||||
|
||||
String world = player.getLocation().getWorld();
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
String arg = args[0].toLowerCase();
|
||||
boolean sort = true;
|
||||
switch (arg) {
|
||||
case "mine":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_MINE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_MINE);
|
||||
return false;
|
||||
}
|
||||
sort = false;
|
||||
plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getBasePlots(player));
|
||||
break;
|
||||
case "shared":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_SHARED)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_SHARED);
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>();
|
||||
for (Plot plot : PlotSquared.get().getPlots()) {
|
||||
if (plot.getTrusted().contains(player.getUUID()) || plot.getMembers()
|
||||
.contains(player.getUUID())) {
|
||||
plots.add(plot);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "world":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_WORLD)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_WORLD);
|
||||
return false;
|
||||
}
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_WORLD_NAME.f(world))) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_LIST_WORLD_NAME.f(world));
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>(PlotSquared.get().getPlots(world));
|
||||
break;
|
||||
case "expired":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_EXPIRED)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_EXPIRED);
|
||||
return false;
|
||||
}
|
||||
plots = ExpireManager.IMP == null ?
|
||||
new ArrayList<Plot>() :
|
||||
new ArrayList<>(ExpireManager.IMP.getPendingExpired());
|
||||
break;
|
||||
case "area":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_AREA)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_AREA);
|
||||
return false;
|
||||
}
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_WORLD_NAME.f(world))) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_LIST_WORLD_NAME.f(world));
|
||||
return false;
|
||||
}
|
||||
plots = area == null ? new ArrayList<Plot>() : new ArrayList<>(area.getPlots());
|
||||
break;
|
||||
case "all":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_ALL)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_ALL);
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>(PlotSquared.get().getPlots());
|
||||
break;
|
||||
case "done":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_DONE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_DONE);
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>();
|
||||
for (Plot plot : PlotSquared.get().getPlots()) {
|
||||
Optional<String> flag = plot.getFlag(Flags.DONE);
|
||||
if (flag.isPresent()) {
|
||||
plots.add(plot);
|
||||
}
|
||||
}
|
||||
Collections.sort(plots, new Comparator<Plot>() {
|
||||
@Override public int compare(Plot a, Plot b) {
|
||||
String va = "" + a.getFlags().get(Flags.DONE);
|
||||
String vb = "" + b.getFlags().get(Flags.DONE);
|
||||
if (MathMan.isInteger(va)) {
|
||||
if (MathMan.isInteger(vb)) {
|
||||
return Integer.parseInt(vb) - Integer.parseInt(va);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
sort = false;
|
||||
break;
|
||||
case "top":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_TOP)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_TOP);
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>(PlotSquared.get().getPlots());
|
||||
Collections.sort(plots, new Comparator<Plot>() {
|
||||
@Override public int compare(Plot p1, Plot p2) {
|
||||
double v1 = 0;
|
||||
int p1s = p1.getSettings().getRatings().size();
|
||||
int p2s = p2.getRatings().size();
|
||||
if (!p1.getSettings().getRatings().isEmpty()) {
|
||||
for (Entry<UUID, Rating> entry : p1.getRatings().entrySet()) {
|
||||
double av = entry.getValue().getAverageRating();
|
||||
v1 += av * av;
|
||||
}
|
||||
v1 /= p1s;
|
||||
v1 += p1s;
|
||||
}
|
||||
double v2 = 0;
|
||||
if (!p2.getSettings().getRatings().isEmpty()) {
|
||||
for (Entry<UUID, Rating> entry : p2.getRatings().entrySet()) {
|
||||
double av = entry.getValue().getAverageRating();
|
||||
v2 += av * av;
|
||||
}
|
||||
v2 /= p2s;
|
||||
v2 += p2s;
|
||||
}
|
||||
if (v2 == v1 && v2 != 0) {
|
||||
return p2s - p1s;
|
||||
}
|
||||
return (int) Math.signum(v2 - v1);
|
||||
}
|
||||
});
|
||||
sort = false;
|
||||
break;
|
||||
case "forsale":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_FORSALE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_FORSALE);
|
||||
return false;
|
||||
}
|
||||
if (EconHandler.manager == null) {
|
||||
break;
|
||||
}
|
||||
plots = new ArrayList<>();
|
||||
for (Plot plot : PlotSquared.get().getPlots()) {
|
||||
Optional<Double> price = plot.getFlag(Flags.PRICE);
|
||||
if (price.isPresent()) {
|
||||
plots.add(plot);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "unowned":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_UNOWNED)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>();
|
||||
for (Plot plot : PlotSquared.get().getPlots()) {
|
||||
if (plot.owner == null) {
|
||||
plots.add(plot);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "unknown":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_UNKNOWN)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_UNKNOWN);
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>();
|
||||
for (Plot plot : PlotSquared.get().getPlots()) {
|
||||
if (plot.owner == null) {
|
||||
continue;
|
||||
}
|
||||
if (UUIDHandler.getName(plot.owner) == null) {
|
||||
plots.add(plot);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "fuzzy":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_FUZZY)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_FUZZY);
|
||||
return false;
|
||||
}
|
||||
if (args.length < (page == -1 ? 2 : 3)) {
|
||||
C.COMMAND_SYNTAX.send(player, "/plot list fuzzy <search...> [#]");
|
||||
return false;
|
||||
}
|
||||
String term;
|
||||
if (MathMan.isInteger(args[args.length - 1])) {
|
||||
term = StringMan.join(Arrays.copyOfRange(args, 1, args.length - 1), " ");
|
||||
} else {
|
||||
term = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " ");
|
||||
}
|
||||
plots = MainUtil.getPlotsBySearch(term);
|
||||
sort = false;
|
||||
break;
|
||||
default:
|
||||
if (PlotSquared.get().hasPlotArea(args[0])) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_WORLD)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_WORLD);
|
||||
return false;
|
||||
}
|
||||
if (!Permissions
|
||||
.hasPermission(player, C.PERMISSION_LIST_WORLD_NAME.f(args[0]))) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_LIST_WORLD_NAME.f(args[0]));
|
||||
return false;
|
||||
}
|
||||
plots = new ArrayList<>(PlotSquared.get().getPlots(args[0]));
|
||||
break;
|
||||
}
|
||||
UUID uuid = UUIDHandler.getUUID(args[0], null);
|
||||
if (uuid == null) {
|
||||
try {
|
||||
uuid = UUID.fromString(args[0]);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
if (uuid != null) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_LIST_PLAYER)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_LIST_PLAYER);
|
||||
return false;
|
||||
}
|
||||
sort = false;
|
||||
plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getPlots(uuid));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (plots == null) {
|
||||
sendMessage(player, C.DID_YOU_MEAN,
|
||||
new StringComparison<>(args[0], new String[] {"mine", "shared", "world", "all"})
|
||||
.getBestMatch());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plots.isEmpty()) {
|
||||
MainUtil.sendMessage(player, C.FOUND_NO_PLOTS);
|
||||
return false;
|
||||
}
|
||||
displayPlots(player, plots, 12, page, area, args, sort);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void displayPlots(final PlotPlayer player, List<Plot> plots, int pageSize, int page,
|
||||
PlotArea area, String[] args, boolean sort) {
|
||||
// Header
|
||||
Iterator<Plot> iterator = plots.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (!iterator.next().isBasePlot()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (sort) {
|
||||
plots = PlotSquared.get().sortPlots(plots, SortType.CREATION_DATE, area);
|
||||
}
|
||||
this.paginate(player, plots, pageSize, page,
|
||||
new RunnableVal3<Integer, Plot, PlotMessage>() {
|
||||
@Override public void run(Integer i, Plot plot, PlotMessage message) {
|
||||
String color;
|
||||
if (plot.owner == null) {
|
||||
color = "$3";
|
||||
} else if (plot.isOwner(player.getUUID())) {
|
||||
color = "$1";
|
||||
} else if (plot.isAdded(player.getUUID())) {
|
||||
color = "$4";
|
||||
} else if (plot.isDenied(player.getUUID())) {
|
||||
color = "$2";
|
||||
} else {
|
||||
color = "$1";
|
||||
}
|
||||
PlotMessage trusted = new PlotMessage().text(C.color(C.PLOT_INFO_TRUSTED.s()
|
||||
.replaceAll("%trusted%", MainUtil.getPlayerList(plot.getTrusted()))))
|
||||
.color("$1");
|
||||
PlotMessage members = new PlotMessage().text(C.color(C.PLOT_INFO_MEMBERS.s()
|
||||
.replaceAll("%members%", MainUtil.getPlayerList(plot.getMembers()))))
|
||||
.color("$1");
|
||||
String strFlags = StringMan.join(plot.getFlags().values(), ",");
|
||||
if (strFlags.isEmpty()) {
|
||||
strFlags = C.NONE.s();
|
||||
}
|
||||
PlotMessage flags = new PlotMessage()
|
||||
.text(C.color(C.PLOT_INFO_FLAGS.s().replaceAll("%flags%", strFlags)))
|
||||
.color("$1");
|
||||
message.text("[").color("$3").text(i + "")
|
||||
.command("/plot visit " + plot.getArea() + ";" + plot.getId())
|
||||
.tooltip("/plot visit " + plot.getArea() + ";" + plot.getId()).color("$1")
|
||||
.text("]").color("$3").text(" " + plot.toString())
|
||||
.tooltip(trusted, members, flags)
|
||||
.command("/plot info " + plot.getArea() + ";" + plot.getId()).color(color)
|
||||
.text(" - ").color("$2");
|
||||
String prefix = "";
|
||||
for (UUID uuid : plot.getOwners()) {
|
||||
String name = UUIDHandler.getName(uuid);
|
||||
if (name == null) {
|
||||
message = message.text(prefix).color("$4").text("unknown").color("$2")
|
||||
.tooltip(uuid.toString()).suggest(uuid.toString());
|
||||
} else {
|
||||
PlotPlayer pp = UUIDHandler.getPlayer(uuid);
|
||||
if (pp != null) {
|
||||
message = message.text(prefix).color("$4").text(name).color("$1")
|
||||
.tooltip(new PlotMessage("Online").color("$4"));
|
||||
} else {
|
||||
message = message.text(prefix).color("$4").text(name).color("$1")
|
||||
.tooltip(new PlotMessage("Offline").color("$3"));
|
||||
}
|
||||
}
|
||||
prefix = ", ";
|
||||
}
|
||||
}
|
||||
}, "/plot list " + args[0], C.PLOT_LIST_HEADER_PAGED.s());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.schematic.Schematic;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
@CommandDeclaration(command = "load", aliases = {"restore"}, category = CommandCategory.SCHEMATIC,
|
||||
requiredType = RequiredType.NONE, description = "Load your plot", permission = "plots.load",
|
||||
usage = "/plot load") public class Load extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
String world = player.getLocation().getWorld();
|
||||
if (!PlotSquared.get().hasPlotArea(world)) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT_WORLD);
|
||||
}
|
||||
final Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_LOAD)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length != 0) {
|
||||
if (args.length == 1) {
|
||||
List<String> schematics = player.getMeta("plot_schematics");
|
||||
if (schematics == null) {
|
||||
// No schematics found:
|
||||
MainUtil.sendMessage(player, C.LOAD_NULL);
|
||||
return false;
|
||||
}
|
||||
String schem;
|
||||
try {
|
||||
schem = schematics.get(Integer.parseInt(args[0]) - 1);
|
||||
} catch (Exception ignored) {
|
||||
// use /plot load <index>
|
||||
MainUtil
|
||||
.sendMessage(player, C.NOT_VALID_NUMBER, "(1, " + schematics.size() + ')');
|
||||
return false;
|
||||
}
|
||||
final URL url;
|
||||
try {
|
||||
url = new URL(Settings.Web.URL + "saves/" + player.getUUID() + '/' + schem);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
MainUtil.sendMessage(player, C.LOAD_FAILED);
|
||||
return false;
|
||||
}
|
||||
plot.addRunning();
|
||||
MainUtil.sendMessage(player, C.GENERATING_COMPONENT);
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
Schematic schematic = SchematicHandler.manager.getSchematic(url);
|
||||
if (schematic == null) {
|
||||
plot.removeRunning();
|
||||
sendMessage(player, C.SCHEMATIC_INVALID,
|
||||
"non-existent or not in gzip format");
|
||||
return;
|
||||
}
|
||||
PlotArea area = plot.getArea();
|
||||
SchematicHandler.manager
|
||||
.paste(schematic, plot, 0, area.MIN_BUILD_HEIGHT, 0, false,
|
||||
new RunnableVal<Boolean>() {
|
||||
@Override public void run(Boolean value) {
|
||||
plot.removeRunning();
|
||||
if (value) {
|
||||
sendMessage(player, C.SCHEMATIC_PASTE_SUCCESS);
|
||||
} else {
|
||||
sendMessage(player, C.SCHEMATIC_PASTE_FAILED);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
plot.removeRunning();
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot load <index>");
|
||||
return false;
|
||||
}
|
||||
|
||||
// list schematics
|
||||
|
||||
List<String> schematics = player.getMeta("plot_schematics");
|
||||
if (schematics == null) {
|
||||
plot.addRunning();
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
List<String> schematics1 = SchematicHandler.manager.getSaves(player.getUUID());
|
||||
plot.removeRunning();
|
||||
if ((schematics1 == null) || schematics1.isEmpty()) {
|
||||
MainUtil.sendMessage(player, C.LOAD_FAILED);
|
||||
return;
|
||||
}
|
||||
player.setMeta("plot_schematics", schematics1);
|
||||
displaySaves(player);
|
||||
});
|
||||
} else {
|
||||
displaySaves(player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void displaySaves(PlotPlayer player) {
|
||||
List<String> schematics = player.getMeta("plot_schematics");
|
||||
for (int i = 0; i < Math.min(schematics.size(), 32); i++) {
|
||||
try {
|
||||
String schematic = schematics.get(i).split("\\.")[0];
|
||||
String[] split = schematic.split("_");
|
||||
if (split.length < 5) {
|
||||
continue;
|
||||
}
|
||||
String time =
|
||||
secToTime((System.currentTimeMillis() / 1000) - Long.parseLong(split[0]));
|
||||
String world = split[1];
|
||||
PlotId id = PlotId.fromString(split[2] + ';' + split[3]);
|
||||
String size = split[4];
|
||||
String color = "$4";
|
||||
MainUtil.sendMessage(player,
|
||||
"$3[$2" + (i + 1) + "$3] " + color + time + "$3 | " + color + world + ';' + id
|
||||
+ "$3 | " + color + size + 'x' + size);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player, C.LOAD_LIST);
|
||||
}
|
||||
|
||||
public String secToTime(long time) {
|
||||
StringBuilder toreturn = new StringBuilder();
|
||||
if (time >= 33868800) {
|
||||
int years = (int) (time / 33868800);
|
||||
time -= years * 33868800;
|
||||
toreturn.append(years).append("y ");
|
||||
}
|
||||
if (time >= 604800) {
|
||||
int weeks = (int) (time / 604800);
|
||||
time -= weeks * 604800;
|
||||
toreturn.append(weeks).append("w ");
|
||||
}
|
||||
if (time >= 86400) {
|
||||
int days = (int) (time / 86400);
|
||||
time -= days * 86400;
|
||||
toreturn.append(days).append("d ");
|
||||
}
|
||||
if (time >= 3600) {
|
||||
int hours = (int) (time / 3600);
|
||||
time -= hours * 3600;
|
||||
toreturn.append(hours).append("h ");
|
||||
}
|
||||
if (time >= 60) {
|
||||
int minutes = (int) (time / 60);
|
||||
time -= minutes * 60;
|
||||
toreturn.append(minutes).append("m ");
|
||||
}
|
||||
if (toreturn.length() == 0 || (time > 0)) {
|
||||
toreturn.append(time).append("s ");
|
||||
}
|
||||
return toreturn.toString().trim();
|
||||
}
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.CmdConfirm;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.EconHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* PlotSquared command class.
|
||||
*/
|
||||
@CommandDeclaration(command = "plot",
|
||||
aliases = {"plots", "p", "plotsquared", "plot2", "p2", "ps", "2", "plotme", "plotz", "ap"})
|
||||
public class MainCommand extends Command {
|
||||
|
||||
private static MainCommand instance;
|
||||
public Help help;
|
||||
public Toggle toggle;
|
||||
|
||||
private MainCommand() {
|
||||
super(null, true);
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static MainCommand getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new MainCommand();
|
||||
new Buy();
|
||||
new Save();
|
||||
new Load();
|
||||
new Confirm();
|
||||
new Template();
|
||||
new Download();
|
||||
new Template();
|
||||
new Setup();
|
||||
new Area();
|
||||
new DebugSaveTest();
|
||||
new DebugLoadTest();
|
||||
new CreateRoadSchematic();
|
||||
new DebugAllowUnsafe();
|
||||
new RegenAllRoads();
|
||||
new Claim();
|
||||
new Auto();
|
||||
new Visit();
|
||||
new Set();
|
||||
new Clear();
|
||||
new Delete();
|
||||
new Trust();
|
||||
new Add();
|
||||
new Leave();
|
||||
new Deny();
|
||||
new Remove();
|
||||
new Info();
|
||||
new Near();
|
||||
new ListCmd();
|
||||
new Debug();
|
||||
new SchematicCmd();
|
||||
new PluginCmd();
|
||||
new Purge();
|
||||
new Reload();
|
||||
new Relight();
|
||||
new Merge();
|
||||
new DebugPaste();
|
||||
new Unlink();
|
||||
new Kick();
|
||||
new Rate();
|
||||
new DebugClaimTest();
|
||||
new Inbox();
|
||||
new Comment();
|
||||
new Database();
|
||||
new Swap();
|
||||
new Music();
|
||||
new DebugRoadRegen();
|
||||
new Trust();
|
||||
new DebugExec();
|
||||
new FlagCmd();
|
||||
new Target();
|
||||
new DebugFixFlags();
|
||||
new Move();
|
||||
new Condense();
|
||||
new Copy();
|
||||
new Chat();
|
||||
new Trim();
|
||||
new Done();
|
||||
new Continue();
|
||||
new Middle();
|
||||
new Grant();
|
||||
// Set commands
|
||||
new Owner();
|
||||
new Desc();
|
||||
new Biome();
|
||||
new Alias();
|
||||
new SetHome();
|
||||
new Cluster();
|
||||
new DebugImportWorlds();
|
||||
// Referenced commands
|
||||
instance.toggle = new Toggle();
|
||||
instance.help = new Help(instance);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean onCommand(final PlotPlayer player, String... args) {
|
||||
if (args.length >= 1 && args[0].contains(":")) {
|
||||
String[] split2 = args[0].split(":");
|
||||
if (split2.length == 2) {
|
||||
// Ref: c:v, this will push value to the last spot in the array
|
||||
// ex. /p h:2 SomeUsername
|
||||
// > /p h SomeUsername 2
|
||||
String[] tmp = new String[args.length + 1];
|
||||
tmp[0] = split2[0];
|
||||
tmp[args.length] = split2[1];
|
||||
if (args.length >= 2) {
|
||||
System.arraycopy(args, 1, tmp, 1, args.length - 1);
|
||||
}
|
||||
args = tmp;
|
||||
}
|
||||
}
|
||||
try {
|
||||
getInstance().execute(player, args, new RunnableVal3<Command, Runnable, Runnable>() {
|
||||
@Override
|
||||
public void run(final Command cmd, final Runnable success, final Runnable failure) {
|
||||
if (cmd.hasConfirmation(player)) {
|
||||
CmdConfirm.addPending(player, cmd.getUsage(), new Runnable() {
|
||||
@Override public void run() {
|
||||
if (EconHandler.manager != null) {
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area != null) {
|
||||
Expression<Double> priceEval =
|
||||
area.PRICES.get(cmd.getFullId());
|
||||
Double price =
|
||||
priceEval != null ? priceEval.evaluate(0d) : 0d;
|
||||
if (price != null
|
||||
&& EconHandler.manager.getMoney(player) < price) {
|
||||
if (failure != null) {
|
||||
failure.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (EconHandler.manager != null) {
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area != null) {
|
||||
Expression<Double> priceEval = area.PRICES.get(cmd.getFullId());
|
||||
Double price = priceEval != null ? priceEval.evaluate(0d) : 0d;
|
||||
if (price != 0d && EconHandler.manager.getMoney(player) < price) {
|
||||
if (failure != null) {
|
||||
failure.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
}
|
||||
}, new RunnableVal2<Command, CommandResult>() {
|
||||
@Override public void run(Command cmd, CommandResult result) {
|
||||
// Post command stuff!?
|
||||
}
|
||||
});
|
||||
} catch (CommandException e) {
|
||||
e.perform(player);
|
||||
}
|
||||
// Always true
|
||||
return true;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @Deprecated legacy
|
||||
*/ public void addCommand(SubCommand command) {
|
||||
PlotSquared.debug("Command registration is now done during instantiation");
|
||||
}
|
||||
|
||||
@Override public void execute(final PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) {
|
||||
// Clear perm caching //
|
||||
player.deleteMeta("perm");
|
||||
// Optional command scope //
|
||||
Location loc = null;
|
||||
Plot plot = null;
|
||||
boolean tp = false;
|
||||
if (args.length >= 2) {
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
Plot newPlot = Plot.fromString(area, args[0]);
|
||||
if (newPlot != null && (player instanceof ConsolePlayer || newPlot.getArea()
|
||||
.equals(area) || Permissions.hasPermission(player, C.PERMISSION_ADMIN)) && !newPlot
|
||||
.isDenied(player.getUUID())) {
|
||||
Location newLoc = newPlot.getCenter();
|
||||
if (player.canTeleport(newLoc)) {
|
||||
// Save meta
|
||||
loc = player.getMeta(PlotPlayer.META_LOCATION);
|
||||
plot = player.getMeta(PlotPlayer.META_LAST_PLOT);
|
||||
tp = true;
|
||||
// Set loc
|
||||
player.setMeta(PlotPlayer.META_LOCATION, newLoc);
|
||||
player.setMeta(PlotPlayer.META_LAST_PLOT, newPlot);
|
||||
} else {
|
||||
C.BORDER.send(player);
|
||||
}
|
||||
// Trim command
|
||||
args = Arrays.copyOfRange(args, 1, args.length);
|
||||
}
|
||||
if (args.length >= 2 && !args[0].isEmpty() && args[0].charAt(0) == '-') {
|
||||
switch (args[0].substring(1)) {
|
||||
case "f":
|
||||
confirm = new RunnableVal3<Command, Runnable, Runnable>() {
|
||||
@Override
|
||||
public void run(Command cmd, Runnable success, Runnable failure) {
|
||||
if (EconHandler.manager != null) {
|
||||
PlotArea area = player.getApplicablePlotArea();
|
||||
if (area != null) {
|
||||
Expression<Double> priceEval =
|
||||
area.PRICES.get(cmd.getFullId());
|
||||
Double price =
|
||||
priceEval != null ? priceEval.evaluate(0d) : 0d;
|
||||
if (price != 0d
|
||||
&& EconHandler.manager.getMoney(player) < price) {
|
||||
if (failure != null) {
|
||||
failure.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
args = Arrays.copyOfRange(args, 1, args.length);
|
||||
break;
|
||||
default:
|
||||
C.INVALID_COMMAND_FLAG.send(player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
super.execute(player, args, confirm, whenDone);
|
||||
} catch (CommandException e) {
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
String message = e.getLocalizedMessage();
|
||||
if (message != null) {
|
||||
C.ERROR.send(player, message);
|
||||
} else {
|
||||
C.ERROR.send(player);
|
||||
}
|
||||
}
|
||||
// Reset command scope //
|
||||
if (tp && !(player instanceof ConsolePlayer)) {
|
||||
if (loc == null) {
|
||||
player.deleteMeta(PlotPlayer.META_LOCATION);
|
||||
} else {
|
||||
player.setMeta(PlotPlayer.META_LOCATION, loc);
|
||||
}
|
||||
if (plot == null) {
|
||||
player.deleteMeta(PlotPlayer.META_LAST_PLOT);
|
||||
} else {
|
||||
player.setMeta(PlotPlayer.META_LAST_PLOT, plot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean canExecute(PlotPlayer player, boolean message) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "merge", aliases = "m",
|
||||
description = "Merge the plot you are standing on, with another plot",
|
||||
permission = "plots.merge", usage = "/plot merge <all|n|e|s|w> [removeroads]",
|
||||
category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE, confirmation = true)
|
||||
public class Merge extends SubCommand {
|
||||
|
||||
public static final String[] values = new String[] {"north", "east", "south", "west", "auto"};
|
||||
public static final String[] aliases = new String[] {"n", "e", "s", "w", "all"};
|
||||
|
||||
public static String direction(float yaw) {
|
||||
yaw = yaw / 90;
|
||||
int i = Math.round(yaw);
|
||||
switch (i) {
|
||||
case -4:
|
||||
case 0:
|
||||
case 4:
|
||||
return "SOUTH";
|
||||
case -1:
|
||||
case 3:
|
||||
return "EAST";
|
||||
case -2:
|
||||
case 2:
|
||||
return "NORTH";
|
||||
case -3:
|
||||
case 1:
|
||||
return "WEST";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocationFull();
|
||||
final Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
UUID uuid = player.getUUID();
|
||||
if (!plot.isOwner(uuid)) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_MERGE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
} else {
|
||||
uuid = plot.guessOwner();
|
||||
}
|
||||
}
|
||||
final PlotArea plotArea = plot.getArea();
|
||||
Expression<Double> priceExr =
|
||||
plotArea.PRICES.getOrDefault("merge", Expression.constant(0d));
|
||||
final int size = plot.getConnectedPlots().size();
|
||||
final double price = priceExr.evaluate((double) size);
|
||||
if (EconHandler.manager != null && plotArea.USE_ECONOMY && price > 0d
|
||||
&& EconHandler.manager.getMoney(player) < price) {
|
||||
sendMessage(player, C.CANNOT_AFFORD_MERGE, String.valueOf(price));
|
||||
return false;
|
||||
}
|
||||
final int maxSize =
|
||||
Permissions.hasPermissionRange(player, "plots.merge", Settings.Limit.MAX_PLOTS);
|
||||
if (size - 1 > maxSize) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, "plots.merge." + (size + 1));
|
||||
return false;
|
||||
}
|
||||
int direction = -1;
|
||||
if (args.length == 0) {
|
||||
switch (direction(player.getLocationFull().getYaw())) {
|
||||
case "NORTH":
|
||||
direction = 0;
|
||||
break;
|
||||
case "EAST":
|
||||
direction = 1;
|
||||
break;
|
||||
case "SOUTH":
|
||||
direction = 2;
|
||||
break;
|
||||
case "WEST":
|
||||
direction = 3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ("all".equalsIgnoreCase(args[0]) || "auto".equalsIgnoreCase(args[0])) {
|
||||
boolean terrain = true;
|
||||
if (args.length == 2) {
|
||||
terrain = "true".equalsIgnoreCase(args[1]);
|
||||
}
|
||||
if (!terrain && !Permissions.hasPermission(player, C.PERMISSION_MERGE_KEEPROAD)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_MERGE_KEEPROAD.s());
|
||||
return true;
|
||||
}
|
||||
if (plot.autoMerge(-1, maxSize, uuid, terrain)) {
|
||||
if (EconHandler.manager != null && plotArea.USE_ECONOMY && price > 0d) {
|
||||
EconHandler.manager.withdrawMoney(player, price);
|
||||
sendMessage(player, C.REMOVED_BALANCE, String.valueOf(price));
|
||||
}
|
||||
MainUtil.sendMessage(player, C.SUCCESS_MERGE);
|
||||
return true;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.NO_AVAILABLE_AUTOMERGE);
|
||||
return false;
|
||||
|
||||
}
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (args[0].equalsIgnoreCase(values[i]) || args[0].equalsIgnoreCase(aliases[i])) {
|
||||
direction = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (direction == -1) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
|
||||
"/plot merge <" + StringMan.join(values, "|") + "> [removeroads]");
|
||||
MainUtil
|
||||
.sendMessage(player, C.DIRECTION.s().replaceAll("%dir%", direction(loc.getYaw())));
|
||||
return false;
|
||||
}
|
||||
final boolean terrain;
|
||||
if (args.length == 2) {
|
||||
terrain = "true".equalsIgnoreCase(args[1]);
|
||||
} else {
|
||||
terrain = true;
|
||||
}
|
||||
if (!terrain && !Permissions.hasPermission(player, C.PERMISSION_MERGE_KEEPROAD)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_MERGE_KEEPROAD.s());
|
||||
return true;
|
||||
}
|
||||
if (plot.autoMerge(direction, maxSize - size, uuid, terrain)) {
|
||||
if (EconHandler.manager != null && plotArea.USE_ECONOMY && price > 0d) {
|
||||
EconHandler.manager.withdrawMoney(player, price);
|
||||
sendMessage(player, C.REMOVED_BALANCE, String.valueOf(price));
|
||||
}
|
||||
MainUtil.sendMessage(player, C.SUCCESS_MERGE);
|
||||
return true;
|
||||
}
|
||||
Plot adjacent = plot.getRelative(direction);
|
||||
if (adjacent == null || !adjacent.hasOwner() || adjacent.getMerged((direction + 2) % 4)
|
||||
|| adjacent.isOwner(uuid)) {
|
||||
MainUtil.sendMessage(player, C.NO_AVAILABLE_AUTOMERGE);
|
||||
return false;
|
||||
}
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_MERGE_OTHER)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_MERGE_OTHER);
|
||||
return false;
|
||||
}
|
||||
java.util.Set<UUID> uuids = adjacent.getOwners();
|
||||
boolean isOnline = false;
|
||||
for (final UUID owner : uuids) {
|
||||
final PlotPlayer accepter = UUIDHandler.getPlayer(owner);
|
||||
if (accepter == null) {
|
||||
continue;
|
||||
}
|
||||
isOnline = true;
|
||||
final int dir = direction;
|
||||
Runnable run = () -> {
|
||||
MainUtil.sendMessage(accepter, C.MERGE_ACCEPTED);
|
||||
plot.autoMerge(dir, maxSize - size, owner, terrain);
|
||||
PlotPlayer plotPlayer = UUIDHandler.getPlayer(player.getUUID());
|
||||
if (plotPlayer == null) {
|
||||
sendMessage(accepter, C.MERGE_NOT_VALID);
|
||||
return;
|
||||
}
|
||||
if (EconHandler.manager != null && plotArea.USE_ECONOMY && price > 0d) {
|
||||
if (EconHandler.manager.getMoney(player) < price) {
|
||||
sendMessage(player, C.CANNOT_AFFORD_MERGE, String.valueOf(price));
|
||||
return;
|
||||
}
|
||||
EconHandler.manager.withdrawMoney(player, price);
|
||||
sendMessage(player, C.REMOVED_BALANCE, String.valueOf(price));
|
||||
}
|
||||
MainUtil.sendMessage(player, C.SUCCESS_MERGE);
|
||||
};
|
||||
if (hasConfirmation(player)) {
|
||||
CmdConfirm.addPending(accepter,
|
||||
C.MERGE_REQUEST_CONFIRM.s().replaceAll("%s", player.getName()), run);
|
||||
} else {
|
||||
run.run();
|
||||
}
|
||||
}
|
||||
if (!isOnline) {
|
||||
MainUtil.sendMessage(player, C.NO_AVAILABLE_AUTOMERGE);
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.MERGE_REQUESTED);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
|
||||
/**
|
||||
* @author manuelgu, altered by Citymonstret
|
||||
*/
|
||||
@CommandDeclaration(command = "middle", aliases = {"center", "centre"},
|
||||
description = "Teleports you to the center of the plot", usage = "/plot middle",
|
||||
category = CommandCategory.TELEPORT, requiredType = RequiredType.NONE) public class Middle
|
||||
extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] arguments) {
|
||||
Location location = player.getLocation();
|
||||
Plot plot = location.getPlot();
|
||||
if (plot == null) {
|
||||
return sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
return sendMessage(player, C.PLOT_UNOWNED);
|
||||
}
|
||||
player.teleport(plot.getCenter());
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
|
||||
@CommandDeclaration(usage = "/plot move <X;Z>", command = "move", description = "Move a plot",
|
||||
aliases = {"debugmove"}, permission = "plots.move", category = CommandCategory.CLAIMING,
|
||||
requiredType = RequiredType.NONE) public class Move extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
Plot plot1 = loc.getPlotAbs();
|
||||
if (plot1 == null) {
|
||||
return !MainUtil.sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot1.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN.s())) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
boolean override = false;
|
||||
if (args.length == 2 && args[1].equalsIgnoreCase("-f")) {
|
||||
args = new String[] {args[0]};
|
||||
override = true;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]);
|
||||
Plot plot2;
|
||||
if (area == null) {
|
||||
plot2 = MainUtil.getPlotFromString(player, args[0], true);
|
||||
if (plot2 == null) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
plot2 = area.getPlotAbs(plot1.getId());
|
||||
}
|
||||
if (plot1.equals(plot2)) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_ID);
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot copy <X;Z>");
|
||||
return false;
|
||||
}
|
||||
if (!plot1.getArea().isCompatible(plot2.getArea()) && (!override || !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN.s()))) {
|
||||
C.PLOTWORLD_INCOMPATIBLE.send(player);
|
||||
return false;
|
||||
}
|
||||
if (plot1.move(plot2, () -> MainUtil.sendMessage(player, C.MOVE_SUCCESS), false)) {
|
||||
return true;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.REQUIRES_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
@CommandDeclaration(command = "music", permission = "plots.music",
|
||||
description = "Play music in your plot", usage = "/plot music",
|
||||
category = CommandCategory.APPEARANCE, requiredType = RequiredType.PLAYER) public class Music
|
||||
extends SubCommand {
|
||||
|
||||
private static final Collection<String> DISCS = Arrays
|
||||
.asList("music_disc_13", "music_disc_cat", "music_disc_blocks", "music_disc_chirp",
|
||||
"music_disc_far", "music_disc_mall", "music_disc_mellohi", "music_disc_stal",
|
||||
"music_disc_strad", "music_disc_ward", "music_disc_11", "music_disc_wait");
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
final Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.isAdded(player.getUUID())) {
|
||||
sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return true;
|
||||
}
|
||||
PlotInventory inv = new PlotInventory(player, 2, "Plot Jukebox") {
|
||||
@Override public boolean onClick(int index) {
|
||||
PlotItemStack item = getItem(index);
|
||||
if (item == null) {
|
||||
return true;
|
||||
}
|
||||
if (item.getPlotBlock().equalsAny(7, "bedrock")) {
|
||||
plot.removeFlag(Flags.MUSIC);
|
||||
C.FLAG_REMOVED.send(player);
|
||||
} else if (item.name.toLowerCase(Locale.ENGLISH).contains("disc")) {
|
||||
plot.setFlag(Flags.MUSIC, item.getPlotBlock().getRawId());
|
||||
C.FLAG_ADDED.send(player);
|
||||
} else {
|
||||
C.FLAG_NOT_ADDED.send(player);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
int index = 0;
|
||||
|
||||
for (final String disc : DISCS) {
|
||||
final String name = String.format("&r&6%s", disc);
|
||||
final String[] lore = {"&r&aClick to play!"};
|
||||
final PlotItemStack item = new PlotItemStack(disc, 1, name, lore);
|
||||
inv.setItem(index++, item);
|
||||
}
|
||||
|
||||
// Always add the cancel button
|
||||
// if (player.getMeta("music") != null) {
|
||||
String name = "&r&6Cancel music";
|
||||
String[] lore = {"&r&cClick to cancel!"};
|
||||
inv.setItem(index, new PlotItemStack("bedrock", 1, name, lore));
|
||||
// }
|
||||
|
||||
inv.openInventory();
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
|
||||
@CommandDeclaration(command = "near", aliases = "n", description = "Display nearby players",
|
||||
usage = "/plot near", category = CommandCategory.INFO) public class Near extends Command {
|
||||
public Near() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
|
||||
final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
|
||||
C.PLOT_NEAR.send(player, StringMan.join(plot.getPlayersInPlot(), ", "));
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "setowner", permission = "plots.set.owner",
|
||||
description = "Set the plot owner", usage = "/plot setowner <player>",
|
||||
aliases = {"owner", "so", "seto"}, category = CommandCategory.CLAIMING,
|
||||
requiredType = RequiredType.NONE, confirmation = true) public class Owner extends SetCommand {
|
||||
|
||||
@Override public boolean set(final PlotPlayer player, final Plot plot, String value) {
|
||||
Set<Plot> plots = plot.getConnectedPlots();
|
||||
UUID uuid = null;
|
||||
String name = null;
|
||||
if (value.length() == 36) {
|
||||
try {
|
||||
uuid = UUID.fromString(value);
|
||||
name = MainUtil.getName(uuid);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
} else {
|
||||
uuid = UUIDHandler.getUUID(value, null);
|
||||
name = UUIDHandler.getName(uuid);
|
||||
name = name == null ? value : name;
|
||||
}
|
||||
if (uuid == null || value.equalsIgnoreCase("-")) {
|
||||
if (value.equalsIgnoreCase("none") || value.equalsIgnoreCase("null") || value
|
||||
.equalsIgnoreCase("-")) {
|
||||
if (!Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_SETOWNER.s(), true)) {
|
||||
return false;
|
||||
}
|
||||
Set<Plot> connected = plot.getConnectedPlots();
|
||||
plot.unlinkPlot(false, false);
|
||||
for (Plot current : connected) {
|
||||
current.unclaim();
|
||||
current.removeSign();
|
||||
}
|
||||
MainUtil.sendMessage(player, C.SET_OWNER);
|
||||
return true;
|
||||
}
|
||||
C.INVALID_PLAYER.send(player, value);
|
||||
return false;
|
||||
}
|
||||
final PlotPlayer other = UUIDHandler.getPlayer(uuid);
|
||||
if (plot.isOwner(uuid)) {
|
||||
C.ALREADY_OWNER.send(player, MainUtil.getName(uuid));
|
||||
return false;
|
||||
}
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_SETOWNER)) {
|
||||
if (other == null) {
|
||||
C.INVALID_PLAYER_OFFLINE.send(player, value);
|
||||
return false;
|
||||
}
|
||||
int size = plots.size();
|
||||
int currentPlots = (Settings.Limit.GLOBAL ?
|
||||
other.getPlotCount() :
|
||||
other.getPlotCount(plot.getWorldName())) + size;
|
||||
if (currentPlots > other.getAllowedPlots()) {
|
||||
sendMessage(player, C.CANT_TRANSFER_MORE_PLOTS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final String finalName = name;
|
||||
final UUID finalUUID = uuid;
|
||||
final boolean removeDenied = plot.isDenied(finalUUID);
|
||||
Runnable run = new Runnable() {
|
||||
@Override public void run() {
|
||||
if (plot.setOwner(finalUUID, player)) {
|
||||
if (removeDenied)
|
||||
plot.removeDenied(finalUUID);
|
||||
plot.setSign(finalName);
|
||||
MainUtil.sendMessage(player, C.SET_OWNER);
|
||||
if (other != null) {
|
||||
MainUtil
|
||||
.sendMessage(other, C.NOW_OWNER, plot.getArea() + ";" + plot.getId());
|
||||
}
|
||||
} else
|
||||
MainUtil.sendMessage(player, C.SET_OWNER_CANCELLED);
|
||||
}
|
||||
};
|
||||
if (hasConfirmation(player)) {
|
||||
CmdConfirm.addPending(player, "/plot set owner " + value, run);
|
||||
} else {
|
||||
TaskManager.runTask(run);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.json.JSONObject;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.HttpUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
|
||||
@CommandDeclaration(command = "plugin", permission = "plots.use",
|
||||
description = "Show plugin information", usage = "/plot plugin", aliases = "version",
|
||||
category = CommandCategory.INFO) public class PluginCmd extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
TaskManager.IMP.taskAsync(new Runnable() {
|
||||
@Override public void run() {
|
||||
MainUtil.sendMessage(player, String.format(
|
||||
"$2>> $1&l" + PlotSquared.imp().getPluginName() + " $2($1Version$2: $1%s$2)",
|
||||
PlotSquared.get().getVersion()));
|
||||
MainUtil.sendMessage(player,
|
||||
"$2>> $1&lAuthors$2: $1Citymonstret $2& $1Empire92 $2& $1MattBDev $2& $1dordsor21");
|
||||
MainUtil.sendMessage(player,
|
||||
"$2>> $1&lWiki$2: $1https://github.com/IntellectualCrafters/PlotSquared/wiki");
|
||||
MainUtil.sendMessage(player,
|
||||
"$2>> $1&lNewest Version$2: $1" + getNewestVersionString());
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getNewestVersionString() {
|
||||
String str = HttpUtil
|
||||
.readUrl("https://api.github.com/repos/IntellectualSites/PlotSquared/releases/latest");
|
||||
JSONObject release = new JSONObject(str);
|
||||
return release.getString("name");
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.listener.PlotListener;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.CmdConfirm;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(
|
||||
usage = "/plot purge world:<world> area:<area> id:<id> owner:<owner> shared:<shared> unknown:[true|false]",
|
||||
command = "purge", permission = "plots.admin", description = "Purge all plots for a world",
|
||||
category = CommandCategory.ADMINISTRATION, requiredType = RequiredType.CONSOLE,
|
||||
confirmation = true) public class Purge extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
if (args.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String world = null;
|
||||
PlotArea area = null;
|
||||
PlotId id = null;
|
||||
UUID owner = null;
|
||||
UUID added = null;
|
||||
boolean unknown = false;
|
||||
for (String arg : args) {
|
||||
String[] split = arg.split(":");
|
||||
if (split.length != 2) {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
switch (split[0].toLowerCase()) {
|
||||
case "world":
|
||||
case "w":
|
||||
world = split[1];
|
||||
break;
|
||||
case "area":
|
||||
case "a":
|
||||
area = PlotSquared.get().getPlotAreaByString(split[1]);
|
||||
if (area == null) {
|
||||
C.NOT_VALID_PLOT_WORLD.send(player, split[1]);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case "plotid":
|
||||
case "id":
|
||||
id = PlotId.fromString(split[1]);
|
||||
if (id == null) {
|
||||
C.NOT_VALID_PLOT_ID.send(player, split[1]);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case "owner":
|
||||
case "o":
|
||||
owner = UUIDHandler.getUUID(split[1], null);
|
||||
if (owner == null) {
|
||||
C.INVALID_PLAYER.send(player, split[1]);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case "shared":
|
||||
case "s":
|
||||
added = UUIDHandler.getUUID(split[1], null);
|
||||
if (added == null) {
|
||||
C.INVALID_PLAYER.send(player, split[1]);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case "unknown":
|
||||
case "?":
|
||||
case "u":
|
||||
unknown = Boolean.parseBoolean(split[1]);
|
||||
break;
|
||||
default:
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final HashSet<Plot> toDelete = new HashSet<>();
|
||||
for (Plot plot : PlotSquared.get().getBasePlots()) {
|
||||
if (world != null && !plot.getWorldName().equalsIgnoreCase(world)) {
|
||||
continue;
|
||||
}
|
||||
if (area != null && !plot.getArea().equals(area)) {
|
||||
continue;
|
||||
}
|
||||
if (id != null && !plot.getId().equals(id)) {
|
||||
continue;
|
||||
}
|
||||
if (owner != null && !plot.isOwner(owner)) {
|
||||
continue;
|
||||
}
|
||||
if (added != null && !plot.isAdded(added)) {
|
||||
continue;
|
||||
}
|
||||
if (unknown && UUIDHandler.getName(plot.owner) != null) {
|
||||
continue;
|
||||
}
|
||||
toDelete.addAll(plot.getConnectedPlots());
|
||||
}
|
||||
if (PlotSquared.get().plots_tmp != null) {
|
||||
for (Entry<String, HashMap<PlotId, Plot>> entry : PlotSquared.get().plots_tmp
|
||||
.entrySet()) {
|
||||
String worldName = entry.getKey();
|
||||
if (world != null && !world.equalsIgnoreCase(worldName)) {
|
||||
continue;
|
||||
}
|
||||
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
|
||||
Plot plot = entry2.getValue();
|
||||
if (id != null && !plot.getId().equals(id)) {
|
||||
continue;
|
||||
}
|
||||
if (owner != null && !plot.isOwner(owner)) {
|
||||
continue;
|
||||
}
|
||||
if (added != null && !plot.isAdded(added)) {
|
||||
continue;
|
||||
}
|
||||
if (unknown && UUIDHandler.getName(plot.owner) != null) {
|
||||
continue;
|
||||
}
|
||||
toDelete.add(plot);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toDelete.isEmpty()) {
|
||||
C.FOUND_NO_PLOTS.send(player);
|
||||
return false;
|
||||
}
|
||||
String cmd =
|
||||
"/plot purge " + StringMan.join(args, " ") + " (" + toDelete.size() + " plots)";
|
||||
Runnable run = () -> {
|
||||
PlotSquared.debug("Calculating plots to purge, please wait...");
|
||||
HashSet<Integer> ids = new HashSet<>();
|
||||
for (Plot plot : toDelete) {
|
||||
if (plot.temp != Integer.MAX_VALUE) {
|
||||
ids.add(plot.temp);
|
||||
plot.getArea().removePlot(plot.getId());
|
||||
for (PlotPlayer pp : plot.getPlayersInPlot()) {
|
||||
PlotListener.plotEntry(pp, plot);
|
||||
}
|
||||
plot.removeSign();
|
||||
}
|
||||
}
|
||||
DBFunc.purgeIds(ids);
|
||||
C.PURGE_SUCCESS.send(player, ids.size() + "/" + toDelete.size());
|
||||
};
|
||||
if (hasConfirmation(player)) {
|
||||
CmdConfirm.addPending(player, cmd, run);
|
||||
} else {
|
||||
run.run();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "rate", permission = "plots.rate", description = "Rate the plot",
|
||||
usage = "/plot rate [#|next|purge]", aliases = "rt", category = CommandCategory.INFO,
|
||||
requiredType = RequiredType.NONE) public class Rate extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
if (args.length == 1) {
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "next": {
|
||||
ArrayList<Plot> plots = new ArrayList<>(PlotSquared.get().getBasePlots());
|
||||
plots.sort((p1, p2) -> {
|
||||
double v1 = 0;
|
||||
if (!p1.getRatings().isEmpty()) {
|
||||
for (Entry<UUID, Rating> entry : p1.getRatings().entrySet()) {
|
||||
v1 -= 11 - entry.getValue().getAverageRating();
|
||||
}
|
||||
}
|
||||
double v2 = 0;
|
||||
if (!p2.getRatings().isEmpty()) {
|
||||
for (Entry<UUID, Rating> entry : p2.getRatings().entrySet()) {
|
||||
v2 -= 11 - entry.getValue().getAverageRating();
|
||||
}
|
||||
}
|
||||
if (v1 == v2) {
|
||||
return -0;
|
||||
}
|
||||
return v2 > v1 ? 1 : -1;
|
||||
});
|
||||
UUID uuid = player.getUUID();
|
||||
for (Plot p : plots) {
|
||||
if ((!Settings.Done.REQUIRED_FOR_RATINGS || p.hasFlag(Flags.DONE)) && p
|
||||
.isBasePlot() && (!p.getRatings().containsKey(uuid)) && !p
|
||||
.isAdded(uuid)) {
|
||||
p.teleportPlayer(player);
|
||||
MainUtil.sendMessage(player, C.RATE_THIS);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player, C.FOUND_NO_PLOTS);
|
||||
return false;
|
||||
}
|
||||
case "purge": {
|
||||
final Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_RATE, true)) {
|
||||
return false;
|
||||
}
|
||||
plot.clearRatings();
|
||||
C.RATINGS_PURGED.send(player);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
final Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
sendMessage(player, C.RATING_NOT_OWNED);
|
||||
return false;
|
||||
}
|
||||
if (plot.isOwner(player.getUUID())) {
|
||||
sendMessage(player, C.RATING_NOT_YOUR_OWN);
|
||||
return false;
|
||||
}
|
||||
if (Settings.Done.REQUIRED_FOR_RATINGS && !plot.hasFlag(Flags.DONE)) {
|
||||
sendMessage(player, C.RATING_NOT_DONE);
|
||||
return false;
|
||||
}
|
||||
if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES.isEmpty()) {
|
||||
final Runnable run = new Runnable() {
|
||||
@Override public void run() {
|
||||
if (plot.getRatings().containsKey(player.getUUID())) {
|
||||
sendMessage(player, C.RATING_ALREADY_EXISTS, plot.getId().toString());
|
||||
return;
|
||||
}
|
||||
final MutableInt index = new MutableInt(0);
|
||||
final MutableInt rating = new MutableInt(0);
|
||||
String title = Settings.Ratings.CATEGORIES.get(0);
|
||||
PlotInventory inventory = new PlotInventory(player, 1, title) {
|
||||
@Override public boolean onClick(int i) {
|
||||
rating.add((i + 1) * Math.pow(10, index.getValue()));
|
||||
index.increment();
|
||||
if (index.getValue() >= Settings.Ratings.CATEGORIES.size()) {
|
||||
int rV = rating.getValue();
|
||||
Rating result =
|
||||
EventUtil.manager.callRating(this.player, plot, new Rating(rV));
|
||||
if (result != null) {
|
||||
plot.addRating(this.player.getUUID(), result);
|
||||
sendMessage(this.player, C.RATING_APPLIED,
|
||||
plot.getId().toString());
|
||||
if (Permissions
|
||||
.hasPermission(this.player, C.PERMISSION_COMMENT)) {
|
||||
Command command =
|
||||
MainCommand.getInstance().getCommand(Comment.class);
|
||||
if (command != null) {
|
||||
MainUtil.sendMessage(this.player, C.COMMENT_THIS,
|
||||
command.getUsage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
setTitle(Settings.Ratings.CATEGORIES.get(index.getValue()));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
inventory.setItem(0, new PlotItemStack("minecraft:brown_wool", 0, "0/8"));
|
||||
inventory.setItem(1, new PlotItemStack(35, (short) 14, 1, "1/8"));
|
||||
inventory.setItem(2, new PlotItemStack(35, (short) 1, 2, "2/8"));
|
||||
inventory.setItem(3, new PlotItemStack(35, (short) 4, 3, "3/8"));
|
||||
inventory.setItem(4, new PlotItemStack(35, (short) 5, 4, "4/8"));
|
||||
inventory.setItem(5, new PlotItemStack(35, (short) 9, 5, "5/8"));
|
||||
inventory.setItem(6, new PlotItemStack(35, (short) 11, 6, "6/8"));
|
||||
inventory.setItem(7, new PlotItemStack(35, (short) 10, 7, "7/8"));
|
||||
inventory.setItem(8, new PlotItemStack(35, (short) 2, 8, "8/8"));
|
||||
inventory.openInventory();
|
||||
}
|
||||
};
|
||||
if (plot.getSettings().ratings == null) {
|
||||
if (!Settings.Enabled_Components.RATING_CACHE) {
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
plot.getSettings().ratings = DBFunc.getRatings(plot);
|
||||
run.run();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
plot.getSettings().ratings = new HashMap<>();
|
||||
}
|
||||
run.run();
|
||||
return true;
|
||||
}
|
||||
if (args.length < 1) {
|
||||
sendMessage(player, C.RATING_NOT_VALID);
|
||||
return true;
|
||||
}
|
||||
String arg = args[0];
|
||||
final int rating;
|
||||
if (MathMan.isInteger(arg) && arg.length() < 3 && !arg.isEmpty()) {
|
||||
rating = Integer.parseInt(arg);
|
||||
if (rating > 10 || rating < 1) {
|
||||
sendMessage(player, C.RATING_NOT_VALID);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
sendMessage(player, C.RATING_NOT_VALID);
|
||||
return false;
|
||||
}
|
||||
final UUID uuid = player.getUUID();
|
||||
final Runnable run = () -> {
|
||||
if (plot.getRatings().containsKey(uuid)) {
|
||||
sendMessage(player, C.RATING_ALREADY_EXISTS, plot.getId().toString());
|
||||
return;
|
||||
}
|
||||
Rating result = EventUtil.manager.callRating(player, plot, new Rating(rating));
|
||||
if (result != null) {
|
||||
plot.addRating(uuid, result);
|
||||
sendMessage(player, C.RATING_APPLIED, plot.getId().toString());
|
||||
}
|
||||
};
|
||||
if (plot.getSettings().ratings == null) {
|
||||
if (!Settings.Enabled_Components.RATING_CACHE) {
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
plot.getSettings().ratings = DBFunc.getRatings(plot);
|
||||
run.run();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
plot.getSettings().ratings = new HashMap<>();
|
||||
}
|
||||
run.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
private class MutableInt {
|
||||
|
||||
private int value;
|
||||
|
||||
MutableInt(int i) {
|
||||
this.value = i;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
this.value++;
|
||||
}
|
||||
|
||||
void decrement() {
|
||||
this.value--;
|
||||
}
|
||||
|
||||
int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
void add(Number v) {
|
||||
this.value += v.intValue();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridPlotManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
@CommandDeclaration(command = "regenallroads",
|
||||
description = "Regenerate all roads in the map using the set road schematic",
|
||||
aliases = {"rgar"}, usage = "/plot regenallroads <world> [height]",
|
||||
category = CommandCategory.ADMINISTRATION, requiredType = RequiredType.CONSOLE,
|
||||
permission = "plots.regenallroads") public class RegenAllRoads extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
int height = 0;
|
||||
if (args.length == 2) {
|
||||
try {
|
||||
height = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException ignored) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_NUMBER, "(0, 256)");
|
||||
MainUtil
|
||||
.sendMessage(player, C.COMMAND_SYNTAX, "/plot regenallroads <world> [height]");
|
||||
return false;
|
||||
}
|
||||
} else if (args.length != 1) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot regenallroads <world> [height]");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]);
|
||||
if (area == null) {
|
||||
C.NOT_VALID_PLOT_WORLD.send(player, args[0]);
|
||||
return false;
|
||||
}
|
||||
String name = args[0];
|
||||
PlotManager manager = area.getPlotManager();
|
||||
if (!(manager instanceof HybridPlotManager)) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_WORLD);
|
||||
return false;
|
||||
}
|
||||
//Set<ChunkLoc> chunks = ChunkManager.manager.getChunkChunks(name);
|
||||
MainUtil
|
||||
.sendMessage(player, "&cIf no schematic is set, the following will not do anything");
|
||||
MainUtil.sendMessage(player,
|
||||
"&7 - To set a schematic, stand in a plot and use &c/plot createroadschematic");
|
||||
//MainUtil.sendMessage(player, "&6Potential chunks to update: &7" + (chunks.size() * 1024));
|
||||
//MainUtil.sendMessage(player, "&6Estimated time: &7" + chunks.size() + " seconds");
|
||||
boolean result = HybridUtils.manager.scheduleRoadUpdate(area, height);
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&cCannot schedule mass schematic update! (Is one already in progress?)");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
@CommandDeclaration(command = "relight", description = "Relight your plot", usage = "/plot relight",
|
||||
category = CommandCategory.DEBUG) public class Relight extends Command {
|
||||
public Relight() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
@Override public void execute(final PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) {
|
||||
final Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
C.NOT_IN_PLOT.send(player);
|
||||
return;
|
||||
}
|
||||
HashSet<RegionWrapper> regions = plot.getRegions();
|
||||
final LocalBlockQueue queue = plot.getArea().getQueue(false);
|
||||
ChunkManager.chunkTask(plot, new RunnableVal<int[]>() {
|
||||
@Override public void run(int[] value) {
|
||||
queue.fixChunkLighting(value[0], value[1]);
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override public void run() {
|
||||
plot.refreshChunks();
|
||||
C.SET_BLOCK_ACTION_FINISHED.send(player);
|
||||
}
|
||||
}, 5);
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.configuration.ConfigurationSection;
|
||||
import com.github.intellectualsites.plotsquared.configuration.MemorySection;
|
||||
import com.github.intellectualsites.plotsquared.configuration.file.YamlConfiguration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
@CommandDeclaration(command = "reload", aliases = "rl", permission = "plots.admin.command.reload",
|
||||
description = "Reload translations and world settings", usage = "/plot reload",
|
||||
category = CommandCategory.ADMINISTRATION) public class Reload extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
try {
|
||||
// The following won't affect world generation, as that has to be
|
||||
// loaded during startup unfortunately.
|
||||
PlotSquared.get().setupConfigs();
|
||||
C.load(PlotSquared.get().translationFile);
|
||||
PlotSquared.get().foreachPlotArea(new RunnableVal<PlotArea>() {
|
||||
@Override public void run(PlotArea area) {
|
||||
ConfigurationSection worldSection = PlotSquared.get().worlds
|
||||
.getConfigurationSection("worlds." + area.worldname);
|
||||
if (worldSection == null) {
|
||||
return;
|
||||
}
|
||||
if (area.TYPE != 2 || !worldSection.contains("areas")) {
|
||||
area.saveConfiguration(worldSection);
|
||||
area.loadDefaultConfiguration(worldSection);
|
||||
} else {
|
||||
ConfigurationSection areaSection = worldSection.getConfigurationSection(
|
||||
"areas." + area.id + "-" + area.getMin() + "-" + area.getMax());
|
||||
YamlConfiguration clone = new YamlConfiguration();
|
||||
for (String key : areaSection.getKeys(true)) {
|
||||
if (areaSection.get(key) instanceof MemorySection) {
|
||||
continue;
|
||||
}
|
||||
if (!clone.contains(key)) {
|
||||
clone.set(key, areaSection.get(key));
|
||||
}
|
||||
}
|
||||
for (String key : worldSection.getKeys(true)) {
|
||||
if (worldSection.get(key) instanceof MemorySection) {
|
||||
continue;
|
||||
}
|
||||
if (!key.startsWith("areas") && !clone.contains(key)) {
|
||||
clone.set(key, worldSection.get(key));
|
||||
}
|
||||
}
|
||||
area.saveConfiguration(clone);
|
||||
// netSections is the combination of
|
||||
for (String key : clone.getKeys(true)) {
|
||||
if (clone.get(key) instanceof MemorySection) {
|
||||
continue;
|
||||
}
|
||||
if (!worldSection.contains(key)) {
|
||||
worldSection.set(key, clone.get(key));
|
||||
} else {
|
||||
Object value = worldSection.get(key);
|
||||
if (Objects.equals(value, clone.get(key))) {
|
||||
areaSection.set(key, clone.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
area.loadDefaultConfiguration(clone);
|
||||
}
|
||||
}
|
||||
});
|
||||
PlotSquared.get().worlds.save(PlotSquared.get().worldsFile);
|
||||
MainUtil.sendMessage(player, C.RELOADED_CONFIGS);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
MainUtil.sendMessage(player, C.RELOAD_FAILED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Argument;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.EventUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "remove", aliases = {"r", "untrust", "ut", "undeny", "unban", "ud"},
|
||||
description = "Remove a player from a plot", usage = "/plot remove <player>",
|
||||
category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE,
|
||||
permission = "plots.remove") public class Remove extends SubCommand {
|
||||
|
||||
public Remove() {
|
||||
super(Argument.PlayerName);
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
Location location = player.getLocation();
|
||||
Plot plot = location.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_REMOVE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return true;
|
||||
}
|
||||
int count = 0;
|
||||
switch (args[0]) {
|
||||
case "unknown": {
|
||||
ArrayList<UUID> toRemove = new ArrayList<>();
|
||||
HashSet<UUID> all = new HashSet<>();
|
||||
all.addAll(plot.getMembers());
|
||||
all.addAll(plot.getTrusted());
|
||||
all.addAll(plot.getDenied());
|
||||
for (UUID uuid : all) {
|
||||
if (UUIDHandler.getName(uuid) == null) {
|
||||
toRemove.add(uuid);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
for (UUID uuid : toRemove) {
|
||||
plot.removeDenied(uuid);
|
||||
plot.removeTrusted(uuid);
|
||||
plot.removeMember(uuid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
|
||||
if (!uuids.isEmpty()) {
|
||||
for (UUID uuid : uuids) {
|
||||
if (uuid == DBFunc.EVERYONE) {
|
||||
if (plot.removeTrusted(uuid)) {
|
||||
EventUtil.manager.callTrusted(player, plot, uuid, false);
|
||||
count++;
|
||||
} else if (plot.removeMember(uuid)) {
|
||||
EventUtil.manager.callMember(player, plot, uuid, false);
|
||||
count++;
|
||||
} else if (plot.removeDenied(uuid)) {
|
||||
EventUtil.manager.callDenied(player, plot, uuid, false);
|
||||
count++;
|
||||
}
|
||||
} else if (plot.getTrusted().contains(uuid)) {
|
||||
if (plot.removeTrusted(uuid)) {
|
||||
EventUtil.manager.callTrusted(player, plot, uuid, false);
|
||||
count++;
|
||||
}
|
||||
} else if (plot.getMembers().contains(uuid)) {
|
||||
if (plot.removeMember(uuid)) {
|
||||
EventUtil.manager.callMember(player, plot, uuid, false);
|
||||
count++;
|
||||
}
|
||||
} else if (plot.getDenied().contains(uuid)) {
|
||||
if (plot.removeDenied(uuid)) {
|
||||
EventUtil.manager.callDenied(player, plot, uuid, false);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (count == 0) {
|
||||
MainUtil.sendMessage(player, C.INVALID_PLAYER, args[0]);
|
||||
return false;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.REMOVED_PLAYERS, count + "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandCaller;
|
||||
|
||||
public enum RequiredType {
|
||||
CONSOLE, PLAYER, NONE;
|
||||
|
||||
public boolean allows(CommandCaller player) {
|
||||
switch (this) {
|
||||
case NONE:
|
||||
return true;
|
||||
default:
|
||||
return this == player.getSuperCaller();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "save", aliases = {"backup"}, description = "Save your plot",
|
||||
category = CommandCategory.SCHEMATIC, requiredType = RequiredType.NONE,
|
||||
permission = "plots.save") public class Save extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
String world = player.getLocation().getWorld();
|
||||
if (!PlotSquared.get().hasPlotArea(world)) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT_WORLD);
|
||||
}
|
||||
final Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_SAVE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
plot.addRunning();
|
||||
SchematicHandler.manager.getCompoundTag(plot, new RunnableVal<CompoundTag>() {
|
||||
@Override public void run(final CompoundTag value) {
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
String time = (System.currentTimeMillis() / 1000) + "";
|
||||
Location[] corners = plot.getCorners();
|
||||
corners[0].setY(0);
|
||||
corners[1].setY(255);
|
||||
int size = (corners[1].getX() - corners[0].getX()) + 1;
|
||||
PlotId id = plot.getId();
|
||||
String world1 = plot.getArea().toString().replaceAll(";", "-")
|
||||
.replaceAll("[^A-Za-z0-9]", "");
|
||||
final String file = time + '_' + world1 + '_' + id.x + '_' + id.y + '_' + size;
|
||||
UUID uuid = player.getUUID();
|
||||
SchematicHandler.manager.upload(value, uuid, file, new RunnableVal<URL>() {
|
||||
@Override public void run(URL url) {
|
||||
plot.removeRunning();
|
||||
if (url == null) {
|
||||
MainUtil.sendMessage(player, C.SAVE_FAILED);
|
||||
return;
|
||||
}
|
||||
MainUtil.sendMessage(player, C.SAVE_SUCCESS);
|
||||
List<String> schematics = player.getMeta("plot_schematics");
|
||||
if (schematics != null) {
|
||||
schematics.add(file + ".schematic");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,222 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Settings;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.schematic.Schematic;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(command = "schematic", permission = "plots.schematic",
|
||||
description = "Schematic command", aliases = {"sch", "schem"},
|
||||
category = CommandCategory.SCHEMATIC, usage = "/plot schematic <arg...>")
|
||||
public class SchematicCmd extends SubCommand {
|
||||
|
||||
private boolean running = false;
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sendMessage(player, C.SCHEMATIC_MISSING_ARG);
|
||||
return true;
|
||||
}
|
||||
String arg = args[0].toLowerCase();
|
||||
switch (arg) {
|
||||
case "paste": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_SCHEMATIC_PASTE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_SCHEMATIC_PASTE);
|
||||
return false;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sendMessage(player, C.SCHEMATIC_MISSING_ARG);
|
||||
break;
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
final Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_SCHEMATIC_PASTE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (this.running) {
|
||||
MainUtil.sendMessage(player, "&cTask is already running.");
|
||||
return false;
|
||||
}
|
||||
final String location = args[1];
|
||||
this.running = true;
|
||||
TaskManager.runTaskAsync(() -> {
|
||||
Schematic schematic = null;
|
||||
if (location.startsWith("url:")) {
|
||||
try {
|
||||
UUID uuid = UUID.fromString(location.substring(4));
|
||||
URL base = new URL(Settings.Web.URL);
|
||||
URL url = new URL(base, "uploads/" + uuid + ".schematic");
|
||||
schematic = SchematicHandler.manager.getSchematic(url);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
sendMessage(player, C.SCHEMATIC_INVALID,
|
||||
"non-existent url: " + location);
|
||||
SchematicCmd.this.running = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
schematic = SchematicHandler.manager.getSchematic(location);
|
||||
} catch (SchematicHandler.UnsupportedFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (schematic == null) {
|
||||
SchematicCmd.this.running = false;
|
||||
sendMessage(player, C.SCHEMATIC_INVALID,
|
||||
"non-existent or not in gzip format");
|
||||
return;
|
||||
}
|
||||
SchematicHandler.manager
|
||||
.paste(schematic, plot, 0, 1, 0, false, new RunnableVal<Boolean>() {
|
||||
@Override public void run(Boolean value) {
|
||||
SchematicCmd.this.running = false;
|
||||
if (value) {
|
||||
sendMessage(player, C.SCHEMATIC_PASTE_SUCCESS);
|
||||
} else {
|
||||
sendMessage(player, C.SCHEMATIC_PASTE_FAILED);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
// TODO test
|
||||
// case "test": {
|
||||
// if (!Permissions.hasPermission(plr, "plots.schematic.test")) {
|
||||
// MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.schematic.test");
|
||||
// return false;
|
||||
// }
|
||||
// if (args.length < 2) {
|
||||
// sendMessage(plr, C.SCHEMATIC_MISSING_ARG);
|
||||
// return false;
|
||||
// }
|
||||
// final Location loc = plr.getLocation();
|
||||
// final Plot plot = MainUtil.getPlot(loc);
|
||||
// if (plot == null) {
|
||||
// sendMessage(plr, C.NOT_IN_PLOT);
|
||||
// return false;
|
||||
// }
|
||||
// file = args[1];
|
||||
// schematic = SchematicHandler.manager.getSchematic(file);
|
||||
// if (schematic == null) {
|
||||
// sendMessage(plr, C.SCHEMATIC_INVALID, "non-existent");
|
||||
// return false;
|
||||
// }
|
||||
// final int l1 = schematic.getSchematicDimension().getX();
|
||||
// final int l2 = schematic.getSchematicDimension().getZ();
|
||||
// final int length = MainUtil.getPlotWidth(loc.getWorld(), plot.id);
|
||||
// if ((l1 < length) || (l2 < length)) {
|
||||
// sendMessage(plr, C.SCHEMATIC_INVALID, String.format("Wrong size (x: %s, z: %d) vs %d ", l1, l2, length));
|
||||
// break;
|
||||
// }
|
||||
// sendMessage(plr, C.SCHEMATIC_VALID);
|
||||
// break;
|
||||
// }
|
||||
case "saveall":
|
||||
case "exportall": {
|
||||
if (!(player instanceof ConsolePlayer)) {
|
||||
MainUtil.sendMessage(player, C.NOT_CONSOLE);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 2) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&cNeed world argument. Use &7/plot sch exportall <area>");
|
||||
return false;
|
||||
}
|
||||
PlotArea area = PlotSquared.get().getPlotAreaByString(args[1]);
|
||||
if (area == null) {
|
||||
C.NOT_VALID_PLOT_WORLD.send(player, args[1]);
|
||||
return false;
|
||||
}
|
||||
Collection<Plot> plots = area.getPlots();
|
||||
if (plots.isEmpty()) {
|
||||
MainUtil
|
||||
.sendMessage(player, "&cInvalid world. Use &7/plot sch exportall <area>");
|
||||
return false;
|
||||
}
|
||||
boolean result = SchematicHandler.manager.exportAll(plots, null, null,
|
||||
() -> MainUtil.sendMessage(player, "&aFinished mass export"));
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, "&cTask is already running.");
|
||||
return false;
|
||||
} else {
|
||||
MainUtil.sendMessage(player,
|
||||
"&3Plot&8->&3Schematic&8: &7Mass export has started. This may take a while.");
|
||||
MainUtil.sendMessage(player,
|
||||
"&3Plot&8->&3Schematic&8: &7Found &c" + plots.size() + "&7 plots...");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "export":
|
||||
case "save":
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_SCHEMATIC_SAVE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_SCHEMATIC_SAVE);
|
||||
return false;
|
||||
}
|
||||
if (this.running) {
|
||||
MainUtil.sendMessage(player, "&cTask is already running.");
|
||||
return false;
|
||||
}
|
||||
Location location = player.getLocation();
|
||||
Plot plot = location.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
MainUtil.sendMessage(player, C.PLOT_UNOWNED);
|
||||
return false;
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN_COMMAND_SCHEMATIC_SAVE)) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
location.getWorld();
|
||||
Collection<Plot> plots = new ArrayList<>();
|
||||
plots.add(plot);
|
||||
boolean result = SchematicHandler.manager.exportAll(plots, null, null, () -> {
|
||||
MainUtil.sendMessage(player, "&aFinished export");
|
||||
SchematicCmd.this.running = false;
|
||||
});
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, "&cTask is already running.");
|
||||
return false;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, "&7Starting export...");
|
||||
}
|
||||
break;
|
||||
case "list": {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_SCHEMATIC_LIST)) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION, C.PERMISSION_SCHEMATIC_LIST);
|
||||
return false;
|
||||
}
|
||||
final String string =
|
||||
StringMan.join(SchematicHandler.manager.getShematicNames(), "$2, $1");
|
||||
C.SCHEMATIC_LIST.send(player, string);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sendMessage(player, C.SCHEMATIC_MISSING_ARG);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Configuration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Configuration.UnknownBlockException;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.FlagManager;
|
||||
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
@CommandDeclaration(command = "set", description = "Set a plot value", aliases = {"s"},
|
||||
usage = "/plot set <biome|alias|home|flag> <value...>", permission = "plots.set",
|
||||
category = CommandCategory.APPEARANCE, requiredType = RequiredType.NONE) public class Set
|
||||
extends SubCommand {
|
||||
|
||||
public static final String[] values = new String[] {"biome", "alias", "home", "flag"};
|
||||
public static final String[] aliases = new String[] {"b", "w", "wf", "f", "a", "h", "fl"};
|
||||
|
||||
private final SetCommand component;
|
||||
|
||||
public Set() {
|
||||
this.component = new SetCommand() {
|
||||
|
||||
@Override public String getId() {
|
||||
return "set.component";
|
||||
}
|
||||
|
||||
@Override public boolean set(PlotPlayer player, final Plot plot, String value) {
|
||||
PlotArea plotArea = player.getLocation().getPlotArea();
|
||||
PlotManager manager = player.getLocation().getPlotManager();
|
||||
String[] components = manager.getPlotComponents(plotArea, plot.getId());
|
||||
boolean allowUnsafe = DebugAllowUnsafe.unsafeAllowed.contains(player.getUUID());
|
||||
|
||||
String[] args = value.split(" ");
|
||||
String material =
|
||||
StringMan.join(Arrays.copyOfRange(args, 1, args.length), ",").trim();
|
||||
|
||||
for (String component : components) {
|
||||
if (component.equalsIgnoreCase(args[0])) {
|
||||
if (!Permissions
|
||||
.hasPermission(player, C.PERMISSION_SET_COMPONENT.f(component))) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_SET_COMPONENT.f(component));
|
||||
return false;
|
||||
}
|
||||
// PlotBlock[] blocks;
|
||||
BlockBucket bucket;
|
||||
try {
|
||||
if (args.length < 2) {
|
||||
MainUtil.sendMessage(player, C.NEED_BLOCK);
|
||||
return true;
|
||||
}
|
||||
String[] split = material.split(",");
|
||||
// blocks = Configuration.BLOCKLIST.parseString(material);
|
||||
|
||||
try {
|
||||
bucket = Configuration.BLOCK_BUCKET.parseString(material);
|
||||
} catch (final UnknownBlockException unknownBlockException) {
|
||||
final String unknownBlock = unknownBlockException.getUnknownValue();
|
||||
C.NOT_VALID_BLOCK.send(player, unknownBlock);
|
||||
StringComparison<PlotBlock>.ComparisonResult match =
|
||||
WorldUtil.IMP.getClosestBlock(unknownBlock);
|
||||
if (match != null) {
|
||||
final String found =
|
||||
WorldUtil.IMP.getClosestMatchingName(match.best);
|
||||
if (found != null) {
|
||||
MainUtil.sendMessage(player, C.DID_YOU_MEAN,
|
||||
found.toLowerCase());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!allowUnsafe) {
|
||||
for (final PlotBlock block : bucket.getBlocks()) {
|
||||
if (!block.isAir() && !WorldUtil.IMP.isBlockSolid(block)) {
|
||||
C.NOT_ALLOWED_BLOCK.send(player, block.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_BLOCK, material);
|
||||
return false;
|
||||
}
|
||||
if (plot.getRunning() > 0) {
|
||||
MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
|
||||
return false;
|
||||
}
|
||||
plot.addRunning();
|
||||
for (Plot current : plot.getConnectedPlots()) {
|
||||
current.setComponent(component, bucket);
|
||||
}
|
||||
MainUtil.sendMessage(player, C.GENERATING_COMPONENT);
|
||||
GlobalBlockQueue.IMP.addTask(new Runnable() {
|
||||
@Override public void run() {
|
||||
plot.removeRunning();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean noArgs(PlotPlayer player) {
|
||||
ArrayList<String> newValues = new ArrayList<>();
|
||||
newValues.addAll(Arrays.asList("biome", "alias", "home", "flag"));
|
||||
Plot plot = player.getCurrentPlot();
|
||||
if (plot != null) {
|
||||
newValues.addAll(
|
||||
Arrays.asList(plot.getManager().getPlotComponents(plot.getArea(), plot.getId())));
|
||||
}
|
||||
MainUtil.sendMessage(player, C.SUBCOMMAND_SET_OPTIONS_HEADER.s() + StringMan
|
||||
.join(newValues, C.BLOCK_LIST_SEPARATER.formatted()));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
if (args.length == 0) {
|
||||
return noArgs(player);
|
||||
}
|
||||
Command cmd = MainCommand.getInstance().getCommand("set" + args[0]);
|
||||
if (cmd != null) {
|
||||
if (!Permissions.hasPermission(player, cmd.getPermission(), true)) {
|
||||
return false;
|
||||
}
|
||||
cmd.execute(player, Arrays.copyOfRange(args, 1, args.length), null, null);
|
||||
return true;
|
||||
}
|
||||
// Additional checks
|
||||
Plot plot = player.getCurrentPlot();
|
||||
if (plot == null) {
|
||||
MainUtil.sendMessage(player, C.NOT_IN_PLOT);
|
||||
return false;
|
||||
}
|
||||
// components
|
||||
HashSet<String> components = new HashSet<>(
|
||||
Arrays.asList(plot.getManager().getPlotComponents(plot.getArea(), plot.getId())));
|
||||
if (components.contains(args[0].toLowerCase())) {
|
||||
return this.component.onCommand(player, Arrays.copyOfRange(args, 0, args.length));
|
||||
}
|
||||
// flag
|
||||
Flag<?> flag = FlagManager.getFlag(args[0].toLowerCase());
|
||||
if (Flags.getFlags().contains(flag)) {
|
||||
StringBuilder a = new StringBuilder();
|
||||
if (args.length > 1) {
|
||||
for (int x = 1; x < args.length; x++) {
|
||||
a.append(" ").append(args[x]);
|
||||
}
|
||||
}
|
||||
MainCommand.onCommand(player, ("flag set " + args[0] + a.toString()).split(" "));
|
||||
return true;
|
||||
}
|
||||
return noArgs(player);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
|
||||
public abstract class SetCommand extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
Plot plot = loc.getPlotAbs();
|
||||
if (plot == null) {
|
||||
return !sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot.hasOwner()) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND.f(getFullId()))) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_ADMIN_COMMAND.f(getFullId()));
|
||||
MainUtil.sendMessage(player, C.PLOT_NOT_CLAIMED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!plot.isOwner(player.getUUID())) {
|
||||
if (!Permissions.hasPermission(player, C.PERMISSION_ADMIN_COMMAND.f(getFullId()))) {
|
||||
MainUtil.sendMessage(player, C.NO_PERMISSION,
|
||||
C.PERMISSION_ADMIN_COMMAND.f(getFullId()));
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (args.length == 0) {
|
||||
return set(player, plot, "");
|
||||
}
|
||||
return set(player, plot, StringMan.join(args, " "));
|
||||
}
|
||||
|
||||
public abstract boolean set(PlotPlayer player, Plot plot, String value);
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.BlockLoc;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
|
||||
@CommandDeclaration(command = "sethome", permission = "plots.set.home",
|
||||
description = "Set the plot home to your current position", usage = "/plot sethome [none]",
|
||||
aliases = {"sh", "seth"}, category = CommandCategory.SETTINGS, requiredType = RequiredType.NONE)
|
||||
public class SetHome extends SetCommand {
|
||||
|
||||
@Override public boolean set(PlotPlayer player, Plot plot, String value) {
|
||||
switch (value.toLowerCase()) {
|
||||
case "unset":
|
||||
case "reset":
|
||||
case "remove":
|
||||
case "none": {
|
||||
Plot base = plot.getBasePlot(false);
|
||||
base.setHome(null);
|
||||
return MainUtil.sendMessage(player, C.POSITION_UNSET);
|
||||
}
|
||||
case "":
|
||||
Plot base = plot.getBasePlot(false);
|
||||
Location bot = base.getBottomAbs();
|
||||
Location loc = player.getLocationFull();
|
||||
BlockLoc rel =
|
||||
new BlockLoc(loc.getX() - bot.getX(), loc.getY(), loc.getZ() - bot.getZ(),
|
||||
loc.getYaw(), loc.getPitch());
|
||||
base.setHome(rel);
|
||||
return MainUtil.sendMessage(player, C.POSITION_SET);
|
||||
default:
|
||||
MainUtil.sendMessage(player, C.HOME_ARGUMENT);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,434 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.Configuration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.ConfigurationNode;
|
||||
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.*;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.SetupUtils;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
|
||||
import lombok.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@CommandDeclaration(command = "setup", permission = "plots.admin.command.setup",
|
||||
description = "Setup wizard for plot worlds", usage = "/plot setup", aliases = {"create"},
|
||||
category = CommandCategory.ADMINISTRATION) public class Setup extends SubCommand {
|
||||
|
||||
public void displayGenerators(PlotPlayer player) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("&6What generator do you want?");
|
||||
for (Entry<String, GeneratorWrapper<?>> entry : SetupUtils.generators.entrySet()) {
|
||||
if (entry.getKey().equals(PlotSquared.imp().getPluginName())) {
|
||||
message.append("\n&8 - &2").append(entry.getKey()).append(" (Default Generator)");
|
||||
} else if (entry.getValue().isFull()) {
|
||||
message.append("\n&8 - &7").append(entry.getKey()).append(" (Plot Generator)");
|
||||
} else {
|
||||
message.append("\n&8 - &7").append(entry.getKey()).append(" (Unknown structure)");
|
||||
}
|
||||
}
|
||||
MainUtil.sendMessage(player, message.toString());
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(PlotPlayer player, String[] args) {
|
||||
// going through setup
|
||||
SetupObject object = player.getMeta("setup");
|
||||
if (object == null) {
|
||||
object = new SetupObject();
|
||||
player.setMeta("setup", object);
|
||||
SetupUtils.manager.updateGenerators();
|
||||
sendMessage(player, C.SETUP_INIT);
|
||||
displayGenerators(player);
|
||||
return false;
|
||||
}
|
||||
if (args.length == 1) {
|
||||
if (args[0].equalsIgnoreCase("cancel")) {
|
||||
player.deleteMeta("setup");
|
||||
MainUtil.sendMessage(player, "&aCancelled setup");
|
||||
return false;
|
||||
}
|
||||
if (args[0].equalsIgnoreCase("back")) {
|
||||
if (object.setup_index > 0) {
|
||||
object.setup_index--;
|
||||
ConfigurationNode node = object.step[object.setup_index];
|
||||
sendMessage(player, C.SETUP_STEP, object.setup_index + 1, node.getDescription(),
|
||||
node.getType().getType(), String.valueOf(node.getDefaultValue()));
|
||||
return false;
|
||||
} else if (object.current > 0) {
|
||||
object.current--;
|
||||
}
|
||||
}
|
||||
}
|
||||
int index = object.current;
|
||||
switch (index) {
|
||||
case 0: // choose generator
|
||||
if (args.length != 1 || !SetupUtils.generators.containsKey(args[0])) {
|
||||
String prefix = "\n&8 - &7";
|
||||
MainUtil.sendMessage(player,
|
||||
"&cYou must choose a generator!" + prefix + StringMan
|
||||
.join(SetupUtils.generators.keySet(), prefix)
|
||||
.replaceAll(PlotSquared.imp().getPluginName(),
|
||||
"&2" + PlotSquared.imp().getPluginName()));
|
||||
sendMessage(player, C.SETUP_INIT);
|
||||
return false;
|
||||
}
|
||||
object.setupGenerator = args[0];
|
||||
object.current++;
|
||||
String partial = "\n&8 - &7PARTIAL&8 - &7Vanilla with clusters of plots";
|
||||
MainUtil.sendMessage(player,
|
||||
"&6What world type do you want?\n&8 - &2DEFAULT&8 - &7Standard plot generation"
|
||||
+ "\n&8 - &7AUGMENTED&8 - &7Plot generation with terrain" + partial);
|
||||
break;
|
||||
case 1: // choose world type
|
||||
List<String> allTypes = Arrays.asList("default", "augmented", "partial");
|
||||
List<String> allDesc = Arrays
|
||||
.asList("Standard plot generation", "Plot generation with vanilla terrain",
|
||||
"Vanilla with clusters of plots");
|
||||
ArrayList<String> types = new ArrayList<>();
|
||||
if (SetupUtils.generators.get(object.setupGenerator).isFull()) {
|
||||
types.add("default");
|
||||
}
|
||||
types.add("augmented");
|
||||
types.add("partial");
|
||||
if (args.length != 1 || !types.contains(args[0].toLowerCase())) {
|
||||
MainUtil.sendMessage(player, "&cYou must choose a world type!");
|
||||
for (String type : types) {
|
||||
int i = allTypes.indexOf(type);
|
||||
if (type.equals("default")) {
|
||||
MainUtil
|
||||
.sendMessage(player, "&8 - &2" + type + " &8-&7 " + allDesc.get(i));
|
||||
} else {
|
||||
MainUtil
|
||||
.sendMessage(player, "&8 - &7" + type + " &8-&7 " + allDesc.get(i));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
object.type = allTypes.indexOf(args[0].toLowerCase());
|
||||
GeneratorWrapper<?> gen = SetupUtils.generators.get(object.setupGenerator);
|
||||
if (object.type == 0) {
|
||||
object.current = 6;
|
||||
if (object.step == null) {
|
||||
object.plotManager = object.setupGenerator;
|
||||
object.step =
|
||||
SetupUtils.generators.get(object.plotManager).getPlotGenerator()
|
||||
.getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null)
|
||||
.getSettingNodes();
|
||||
SetupUtils.generators.get(object.plotManager).getPlotGenerator()
|
||||
.processSetup(object);
|
||||
}
|
||||
if (object.step.length == 0) {
|
||||
MainUtil.sendMessage(player, "&6What do you want your world to be called?");
|
||||
object.setup_index = 0;
|
||||
return true;
|
||||
}
|
||||
ConfigurationNode step = object.step[object.setup_index];
|
||||
sendMessage(player, C.SETUP_STEP, object.setup_index + 1, step.getDescription(),
|
||||
step.getType().getType(), String.valueOf(step.getDefaultValue()));
|
||||
} else {
|
||||
if (gen.isFull()) {
|
||||
object.plotManager = object.setupGenerator;
|
||||
object.setupGenerator = null;
|
||||
object.step =
|
||||
SetupUtils.generators.get(object.plotManager).getPlotGenerator()
|
||||
.getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null)
|
||||
.getSettingNodes();
|
||||
SetupUtils.generators.get(object.plotManager).getPlotGenerator()
|
||||
.processSetup(object);
|
||||
} else {
|
||||
object.plotManager = PlotSquared.imp().getPluginName();
|
||||
MainUtil.sendMessage(player,
|
||||
"&c[WARNING] The specified generator does not identify as BukkitPlotGenerator");
|
||||
MainUtil.sendMessage(player,
|
||||
"&7 - You may need to manually configure the other plugin");
|
||||
object.step =
|
||||
SetupUtils.generators.get(object.plotManager).getPlotGenerator()
|
||||
.getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null)
|
||||
.getSettingNodes();
|
||||
}
|
||||
if (object.type == 2) {
|
||||
MainUtil.sendMessage(player, "What would you like this area called?");
|
||||
object.current++;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, "&6What terrain would you like in plots?"
|
||||
+ "\n&8 - &2NONE&8 - &7No terrain at all"
|
||||
+ "\n&8 - &7ORE&8 - &7Just some ore veins and trees"
|
||||
+ "\n&8 - &7ROAD&8 - &7Terrain separated by roads"
|
||||
+ "\n&8 - &7ALL&8 - &7Entirely vanilla generation");
|
||||
object.current = 5;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // area id
|
||||
if (!StringMan.isAlphanumericUnd(args[0])) {
|
||||
MainUtil.sendMessage(player, "&cThe area id must be alphanumerical!");
|
||||
return false;
|
||||
}
|
||||
for (PlotArea area : PlotSquared.get().getPlotAreas()) {
|
||||
if (area.id != null && area.id.equalsIgnoreCase(args[0])) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&cYou must choose an area id that is not in use!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
object.id = args[0];
|
||||
object.current++;
|
||||
MainUtil.sendMessage(player, "&6What should be the minimum Plot Id?");
|
||||
break;
|
||||
case 3: // min
|
||||
object.min = PlotId.fromString(args[0]);
|
||||
if (object.min == null) {
|
||||
MainUtil.sendMessage(player, "&cYou must choose a valid minimum PlotId!");
|
||||
return false;
|
||||
}
|
||||
object.current++;
|
||||
MainUtil.sendMessage(player, "&6What should be the maximum Plot Id?");
|
||||
break;
|
||||
case 4:
|
||||
// max
|
||||
PlotId id = PlotId.fromString(args[0]);
|
||||
if (id == null) {
|
||||
MainUtil.sendMessage(player, "&cYou must choose a valid maximum PlotId!");
|
||||
return false;
|
||||
}
|
||||
if (id.x <= object.min.x || id.y <= object.min.y) {
|
||||
MainUtil
|
||||
.sendMessage(player, "&cThe max PlotId must be greater than the minimum!");
|
||||
return false;
|
||||
}
|
||||
object.max = id;
|
||||
object.current++;
|
||||
MainUtil.sendMessage(player, "&6What terrain would you like in plots?"
|
||||
+ "\n&8 - &2NONE&8 - &7No terrain at all"
|
||||
+ "\n&8 - &7ORE&8 - &7Just some ore veins and trees"
|
||||
+ "\n&8 - &7ROAD&8 - &7Terrain separated by roads"
|
||||
+ "\n&8 - &7ALL&8 - &7Entirely vanilla generation");
|
||||
break;
|
||||
case 5: { // Choose terrain
|
||||
List<String> terrain = Arrays.asList("none", "ore", "road", "all");
|
||||
if (args.length != 1 || !terrain.contains(args[0].toLowerCase())) {
|
||||
MainUtil.sendMessage(player,
|
||||
"&cYou must choose the terrain!" + "\n&8 - &2NONE&8 - &7No terrain at all"
|
||||
+ "\n&8 - &7ORE&8 - &7Just some ore veins and trees"
|
||||
+ "\n&8 - &7ROAD&8 - &7Terrain separated by roads"
|
||||
+ "\n&8 - &7ALL&8 - &7Entirely vanilla generation");
|
||||
return false;
|
||||
}
|
||||
object.terrain = terrain.indexOf(args[0].toLowerCase());
|
||||
object.current++;
|
||||
if (object.step == null) {
|
||||
object.step = SetupUtils.generators.get(object.plotManager).getPlotGenerator()
|
||||
.getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null)
|
||||
.getSettingNodes();
|
||||
}
|
||||
ConfigurationNode step = object.step[object.setup_index];
|
||||
sendMessage(player, C.SETUP_STEP, object.setup_index + 1, step.getDescription(),
|
||||
step.getType().getType(), String.valueOf(step.getDefaultValue()));
|
||||
break;
|
||||
}
|
||||
case 6: // world setup
|
||||
if (object.setup_index == object.step.length) {
|
||||
MainUtil.sendMessage(player, "&6What do you want your world to be called?");
|
||||
object.setup_index = 0;
|
||||
object.current++;
|
||||
return true;
|
||||
}
|
||||
ConfigurationNode step = object.step[object.setup_index];
|
||||
if (args.length < 1) {
|
||||
sendMessage(player, C.SETUP_STEP, object.setup_index + 1, step.getDescription(),
|
||||
step.getType().getType(), String.valueOf(step.getDefaultValue()));
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean valid = false;
|
||||
try {
|
||||
valid = step.isValid(args[0]);
|
||||
} catch (final Configuration.UnsafeBlockException e) {
|
||||
C.NOT_ALLOWED_BLOCK.send(player, e.getUnsafeBlock().toString());
|
||||
}
|
||||
if (valid) {
|
||||
sendMessage(player, C.SETUP_VALID_ARG, step.getConstant(), args[0]);
|
||||
step.setValue(args[0]);
|
||||
object.setup_index++;
|
||||
if (object.setup_index == object.step.length) {
|
||||
onCommand(player, args);
|
||||
return false;
|
||||
}
|
||||
step = object.step[object.setup_index];
|
||||
sendMessage(player, C.SETUP_STEP, object.setup_index + 1, step.getDescription(),
|
||||
step.getType().getType(), String.valueOf(step.getDefaultValue()));
|
||||
return false;
|
||||
} else {
|
||||
sendMessage(player, C.SETUP_INVALID_ARG, args[0], step.getConstant());
|
||||
sendMessage(player, C.SETUP_STEP, object.setup_index + 1, step.getDescription(),
|
||||
step.getType().getType(), String.valueOf(step.getDefaultValue()));
|
||||
return false;
|
||||
}
|
||||
case 7:
|
||||
if (args.length != 1) {
|
||||
MainUtil.sendMessage(player, "&cYou need to choose a world name!");
|
||||
return false;
|
||||
}
|
||||
if (WorldUtil.IMP.isWorld(args[0])) {
|
||||
if (PlotSquared.get().hasPlotArea(args[0])) {
|
||||
MainUtil.sendMessage(player, "&cThat world name is already taken!");
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player,
|
||||
"&cThe world you specified already exists. After restarting, new terrain will use "
|
||||
+ PlotSquared.imp().getPluginName() + ", however you may need to "
|
||||
+ "reset the world for it to generate correctly!");
|
||||
}
|
||||
object.world = args[0];
|
||||
player.deleteMeta("setup");
|
||||
String world;
|
||||
if (object.setupManager == null) {
|
||||
world = SetupUtils.manager.setupWorld(object);
|
||||
} else {
|
||||
world = object.setupManager.setupWorld(object);
|
||||
}
|
||||
try {
|
||||
player.teleport(WorldUtil.IMP.getSpawn(world));
|
||||
} catch (Exception e) {
|
||||
player.sendMessage("&cAn error occurred. See console for more information");
|
||||
e.printStackTrace();
|
||||
}
|
||||
sendMessage(player, C.SETUP_FINISHED, object.world);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final class StepPickGenerator extends SetupStep {
|
||||
|
||||
@Getter private String generator;
|
||||
|
||||
public StepPickGenerator() {
|
||||
super("generator");
|
||||
}
|
||||
|
||||
@Override public Collection<PlotMessage> showDescriptionMessage() {
|
||||
SetupUtils.manager.updateGenerators();
|
||||
final List<PlotMessage> messages = new ArrayList<>();
|
||||
messages.add(new PlotMessage("What generator do you want?").color("$6"));
|
||||
for (Entry<String, GeneratorWrapper<?>> entry : SetupUtils.generators.entrySet()) {
|
||||
final PlotMessage plotMessage = new PlotMessage(" - ").color("$8");
|
||||
if (entry.getKey().equals(PlotSquared.imp().getPluginName())) {
|
||||
plotMessage.text(entry.getKey()).color("$8").tooltip("Select this generator")
|
||||
.color("$2").command("/plot setup generator " + entry.getKey())
|
||||
.text(" (Default Generator)").color("$7");
|
||||
} else if (entry.getValue().isFull()) {
|
||||
plotMessage.text(entry.getKey()).color("$8").tooltip("Select this generator")
|
||||
.color("$7").command("/plot setup generator " + entry.getKey())
|
||||
.text(" (Plot Generator)").color("$7");
|
||||
} else {
|
||||
plotMessage.text(entry.getKey()).color("$8").tooltip("Select this generator")
|
||||
.color("$7").command("/plot setup generator " + entry.getKey())
|
||||
.text(" (Unknown Structure)").color("$7");
|
||||
}
|
||||
messages.add(plotMessage);
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Override public boolean parseInut(String input) {
|
||||
this.generator = input.toLowerCase();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable @Override public String getDefault() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class StepWorldType extends SetupStep {
|
||||
|
||||
private static final Map<String, String> WORLD_TYPES = new HashMap<>();
|
||||
|
||||
static {
|
||||
WORLD_TYPES.put("default", "Standard plot generation");
|
||||
WORLD_TYPES.put("augmented", "Plot generation with vanilla terrain");
|
||||
WORLD_TYPES.put("partial", "Vanilla clusters of plots");
|
||||
}
|
||||
|
||||
@Getter private String worldType;
|
||||
|
||||
public StepWorldType() {
|
||||
super("type");
|
||||
}
|
||||
|
||||
@Override public Collection<PlotMessage> showDescriptionMessage() {
|
||||
final List<PlotMessage> messages = new ArrayList<>();
|
||||
messages.add(new PlotMessage("What world type do you want?").color("$6"));
|
||||
for (final Map.Entry<String, String> worldType : WORLD_TYPES.entrySet()) {
|
||||
messages.add(new PlotMessage(" - ").color("$8").text(worldType.getKey())
|
||||
.color(worldType.getKey().equals(getDefault()) ? "$2" : "$7")
|
||||
.tooltip("Select this world type")
|
||||
.command("/plot setup type " + worldType.getKey())
|
||||
.text(" (" + worldType.getValue() + ")").color("$7"));
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Override public boolean parseInut(String input) {
|
||||
if (!WORLD_TYPES.keySet().contains(input.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
this.worldType = input.toLowerCase();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public String getDefault() {
|
||||
return "default";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ToString @EqualsAndHashCode(of = "uuid") @AllArgsConstructor
|
||||
private static class SetupContext {
|
||||
|
||||
private final UUID uuid;
|
||||
|
||||
@Getter private String step;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
private abstract static class SetupStep {
|
||||
|
||||
private final String stepName;
|
||||
|
||||
public abstract Collection<PlotMessage> showDescriptionMessage();
|
||||
|
||||
public abstract boolean parseInut(String input);
|
||||
|
||||
public final PlotMessage getUsage() {
|
||||
return new PlotMessage("Usage: ").color("$1")
|
||||
.text("/plot setup " + this.stepName + " <value>").color("$2").suggest(
|
||||
"/plot setup " + this.stepName + (this.getDefault() != null ?
|
||||
this.getDefault() :
|
||||
""));
|
||||
}
|
||||
|
||||
@Nullable public abstract String getDefault();
|
||||
|
||||
public void sendToPlayer(@NonNull final PlotPlayer plotPlayer) {
|
||||
new PlotMessage("Setup Step: ").color("$6").text(this.stepName).color("$7")
|
||||
.send(plotPlayer);
|
||||
this.getUsage().send(plotPlayer);
|
||||
this.showDescriptionMessage().forEach(plotMessage -> plotMessage.send(plotPlayer));
|
||||
if (this.getDefault() != null) {
|
||||
new PlotMessage("Default: ").color("$6").text(this.getDefault()).color("$7");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.Argument;
|
||||
import com.github.intellectualsites.plotsquared.commands.Command;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
|
||||
|
||||
/**
|
||||
* SubCommand class
|
||||
*
|
||||
* @Deprecated In favor of normal Command class
|
||||
* @see Command(Command, boolean)
|
||||
*/
|
||||
public abstract class SubCommand extends Command {
|
||||
public SubCommand() {
|
||||
super(MainCommand.getInstance(), true);
|
||||
}
|
||||
|
||||
public SubCommand(Argument... arguments) {
|
||||
this();
|
||||
setRequiredArguments(arguments);
|
||||
}
|
||||
|
||||
@Override public void execute(PlotPlayer player, String[] args,
|
||||
RunnableVal3<Command, Runnable, Runnable> confirm,
|
||||
RunnableVal2<Command, CommandResult> whenDone) {
|
||||
onCommand(player, args);
|
||||
}
|
||||
|
||||
|
||||
public abstract boolean onCommand(PlotPlayer player, String[] args);
|
||||
|
||||
public boolean sendMessage(PlotPlayer player, C message, Object... args) {
|
||||
message.send(player, args);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.github.intellectualsites.plotsquared.plot.commands;
|
||||
|
||||
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
||||
import com.github.intellectualsites.plotsquared.plot.config.C;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Location;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.Plot;
|
||||
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
|
||||
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
|
||||
|
||||
@CommandDeclaration(usage = "/plot swap <X;Z>", command = "swap", description = "Swap two plots",
|
||||
aliases = {"switch"}, category = CommandCategory.CLAIMING, requiredType = RequiredType.NONE)
|
||||
public class Swap extends SubCommand {
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
|
||||
Location loc = player.getLocation();
|
||||
Plot plot1 = loc.getPlotAbs();
|
||||
if (plot1 == null) {
|
||||
return !MainUtil.sendMessage(player, C.NOT_IN_PLOT);
|
||||
}
|
||||
if (!plot1.isOwner(player.getUUID()) && !Permissions
|
||||
.hasPermission(player, C.PERMISSION_ADMIN.s())) {
|
||||
MainUtil.sendMessage(player, C.NO_PLOT_PERMS);
|
||||
return false;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
C.COMMAND_SYNTAX.send(player, getUsage());
|
||||
return false;
|
||||
}
|
||||
Plot plot2 = MainUtil.getPlotFromString(player, args[0], true);
|
||||
if (plot2 == null) {
|
||||
return false;
|
||||
}
|
||||
if (plot1.equals(plot2)) {
|
||||
MainUtil.sendMessage(player, C.NOT_VALID_PLOT_ID);
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot copy <X;Z>");
|
||||
return false;
|
||||
}
|
||||
if (!plot1.getArea().isCompatible(plot2.getArea())) {
|
||||
C.PLOTWORLD_INCOMPATIBLE.send(player);
|
||||
return false;
|
||||
}
|
||||
if (plot1.move(plot2, new Runnable() {
|
||||
@Override public void run() {
|
||||
MainUtil.sendMessage(player, C.SWAP_SUCCESS);
|
||||
}
|
||||
}, true)) {
|
||||
return true;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, C.SWAP_OVERLAP);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user