Optimize auto trim + command cost/confirmation

This commit is contained in:
Jesse Boyd 2016-05-22 05:29:19 +10:00
parent e2182260d9
commit b8afbe8a00
16 changed files with 325 additions and 745 deletions

View File

@ -44,7 +44,6 @@ import com.plotsquared.bukkit.listeners.PlayerEvents_1_8;
import com.plotsquared.bukkit.listeners.PlayerEvents_1_9; import com.plotsquared.bukkit.listeners.PlayerEvents_1_9;
import com.plotsquared.bukkit.listeners.PlotPlusListener; import com.plotsquared.bukkit.listeners.PlotPlusListener;
import com.plotsquared.bukkit.listeners.WorldEvents; import com.plotsquared.bukkit.listeners.WorldEvents;
import com.plotsquared.bukkit.listeners.worldedit.WEListener;
import com.plotsquared.bukkit.titles.DefaultTitle_19; import com.plotsquared.bukkit.titles.DefaultTitle_19;
import com.plotsquared.bukkit.util.BukkitChatManager; import com.plotsquared.bukkit.util.BukkitChatManager;
import com.plotsquared.bukkit.util.BukkitChunkManager; import com.plotsquared.bukkit.util.BukkitChunkManager;
@ -387,7 +386,6 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
public boolean initWorldEdit() { public boolean initWorldEdit() {
if (getServer().getPluginManager().getPlugin("WorldEdit") != null) { if (getServer().getPluginManager().getPlugin("WorldEdit") != null) {
worldEdit = (WorldEditPlugin) getServer().getPluginManager().getPlugin("WorldEdit"); worldEdit = (WorldEditPlugin) getServer().getPluginManager().getPlugin("WorldEdit");
getServer().getPluginManager().registerEvents(new WEListener(), this);
return true; return true;
} }
return false; return false;

View File

@ -1,18 +1,15 @@
package com.plotsquared.bukkit.listeners; package com.plotsquared.bukkit.listeners;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.Settings; import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass; import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField; import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod; import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler; import java.lang.reflect.Method;
import java.util.HashSet;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Material; import org.bukkit.Material;
@ -31,9 +28,8 @@ import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.event.world.ChunkUnloadEvent;
import java.util.ArrayDeque;
import java.util.HashMap; import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import java.util.Map.Entry;
public class ChunkListener implements Listener { public class ChunkListener implements Listener {
@ -43,7 +39,7 @@ public class ChunkListener implements Listener {
public ChunkListener() { public ChunkListener() {
if (Settings.CHUNK_PROCESSOR_GC || Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE) { if (Settings.CHUNK_PROCESSOR_GC) {
try { try {
RefClass classChunk = getRefClass("{nms}.Chunk"); RefClass classChunk = getRefClass("{nms}.Chunk");
RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
@ -52,130 +48,60 @@ public class ChunkListener implements Listener {
} catch (Throwable ignored) { } catch (Throwable ignored) {
PS.debug("PlotSquared/Server not compatible for chunk processor trim/gc"); PS.debug("PlotSquared/Server not compatible for chunk processor trim/gc");
Settings.CHUNK_PROCESSOR_GC = false; Settings.CHUNK_PROCESSOR_GC = false;
Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE = false;
} }
} }
if (!Settings.CHUNK_PROCESSOR_GC) { if (!Settings.CHUNK_PROCESSOR_GC) {
return; return;
} }
TaskManager.runTask(new Runnable() { for (World world : Bukkit.getWorlds()) {
world.setAutoSave(false);
}
TaskManager.runTaskRepeat(new Runnable() {
@Override @Override
public void run() { public void run() {
int distance = Bukkit.getViewDistance() + 2; try {
HashMap<String, HashMap<ChunkLoc, Integer>> players = new HashMap<>(); HashSet<Chunk> toUnload = new HashSet<>();
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) { for (World world : Bukkit.getWorlds()) {
PlotPlayer pp = entry.getValue(); String worldName = world.getName();
Location location = pp.getLocation(); if (!PS.get().hasPlotArea(worldName)) {
String world = location.getWorld();
if (!PS.get().hasPlotArea(world)) {
continue;
}
HashMap<ChunkLoc, Integer> map = players.get(world);
if (map == null) {
map = new HashMap<>();
players.put(world, map);
}
ChunkLoc origin = new ChunkLoc(location.getX() >> 4, location.getZ() >> 4);
Integer val = map.get(origin);
int check;
if (val != null) {
if (val == distance) {
continue; continue;
} }
check = distance - val; Object w = world.getClass().getDeclaredMethod("getHandle").invoke(world);
} else { Object chunkMap = w.getClass().getDeclaredMethod("getPlayerChunkMap").invoke(w);
check = distance; Method methodIsChunkInUse = chunkMap.getClass().getDeclaredMethod("isChunkInUse", int.class, int.class);
map.put(origin, distance); Chunk[] chunks = world.getLoadedChunks();
} for (Chunk chunk : chunks) {
for (int x = -distance; x <= distance; x++) { if ((boolean) methodIsChunkInUse.invoke(chunkMap, chunk.getX(), chunk.getZ())) {
if (x >= check || -x >= check) {
continue;
}
for (int z = -distance; z <= distance; z++) {
if (z >= check || -z >= check) {
continue; continue;
} }
int weight = distance - Math.max(Math.abs(x), Math.abs(z)); int x = chunk.getX();
ChunkLoc chunk = new ChunkLoc(x + origin.x, z + origin.z); int z = chunk.getZ();
val = map.get(chunk); if (!shouldSave(worldName, x, z)) {
if (val == null || val < weight) { unloadChunk(worldName, chunk, false);
map.put(chunk, weight); continue;
} }
}
}
}
int time = 300;
for (World world : Bukkit.getWorlds()) {
String name = world.getName();
if (!PS.get().hasPlotArea(name)) {
continue;
}
boolean autoSave = world.isAutoSave();
if (autoSave) {
world.setAutoSave(false);
}
HashMap<ChunkLoc, Integer> map = players.get(name);
if (map == null || map.isEmpty()) {
continue;
}
Chunk[] chunks = world.getLoadedChunks();
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();
for (Chunk chunk : chunks) {
int x = chunk.getX();
int z = chunk.getZ();
if (!map.containsKey(new ChunkLoc(x, z))) {
toUnload.add(chunk); toUnload.add(chunk);
} }
} }
if (!toUnload.isEmpty()) { if (toUnload.isEmpty()) {
long start = System.currentTimeMillis(); return;
Chunk chunk;
while ((chunk = toUnload.poll()) != null && System.currentTimeMillis() - start < 5) {
if (!Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE || !unloadChunk(name, chunk)) {
if (chunk.isLoaded()) {
chunk.unload(true, false);
}
}
}
if (!toUnload.isEmpty()) {
time = 1;
}
} }
if (!Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE && autoSave) { long start = System.currentTimeMillis();
world.setAutoSave(true); for (Chunk chunk : toUnload) {
if (System.currentTimeMillis() - start > 5) {
return;
}
chunk.unload(true, false);
} }
} catch (Throwable e) {
e.printStackTrace();
} }
TaskManager.runTaskLater(this, time);
} }
}); }, 1);
} }
public boolean unloadChunk(String world, Chunk chunk) { public boolean unloadChunk(String world, Chunk chunk, boolean safe) {
int X = chunk.getX(); if (safe && shouldSave(world, chunk.getX(), chunk.getZ())) {
int Z = chunk.getZ();
int x = X << 4;
int z = Z << 4;
int x2 = x + 15;
int z2 = z + 15;
Plot plot = new Location(world, x, 1, z).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return false;
}
plot = new Location(world, x2, 1, z2).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return false;
}
plot = new Location(world, x2, 1, z).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return false;
}
plot = new Location(world, x, 1, z2).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return false;
}
plot = new Location(world, x + 7, 1, z + 7).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return false; return false;
} }
Object c = this.methodGetHandleChunk.of(chunk).call(); Object c = this.methodGetHandleChunk.of(chunk).call();
@ -185,14 +111,42 @@ public class ChunkListener implements Listener {
} }
return true; return true;
} }
public boolean shouldSave(String world, int X, int Z) {
int x = X << 4;
int z = Z << 4;
int x2 = x + 15;
int z2 = z + 15;
Plot plot = new Location(world, x, 1, z).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return true;
}
plot = new Location(world, x2, 1, z2).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return true;
}
plot = new Location(world, x2, 1, z).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return true;
}
plot = new Location(world, x, 1, z2).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return true;
}
plot = new Location(world, x + 7, 1, z + 7).getOwnedPlotAbs();
if (plot != null && plot.hasOwner()) {
return true;
}
return false;
}
@EventHandler @EventHandler
public void onChunkUnload(ChunkUnloadEvent event) { public void onChunkUnload(ChunkUnloadEvent event) {
if (Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE) { if (Settings.CHUNK_PROCESSOR_GC) {
Chunk chunk = event.getChunk(); Chunk chunk = event.getChunk();
String world = chunk.getWorld().getName(); String world = chunk.getWorld().getName();
if (PS.get().hasPlotArea(world)) { if (PS.get().hasPlotArea(world)) {
if (unloadChunk(world, chunk)) { if (unloadChunk(world, chunk, true)) {
return; return;
} }
} }

View File

@ -1,330 +0,0 @@
package com.plotsquared.bukkit.listeners.worldedit;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SetQueue;
import com.plotsquared.bukkit.BukkitMain;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.listener.WEManager;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.selections.Selection;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class WEListener implements Listener {
public final Set<String> other = new HashSet<>(Arrays.asList("undo", "redo"));
private final Set<String> rad1 = new HashSet<>(
Arrays.asList("forestgen", "pumpkins", "drain", "fixwater", "fixlava", "replacenear", "snow", "thaw", "ex", "butcher", "size"));
private final Set<String> rad2 = new HashSet<>(Arrays.asList("fill", "fillr", "removenear", "remove"));
private final Set<String> rad2_1 = new HashSet<>(Arrays.asList("hcyl", "cyl"));
private final Set<String> rad2_2 = new HashSet<>(Arrays.asList("sphere", "pyramid"));
private final Set<String> rad2_3 = Collections.singleton("brush smooth");
private final Set<String> rad3_1 = Collections.singleton("brush gravity");
private final Set<String> rad3_2 = new HashSet<>(Arrays.asList("brush sphere", "brush cylinder"));
private final Set<String> region = new HashSet<>(
Arrays.asList("move", "set", "replace", "overlay", "walls", "outline", "deform", "hollow", "smooth", "naturalize", "paste", "count",
"distr",
"regen", "copy", "cut", "green", "setbiome"));
private final Set<String> regionExtend = Collections.singleton("stack");
private final Set<String> restricted = Collections.singleton("up");
public String reduceCmd(String cmd, boolean single) {
if (cmd.startsWith("/worldedit:/")) {
return cmd.substring(12);
}
if (cmd.startsWith("/worldedit:")) {
return cmd.substring(11);
}
if (cmd.startsWith("//")) {
return cmd.substring(2);
}
if (single && cmd.startsWith("/")) {
return cmd.substring(1);
}
return cmd;
}
public int getInt(String s) {
try {
int max = 0;
String[] split = s.split(",");
for (String rad : split) {
int val = Integer.parseInt(rad);
if (val > max) {
max = val;
}
}
return max;
} catch (NumberFormatException ignored) {
return 0;
}
}
public boolean checkVolume(PlotPlayer player, long volume, long max, Cancellable e) {
if (volume > max) {
MainUtil.sendMessage(player, C.WORLDEDIT_VOLUME.s().replaceAll("%current%", String.valueOf(volume)).replaceAll("%max%", String.valueOf(max)));
e.setCancelled(true);
}
if (Permissions.hasPermission(player, "plots.worldedit.bypass")) {
MainUtil.sendMessage(player, C.WORLDEDIT_BYPASS);
}
return true;
}
public boolean checkSelection(Player p, PlotPlayer pp, int modifier, long max, Cancellable e) {
Selection selection = BukkitMain.worldEdit.getSelection(p);
if (selection == null) {
return true;
}
BlockVector pos1 = selection.getNativeMinimumPoint().toBlockVector();
BlockVector pos2 = selection.getNativeMaximumPoint().toBlockVector();
HashSet<RegionWrapper> mask = WEManager.getMask(pp);
RegionWrapper region = new RegionWrapper(pos1.getBlockX(), pos2.getBlockX(), pos1.getBlockZ(), pos2.getBlockZ());
if (Settings.REQUIRE_SELECTION) {
String arg = null;
if (!WEManager.regionContains(region, mask)) {
arg = "pos1 + pos2";
} else if (!WEManager.maskContains(mask, pos1.getBlockX(), pos1.getBlockY(), pos1.getBlockZ())) {
arg = "pos1";
} else if (!WEManager.maskContains(mask, pos2.getBlockX(), pos2.getBlockY(), pos2.getBlockZ())) {
arg = "pos2";
}
if (arg != null) {
e.setCancelled(true);
MainUtil.sendMessage(pp, C.REQUIRE_SELECTION_IN_MASK, arg);
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
}
return true;
}
if (!WEManager.regionContains(region, mask)) {
MainUtil.sendMessage(pp, C.REQUIRE_SELECTION_IN_MASK, "pos1 + pos2");
e.setCancelled(true);
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
}
return true;
}
}
long volume = Math.abs((pos1.getBlockX() - pos2.getBlockX()) * (pos1.getBlockY() - pos2.getBlockY()) * (pos1.getBlockZ() - pos2.getBlockZ()))
* modifier;
return checkVolume(pp, volume, max, e);
}
public boolean delay(final Player player, final String command, boolean delayed) {
if (!Settings.QUEUE_COMMANDS || !Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT) {
return false;
}
boolean free = SetQueue.IMP.addTask(null);
if (free) {
if (delayed) {
MainUtil.sendMessage(BukkitUtil.getPlayer(player), C.WORLDEDIT_RUN, command);
Bukkit.getServer().dispatchCommand(player, command.substring(1));
} else {
return false;
}
} else {
if (!delayed) {
MainUtil.sendMessage(BukkitUtil.getPlayer(player), C.WORLDEDIT_DELAYED);
}
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
delay(player, command, true);
}
});
}
return true;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public boolean onPlayerCommand(PlayerCommandPreprocessEvent e) {
WorldEditPlugin worldedit = BukkitMain.worldEdit;
if (worldedit == null) {
HandlerList.unregisterAll(this);
return true;
}
Player p = e.getPlayer();
PlotPlayer pp = BukkitUtil.getPlayer(p);
if (!PS.get().hasPlotArea(p.getWorld().getName())) {
return true;
}
String message = e.getMessage();
String cmd = message.toLowerCase();
String[] split = cmd.split(" ");
long maxVolume = Settings.WE_MAX_VOLUME;
long maxIterations = Settings.WE_MAX_ITERATIONS;
if (pp.getAttribute("worldedit")) {
return true;
}
boolean single = true;
if (split.length >= 2) {
String reduced = reduceCmd(split[0], single);
String reduced2 = reduceCmd(split[0] + ' ' + split[1], single);
if (this.rad1.contains(reduced)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
long volume = getInt(split[1]) * 256;
return checkVolume(pp, volume, maxVolume, e);
}
if (this.rad2.contains(reduced)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
if (split.length >= 3) {
long volume = getInt(split[2]) * 256;
return checkVolume(pp, volume, maxVolume, e);
}
return true;
}
if (this.rad2_1.contains(reduced)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
if (split.length >= 4) {
long volume = getInt(split[2]) * getInt(split[3]);
return checkVolume(pp, volume, maxVolume, e);
}
return true;
}
if (this.rad2_2.contains(reduced)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
if (split.length >= 3) {
long radius = getInt(split[2]);
long volume = radius * radius;
return checkVolume(pp, volume, maxVolume, e);
}
return true;
}
if (this.rad2_3.contains(reduced2)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
if (split.length >= 3) {
if (split.length == 4) {
int iterations = getInt(split[3]);
if (iterations > maxIterations) {
MainUtil.sendMessage(pp,
C.WORLDEDIT_ITERATIONS.s().replaceAll("%current%", String.valueOf(iterations)).replaceAll("%max%",
String.valueOf(maxIterations)));
e.setCancelled(true);
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
}
return true;
}
}
long radius = getInt(split[2]);
long volume = radius * radius;
return checkVolume(pp, volume, maxVolume, e);
}
return true;
}
if (this.rad3_1.contains(reduced2)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
if (split.length >= 3) {
int i = 2;
if (split[i].equalsIgnoreCase("-h")) {
i = 3;
}
long radius = getInt(split[i]);
long volume = radius * radius;
return checkVolume(pp, volume, maxVolume, e);
}
return true;
}
if (this.rad3_2.contains(reduced2)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
if (split.length >= 4) {
int i = 3;
if (split[i].equalsIgnoreCase("-h")) {
i = 4;
}
long radius = getInt(split[i]);
long volume = radius * radius;
return checkVolume(pp, volume, maxVolume, e);
}
return true;
}
if (this.regionExtend.contains(reduced)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
return checkSelection(p, pp, getInt(split[1]), maxVolume, e);
}
}
String reduced = reduceCmd(split[0], single);
if (Settings.WE_BLACKLIST.contains(reduced)) {
MainUtil.sendMessage(pp, C.WORLDEDIT_UNSAFE);
e.setCancelled(true);
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
}
}
if (this.restricted.contains(reduced)) {
Plot plot = pp.getCurrentPlot();
if ((plot != null) && plot.isAdded(pp.getUUID())) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
return true;
}
e.setCancelled(true);
MainUtil.sendMessage(pp, C.NO_PLOT_PERMS);
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
}
return true;
}
if (this.region.contains(reduced)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
return checkSelection(p, pp, 1, maxVolume, e);
}
if (this.other.contains(reduced)) {
if (delay(p, message, false)) {
e.setCancelled(true);
return true;
}
}
return true;
}
}

View File

@ -43,7 +43,7 @@ public interface Configuration extends ConfigurationSection {
* *
* <p>This method will not hold a reference to the specified Configuration, * <p>This method will not hold a reference to the specified Configuration,
* nor will it automatically update if that Configuration ever changes. If * nor will it automatically update if that Configuration ever changes. If
* you require this, you should set the default source with {@link * you check this, you should set the default source with {@link
* #setDefaults(Configuration)}.</p> * #setDefaults(Configuration)}.</p>
* *
* @param defaults A configuration holding a list of defaults to copy. * @param defaults A configuration holding a list of defaults to copy.

View File

@ -1903,7 +1903,7 @@ public class PS {
this.config.set("clear.ignore-if-modified", null); this.config.set("clear.ignore-if-modified", null);
// Done // Done
options.put("approval.ratings.require-done", Settings.REQUIRE_DONE); options.put("approval.ratings.check-done", Settings.REQUIRE_DONE);
options.put("approval.done.counts-towards-limit", Settings.DONE_COUNTS_TOWARDS_LIMIT); options.put("approval.done.counts-towards-limit", Settings.DONE_COUNTS_TOWARDS_LIMIT);
options.put("approval.done.restrict-building", Settings.DONE_RESTRICTS_BUILDING); options.put("approval.done.restrict-building", Settings.DONE_RESTRICTS_BUILDING);
options.put("approval.done.required-for-download", Settings.DOWNLOAD_REQUIRES_DONE); options.put("approval.done.required-for-download", Settings.DOWNLOAD_REQUIRES_DONE);
@ -1932,18 +1932,13 @@ public class PS {
options.put("teleport.delay", Settings.TELEPORT_DELAY); options.put("teleport.delay", Settings.TELEPORT_DELAY);
// WorldEdit // WorldEdit
options.put("worldedit.require-selection-in-mask", Settings.REQUIRE_SELECTION);
options.put("worldedit.queue-commands", Settings.QUEUE_COMMANDS);
options.put("worldedit.enable-for-helpers", Settings.WE_ALLOW_HELPER); options.put("worldedit.enable-for-helpers", Settings.WE_ALLOW_HELPER);
options.put("worldedit.max-volume", Settings.WE_MAX_VOLUME);
options.put("worldedit.max-iterations", Settings.WE_MAX_ITERATIONS);
options.put("worldedit.blacklist", Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks")); options.put("worldedit.blacklist", Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks"));
// Chunk processor // Chunk processor
options.put("chunk-processor.enabled", Settings.CHUNK_PROCESSOR); options.put("chunk-processor.enabled", Settings.CHUNK_PROCESSOR);
options.put("chunk-processor.auto-unload", Settings.CHUNK_PROCESSOR_GC); options.put("chunk-processor.auto-unload", Settings.CHUNK_PROCESSOR_GC);
options.put("chunk-processor.experimental-fast-async-worldedit", Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT); options.put("chunk-processor.experimental-fast-async-worldedit", Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT);
options.put("chunk-processor.auto-trim", Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE);
options.put("chunk-processor.max-blockstates", Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES); options.put("chunk-processor.max-blockstates", Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES);
options.put("chunk-processor.max-entities", Settings.CHUNK_PROCESSOR_MAX_ENTITIES); options.put("chunk-processor.max-entities", Settings.CHUNK_PROCESSOR_MAX_ENTITIES);
options.put("chunk-processor.disable-physics", Settings.CHUNK_PROCESSOR_DISABLE_PHYSICS); options.put("chunk-processor.disable-physics", Settings.CHUNK_PROCESSOR_DISABLE_PHYSICS);
@ -2011,7 +2006,7 @@ public class PS {
Settings.AUTO_CLEAR_CONFIRMATION = this.config.getBoolean("clear.auto.confirmation"); // TODO FIXME Settings.AUTO_CLEAR_CONFIRMATION = this.config.getBoolean("clear.auto.confirmation"); // TODO FIXME
// Done // Done
Settings.REQUIRE_DONE = this.config.getBoolean("approval.ratings.require-done"); Settings.REQUIRE_DONE = this.config.getBoolean("approval.ratings.check-done");
Settings.DONE_COUNTS_TOWARDS_LIMIT = this.config.getBoolean("approval.done.counts-towards-limit"); Settings.DONE_COUNTS_TOWARDS_LIMIT = this.config.getBoolean("approval.done.counts-towards-limit");
Settings.DONE_RESTRICTS_BUILDING = this.config.getBoolean("approval.done.restrict-building"); Settings.DONE_RESTRICTS_BUILDING = this.config.getBoolean("approval.done.restrict-building");
Settings.DOWNLOAD_REQUIRES_DONE = this.config.getBoolean("approval.done.required-for-download"); Settings.DOWNLOAD_REQUIRES_DONE = this.config.getBoolean("approval.done.required-for-download");
@ -2042,17 +2037,11 @@ public class PS {
Settings.TELEPORT_ON_DEATH = this.config.getBoolean("teleport.on_death"); Settings.TELEPORT_ON_DEATH = this.config.getBoolean("teleport.on_death");
// WorldEdit // WorldEdit
Settings.QUEUE_COMMANDS = this.config.getBoolean("worldedit.queue-commands");
Settings.REQUIRE_SELECTION = this.config.getBoolean("worldedit.require-selection-in-mask");
Settings.WE_ALLOW_HELPER = this.config.getBoolean("worldedit.enable-for-helpers"); Settings.WE_ALLOW_HELPER = this.config.getBoolean("worldedit.enable-for-helpers");
Settings.WE_MAX_VOLUME = this.config.getLong("worldedit.max-volume");
Settings.WE_MAX_ITERATIONS = this.config.getLong("worldedit.max-iterations");
Settings.WE_BLACKLIST = this.config.getStringList("worldedit.blacklist");
// Chunk processor // Chunk processor
Settings.CHUNK_PROCESSOR = this.config.getBoolean("chunk-processor.enabled"); Settings.CHUNK_PROCESSOR = this.config.getBoolean("chunk-processor.enabled");
Settings.CHUNK_PROCESSOR_GC = this.config.getBoolean("chunk-processor.auto-unload"); Settings.CHUNK_PROCESSOR_GC = this.config.getBoolean("chunk-processor.auto-unload");
Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE = this.config.getBoolean("chunk-processor.auto-trim");
Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT = this.config.getBoolean("chunk-processor.experimental-fast-async-worldedit"); Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT = this.config.getBoolean("chunk-processor.experimental-fast-async-worldedit");
Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES = this.config.getInt("chunk-processor.max-blockstates"); Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES = this.config.getInt("chunk-processor.max-blockstates");
Settings.CHUNK_PROCESSOR_MAX_ENTITIES = this.config.getInt("chunk-processor.max-entities"); Settings.CHUNK_PROCESSOR_MAX_ENTITIES = this.config.getInt("chunk-processor.max-entities");

View File

@ -2,13 +2,14 @@ package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal2;
import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.Argument; import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
@ -22,67 +23,57 @@ import java.util.UUID;
category = CommandCategory.SETTINGS, category = CommandCategory.SETTINGS,
permission = "plots.add", permission = "plots.add",
requiredType = RequiredType.PLAYER) requiredType = RequiredType.PLAYER)
public class Add extends SubCommand { public class Add extends Command {
public Add() { public Add() {
super(Argument.PlayerName); super(MainCommand.getInstance(), true);
} }
@Override @Override
public boolean onCommand(PlotPlayer plr, String[] args) { public void execute(final PlotPlayer player, String[] args, RunnableVal3<Command, Runnable, Runnable> confirm, RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
Location loc = plr.getLocation(); final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
Plot plot = loc.getPlotAbs(); checkTrue(plot.hasOwner(), C.PLOT_UNOWNED);
if (plot == null) { checkTrue(plot.isOwner(player.getUUID()) || Permissions.hasPermission(player, "plots.admin.command.trust"), C.NO_PLOT_PERMS);
return !sendMessage(plr, C.NOT_IN_PLOT); checkTrue(args.length == 1, C.COMMAND_SYNTAX, getUsage());
} final Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
if (!plot.hasOwner()) { checkTrue(uuids != null && !uuids.isEmpty(), C.INVALID_PLAYER, args[0]);
MainUtil.sendMessage(plr, C.PLOT_UNOWNED);
return false;
}
if (!plot.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, "plots.admin.command.add")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return true;
}
Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
if (uuids == null || uuids.isEmpty()) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[0]);
return false;
}
Iterator<UUID> iter = uuids.iterator(); Iterator<UUID> iter = uuids.iterator();
int size = plot.getTrusted().size() + plot.getMembers().size();
while (iter.hasNext()) { while (iter.hasNext()) {
UUID uuid = iter.next(); UUID uuid = iter.next();
if (uuid == DBFunc.everyone && !(Permissions.hasPermission(plr, "plots.add.everyone") || Permissions.hasPermission(plr, "plots.admin.command.add"))) { if (uuid == DBFunc.everyone && !(Permissions.hasPermission(player, "plots.trust.everyone") || Permissions.hasPermission(player, "plots.admin.command.trust"))) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, MainUtil.getName(uuid)); MainUtil.sendMessage(player, C.INVALID_PLAYER, MainUtil.getName(uuid));
iter.remove();
continue; continue;
} }
if (plot.isOwner(uuid)) { if (plot.isOwner(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_OWNER, MainUtil.getName(uuid)); MainUtil.sendMessage(player, C.ALREADY_OWNER, MainUtil.getName(uuid));
iter.remove(); iter.remove();
continue; continue;
} }
if (plot.getMembers().contains(uuid)) { if (plot.getMembers().contains(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_ADDED, MainUtil.getName(uuid)); MainUtil.sendMessage(player, C.ALREADY_ADDED, MainUtil.getName(uuid));
iter.remove(); iter.remove();
continue; continue;
} }
if (plot.removeTrusted(uuid)) { size += plot.getTrusted().contains(uuid) ? 0 : 1;
plot.addMember(uuid); }
} else { checkTrue(!uuids.isEmpty(), null);
if ((plot.getMembers().size() + plot.getTrusted().size()) >= plot.getArea().MAX_PLOT_MEMBERS) { checkTrue(size <= plot.getArea().MAX_PLOT_MEMBERS, C.PLOT_MAX_MEMBERS);
MainUtil.sendMessage(plr, C.PLOT_MAX_MEMBERS); confirm.run(this, new Runnable() {
iter.remove(); @Override // Success
continue; public void run() {
for (UUID uuid : uuids) {
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);
} }
if (plot.getDenied().contains(uuid)) {
plot.removeDenied(uuid);
}
plot.addMember(uuid);
} }
EventUtil.manager.callMember(plr, plot, uuid, true); }, null);
}
if (!uuids.isEmpty()) {
MainUtil.sendMessage(plr, C.MEMBER_ADDED);
}
return true;
} }
} }

View File

@ -1,17 +1,17 @@
package com.intellectualcrafters.plot.commands; package com.intellectualcrafters.plot.commands;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.flag.Flags; import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal2;
import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.EconHandler; import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.util.Set; import java.util.Set;
@CommandDeclaration( @CommandDeclaration(
@ -22,67 +22,51 @@ import java.util.Set;
permission = "plots.buy", permission = "plots.buy",
category = CommandCategory.CLAIMING, category = CommandCategory.CLAIMING,
requiredType = RequiredType.NONE) requiredType = RequiredType.NONE)
public class Buy extends SubCommand { public class Buy extends Command {
public Buy() {
super(MainCommand.getInstance(), true);
}
@Override @Override
public boolean onCommand(PlotPlayer plr, String[] args) { public void execute(final PlotPlayer player, String[] args, RunnableVal3<Command, Runnable, Runnable> confirm, final RunnableVal2<Command, CommandResult> whenDone) {
if (EconHandler.manager == null) { check(EconHandler.manager, C.ECON_DISABLED);
return sendMessage(plr, C.ECON_DISABLED); final Plot plot;
} if (args.length != 0) {
Location loc = plr.getLocation(); check(args.length == 1, C.COMMAND_SYNTAX, getUsage());
String world = loc.getWorld(); plot = check(MainUtil.getPlotFromString(player, args[0], true), null);
if (!PS.get().hasPlotArea(world)) {
return sendMessage(plr, C.NOT_IN_PLOT_WORLD);
}
Set<Plot> plots;
Plot plot;
if (args.length > 0) {
try {
plot = MainUtil.getPlotFromString(plr, world, true);
if (plot == null) {
return false;
}
plots = plot.getConnectedPlots();
} catch (Exception ignored) {
return sendMessage(plr, C.NOT_VALID_PLOT_ID);
}
} else { } else {
plot = loc.getPlotAbs(); plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
plots = plot != null ? plot.getConnectedPlots() : null;
}
if (plots == null) {
return sendMessage(plr, C.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
return sendMessage(plr, C.PLOT_UNOWNED);
}
int currentPlots = plr.getPlotCount() + plots.size();
if (currentPlots > plr.getAllowedPlots()) {
return sendMessage(plr, C.CANT_CLAIM_MORE_PLOTS);
} }
check(plot.hasOwner(), C.PLOT_UNOWNED);
check(!plot.isOwner(player.getUUID()), C.CANNOT_BUY_OWN);
Set<Plot> plots = plot.getConnectedPlots();
check(player.getPlotCount() + plots.size() <= player.getAllowedPlots(), C.CANT_CLAIM_MORE_PLOTS);
Optional<Double> flag = plot.getFlag(Flags.PRICE); Optional<Double> flag = plot.getFlag(Flags.PRICE);
if (!flag.isPresent()) { check(flag.isPresent(), C.NOT_FOR_SALE);
return sendMessage(plr, C.NOT_FOR_SALE); final double price = flag.get();
} check(player.getMoney() >= price, C.CANNOT_AFFORD_PLOT);
if (plot.isOwner(plr.getUUID())) { player.withdraw(price);
return sendMessage(plr, C.CANNOT_BUY_OWN); confirm.run(this, new Runnable() {
} @Override // Success
double price = flag.get(); public void run() {
if ((EconHandler.manager != null) && (price > 0d)) { C.REMOVED_BALANCE.send(player, price);
if (EconHandler.manager.getMoney(plr) < price) { EconHandler.manager.depositMoney(UUIDHandler.getUUIDWrapper().getOfflinePlayer(plot.owner), price);
return sendMessage(plr, C.CANNOT_AFFORD_PLOT, "" + 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);
} }
EconHandler.manager.withdrawMoney(plr, price); }, new Runnable() {
sendMessage(plr, C.REMOVED_BALANCE, price + ""); @Override // Failure
EconHandler.manager.depositMoney(UUIDHandler.getUUIDWrapper().getOfflinePlayer(plot.owner), price); public void run() {
PlotPlayer owner = UUIDHandler.getPlayer(plot.owner); player.deposit(price);
if (owner != null) { whenDone.run(Buy.this, CommandResult.FAILURE);
sendMessage(plr, C.PLOT_SOLD, plot.getId() + "", plr.getName(), price + "");
} }
plot.removeFlag(Flags.PRICE); });
}
plot.setOwner(plr.getUUID());
MainUtil.sendMessage(plr, C.CLAIMED);
return true;
} }
} }

View File

@ -4,72 +4,40 @@ import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings; import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.flag.FlagManager; import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.flag.Flags; import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.CmdConfirm; import com.intellectualcrafters.plot.object.RunnableVal2;
import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SetQueue; import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.TaskManager; import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.util.Set;
@CommandDeclaration(command = "clear", @CommandDeclaration(command = "clear",
description = "Clear a plot", description = "Clear a plot",
permission = "plots.clear", permission = "plots.clear",
category = CommandCategory.APPEARANCE, category = CommandCategory.APPEARANCE,
usage = "/plot clear [id]", usage = "/plot clear",
aliases = "reset", aliases = "reset",
confirmation = true) confirmation = true)
public class Clear extends SubCommand { 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 @Override
public boolean onCommand(final PlotPlayer plr, String[] args) { public void execute(final PlotPlayer player, String[] args, RunnableVal3<Command, Runnable, Runnable> confirm, RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
Location loc = plr.getLocation(); checkTrue(args.length == 0, C.COMMAND_SYNTAX, getUsage());
final Plot plot; final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
if (args.length == 1) { checkTrue(plot.isOwner(player.getUUID()) || Permissions.hasPermission(player, "plots.admin.command.clear"), C.NO_PLOT_PERMS);
if (args[0].equalsIgnoreCase("mine")) { checkTrue(plot.getRunning() == 0, C.WAIT_FOR_TIMER);
Set<Plot> plots = plr.getPlots(); checkTrue((!Flags.DONE.isSet(plot) || Permissions.hasPermission(player, "plots.continue")) && (!Settings.DONE_COUNTS_TOWARDS_LIMIT || player.getAllowedPlots() >= player.getPlotCount() + plot.getConnectedPlots().size()), C.DONE_ALREADY_DONE);
if (!plots.isEmpty()) { confirm.run(this, new Runnable() {
plot = plots.iterator().next();
} else {
MainUtil.sendMessage(plr, C.NO_PLOTS);
return false;
}
} else {
plot = MainUtil.getPlotFromString(plr, args[0], true);
}
if (plot == null) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot clear [X;Z|mine]");
return false;
}
} else if (args.length == 0) {
plot = loc.getPlotAbs();
if (plot == null) {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot clear [X;Z|mine]");
C.NOT_IN_PLOT.send(plr);
return false;
}
} else {
MainUtil.sendMessage(plr, C.COMMAND_SYNTAX, "/plot clear [X;Z|mine]");
return false;
}
if ((!plot.hasOwner() || !plot.isOwner(plr.getUUID())) && !Permissions.hasPermission(plr, "plots.admin.command.clear")) {
return sendMessage(plr, C.NO_PLOT_PERMS);
}
if (plot.getRunning() != 0) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER);
return false;
}
if (plot.getFlag(Flags.DONE).isPresent()
&& (!Permissions.hasPermission(plr, "plots.continue") || (Settings.DONE_COUNTS_TOWARDS_LIMIT && (plr.getAllowedPlots() >= plr
.getPlotCount())))) {
MainUtil.sendMessage(plr, C.DONE_ALREADY_DONE);
return false;
}
Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
@ -88,23 +56,17 @@ public class Clear extends SubCommand {
if (plot.getFlag(Flags.ANALYSIS).isPresent()) { if (plot.getFlag(Flags.ANALYSIS).isPresent()) {
FlagManager.removePlotFlag(plot, Flags.ANALYSIS); FlagManager.removePlotFlag(plot, Flags.ANALYSIS);
} }
MainUtil.sendMessage(plr, C.CLEARING_DONE, "" + (System.currentTimeMillis() - start)); MainUtil.sendMessage(player, C.CLEARING_DONE, "" + (System.currentTimeMillis() - start));
} }
}); });
} }
}); });
if (!result) { if (!result) {
MainUtil.sendMessage(plr, C.WAIT_FOR_TIMER); MainUtil.sendMessage(player, C.WAIT_FOR_TIMER);
} else { } else {
plot.addRunning(); plot.addRunning();
} }
} }
}; }, null);
if (hasConfirmation(plr)) {
CmdConfirm.addPending(plr, "/plot clear " + plot.getId(), runnable);
} else {
TaskManager.runTask(runnable);
}
return true;
} }
} }

View File

@ -128,46 +128,58 @@ public class MainCommand extends Command {
args = tmp; args = tmp;
} }
} }
getInstance().execute(player, args, new RunnableVal3<Command, Runnable, Runnable>() { try {
@Override getInstance().execute(player, args, new RunnableVal3<Command, Runnable, Runnable>() {
public void run(final Command cmd, final Runnable success, final Runnable failure) { @Override
if (cmd.hasConfirmation(player) ) { public void run(final Command cmd, final Runnable success, final Runnable failure) {
CmdConfirm.addPending(player, cmd.getUsage(), new Runnable() { if (cmd.hasConfirmation(player)) {
@Override CmdConfirm.addPending(player, cmd.getUsage(), new Runnable() {
public void run() { @Override
if (EconHandler.manager != null) { public void run() {
PlotArea area = player.getApplicablePlotArea(); if (EconHandler.manager != null) {
if (area != null) { PlotArea area = player.getApplicablePlotArea();
Double price = area.PRICES.get(cmd.getFullId()); if (area != null) {
if (price != null && EconHandler.manager.getMoney(player) < price) { Double price = area.PRICES.get(cmd.getFullId());
failure.run(); if (price != null && EconHandler.manager.getMoney(player) < price) {
return; if (failure != null) {
failure.run();
}
return;
}
} }
} }
if (success != null) {
success.run();
}
}
});
return;
}
if (EconHandler.manager != null) {
PlotArea area = player.getApplicablePlotArea();
if (area != null) {
Double price = area.PRICES.get(cmd.getFullId());
if (price != null && EconHandler.manager.getMoney(player) < price) {
if (failure != null) {
failure.run();
}
return;
} }
success.run();
}
});
return;
}
if (EconHandler.manager != null) {
PlotArea area = player.getApplicablePlotArea();
if (area != null) {
Double price = area.PRICES.get(cmd.getFullId());
if (price != null && EconHandler.manager.getMoney(player) < price) {
failure.run();
return;
} }
} }
if (success != null) {
success.run();
}
} }
success.run(); }, new RunnableVal2<Command, CommandResult>() {
} @Override
}, new RunnableVal2<Command, CommandResult>() { public void run(Command cmd, CommandResult result) {
@Override // Post command stuff!?
public void run(Command cmd, CommandResult result) { }
// Post command stuff!? });
} } catch (CommandException e) {
}); e.perform(player);
}
// Always true // Always true
return true; return true;
} }
@ -191,8 +203,7 @@ public class MainCommand extends Command {
if (args.length >= 2) { if (args.length >= 2) {
PlotArea area = player.getApplicablePlotArea(); PlotArea area = player.getApplicablePlotArea();
Plot newPlot = Plot.fromString(area, args[0]); Plot newPlot = Plot.fromString(area, args[0]);
if (newPlot != null && (player instanceof ConsolePlayer || newPlot.getArea().equals(area) || Permissions if (newPlot != null && (player instanceof ConsolePlayer || newPlot.getArea().equals(area) || Permissions.hasPermission(player, C.PERMISSION_ADMIN)) && !newPlot.isDenied(player.getUUID())) {
.hasPermission(player, C.PERMISSION_ADMIN)) && !newPlot.isDenied(player.getUUID())) {
// Save meta // Save meta
loc = player.getMeta("location"); loc = player.getMeta("location");
plot = player.getMeta("lastplot"); plot = player.getMeta("lastplot");
@ -206,7 +217,7 @@ public class MainCommand extends Command {
} }
super.execute(player, args, confirm, whenDone); super.execute(player, args, confirm, whenDone);
// Reset command scope // // Reset command scope //
if (tp) { if (tp && !(player instanceof ConsolePlayer)) {
if (loc == null) { if (loc == null) {
player.deleteMeta("location"); player.deleteMeta("location");
} else { } else {

View File

@ -2,16 +2,18 @@ package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal2;
import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.Argument; import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.util.*; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.UUID;
@CommandDeclaration( @CommandDeclaration(
command = "trust", command = "trust",
@ -20,64 +22,57 @@ import java.util.Set;
usage = "/plot trust <player>", usage = "/plot trust <player>",
description = "Allow a player to build in a plot", description = "Allow a player to build in a plot",
category = CommandCategory.SETTINGS) category = CommandCategory.SETTINGS)
public class Trust extends SubCommand { public class Trust extends Command {
public Trust() { public Trust() {
super(Argument.PlayerName); super(MainCommand.getInstance(), true);
} }
@Override @Override
public boolean onCommand(PlotPlayer plr, String[] args) { public void execute(final PlotPlayer player, String[] args, RunnableVal3<Command, Runnable, Runnable> confirm, RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
Location loc = plr.getLocation(); final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT);
Plot plot = loc.getPlotAbs(); checkTrue(plot.hasOwner(), C.PLOT_UNOWNED);
if (plot == null) { checkTrue(plot.isOwner(player.getUUID()) || Permissions.hasPermission(player, "plots.admin.command.trust"), C.NO_PLOT_PERMS);
return !sendMessage(plr, C.NOT_IN_PLOT); checkTrue(args.length == 1, C.COMMAND_SYNTAX, getUsage());
} final Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
if (!plot.hasOwner()) { checkTrue(uuids != null && !uuids.isEmpty(), C.INVALID_PLAYER, args[0]);
MainUtil.sendMessage(plr, C.PLOT_UNOWNED);
return false;
}
if (!plot.isOwner(plr.getUUID()) && !Permissions.hasPermission(plr, "plots.admin.command.trust")) {
MainUtil.sendMessage(plr, C.NO_PLOT_PERMS);
return true;
}
Set<UUID> uuids = MainUtil.getUUIDsFromString(args[0]);
if (uuids == null || uuids.isEmpty()) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, args[0]);
return false;
}
Iterator<UUID> iter = uuids.iterator(); Iterator<UUID> iter = uuids.iterator();
int size = plot.getTrusted().size() + plot.getMembers().size();
while (iter.hasNext()) { while (iter.hasNext()) {
UUID uuid = iter.next(); UUID uuid = iter.next();
if (uuid == DBFunc.everyone && !(Permissions.hasPermission(plr, "plots.trust.everyone") || Permissions.hasPermission(plr, "plots.admin.command.trust"))) { if (uuid == DBFunc.everyone && !(Permissions.hasPermission(player, "plots.trust.everyone") || Permissions.hasPermission(player, "plots.admin.command.trust"))) {
MainUtil.sendMessage(plr, C.INVALID_PLAYER, MainUtil.getName(uuid)); MainUtil.sendMessage(player, C.INVALID_PLAYER, MainUtil.getName(uuid));
iter.remove();
continue; continue;
} }
if (plot.isOwner(uuid)) { if (plot.isOwner(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_OWNER, MainUtil.getName(uuid)); MainUtil.sendMessage(player, C.ALREADY_OWNER, MainUtil.getName(uuid));
iter.remove();
continue; continue;
} }
if (plot.getTrusted().contains(uuid)) { if (plot.getTrusted().contains(uuid)) {
MainUtil.sendMessage(plr, C.ALREADY_ADDED, MainUtil.getName(uuid)); MainUtil.sendMessage(player, C.ALREADY_ADDED, MainUtil.getName(uuid));
iter.remove();
continue; continue;
} }
if (plot.removeMember(uuid)) { size += plot.getMembers().contains(uuid) ? 0 : 1;
plot.addTrusted(uuid); }
} else { checkTrue(!uuids.isEmpty(), null);
if ((plot.getMembers().size() + plot.getTrusted().size()) >= plot.getArea().MAX_PLOT_MEMBERS) { checkTrue(size <= plot.getArea().MAX_PLOT_MEMBERS, C.PLOT_MAX_MEMBERS);
MainUtil.sendMessage(plr, C.PLOT_MAX_MEMBERS); confirm.run(this, new Runnable() {
continue; @Override // Success
public void run() {
for (UUID uuid : uuids) {
if (!plot.removeMember(uuid)) {
if (plot.getDenied().contains(uuid)) {
plot.removeDenied(uuid);
}
}
plot.addTrusted(uuid);
EventUtil.manager.callTrusted(player, plot, uuid, true);
MainUtil.sendMessage(player, C.TRUSTED_ADDED);
} }
if (plot.getDenied().contains(uuid)) {
plot.removeDenied(uuid);
}
plot.addTrusted(uuid);
} }
EventUtil.manager.callTrusted(plr, plot, uuid, true); }, null);
}
if (!uuids.isEmpty()) {
MainUtil.sendMessage(plr, C.TRUSTED_ADDED);
}
return true;
} }
} }

View File

@ -1,6 +1,5 @@
package com.intellectualcrafters.plot.config; package com.intellectualcrafters.plot.config;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -50,7 +49,6 @@ public class Settings {
*/ */
public static boolean CHUNK_PROCESSOR = false; public static boolean CHUNK_PROCESSOR = false;
public static boolean EXPERIMENTAL_FAST_ASYNC_WORLDEDIT = false; public static boolean EXPERIMENTAL_FAST_ASYNC_WORLDEDIT = false;
public static boolean CHUNK_PROCESSOR_TRIM_ON_SAVE = false;
public static boolean CHUNK_PROCESSOR_GC = false; public static boolean CHUNK_PROCESSOR_GC = false;
public static int CHUNK_PROCESSOR_MAX_BLOCKSTATES = 4096; public static int CHUNK_PROCESSOR_MAX_BLOCKSTATES = 4096;
public static int CHUNK_PROCESSOR_MAX_ENTITIES = 512; public static int CHUNK_PROCESSOR_MAX_ENTITIES = 512;
@ -65,14 +63,9 @@ public class Settings {
*/ */
public static int MAX_AUTO_SIZE = 4; public static int MAX_AUTO_SIZE = 4;
/** /**
* Default worldedit-require-selection-in-mask: false * Default worldedit-check-selection-in-mask: false
*/ */
public static boolean REQUIRE_SELECTION = true;
public static boolean QUEUE_COMMANDS = false;
public static boolean WE_ALLOW_HELPER = false; public static boolean WE_ALLOW_HELPER = false;
public static long WE_MAX_VOLUME = 500000;
public static long WE_MAX_ITERATIONS = 1000;
public static List<String> WE_BLACKLIST = new ArrayList<>();
/** /**
* Teleport to path on login * Teleport to path on login
*/ */

View File

@ -31,7 +31,18 @@ public class Flags {
public static final BooleanFlag NOTIFY_ENTER = new BooleanFlag("notify-enter"); public static final BooleanFlag NOTIFY_ENTER = new BooleanFlag("notify-enter");
public static final LongFlag TIME = new LongFlag("time"); public static final LongFlag TIME = new LongFlag("time");
public static final PlotWeatherFlag WEATHER = new PlotWeatherFlag("weather"); public static final PlotWeatherFlag WEATHER = new PlotWeatherFlag("weather");
public static final DoubleFlag PRICE = new DoubleFlag("price"); public static final DoubleFlag PRICE = new DoubleFlag("price") {
@Override
public Double parseValue(String input) {
Double value = super.parseValue(input);
return value != null && value > 0 ? value : null;
}
@Override
public String getValueDescription() {
return "Flag value must be a positive number.";
}
};
public static final BooleanFlag EXPLOSION = new BooleanFlag("explosion"); public static final BooleanFlag EXPLOSION = new BooleanFlag("explosion");
public static final BooleanFlag GRASS_GROW = new BooleanFlag("grass-grow"); public static final BooleanFlag GRASS_GROW = new BooleanFlag("grass-grow");
public static final BooleanFlag VINE_GROW = new BooleanFlag("vine-grow"); public static final BooleanFlag VINE_GROW = new BooleanFlag("vine-grow");

View File

@ -27,7 +27,7 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld {
/** /**
* CONFIG NODE | DEFAULT VALUE | DESCRIPTION | CONFIGURATION TYPE | REQUIRED FOR INITIAL SETUP. * CONFIG NODE | DEFAULT VALUE | DESCRIPTION | CONFIGURATION TYPE | REQUIRED FOR INITIAL SETUP.
* *
* <p>Set the last boolean to false if you do not require a specific config node to be set while using the setup * <p>Set the last boolean to false if you do not check a specific config node to be set while using the setup
* command - this may be useful if a config value can be changed at a later date, and has no impact on the actual * command - this may be useful if a config value can be changed at a later date, and has no impact on the actual
* world generation</p> * world generation</p>
*/ */

View File

@ -5,20 +5,13 @@ import com.intellectualcrafters.plot.commands.RequiredType;
import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.util.PlotGameMode; import com.intellectualcrafters.plot.util.PlotGameMode;
import com.intellectualcrafters.plot.util.PlotWeather; import com.intellectualcrafters.plot.util.PlotWeather;
import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
public class ConsolePlayer extends PlotPlayer { public class ConsolePlayer extends PlotPlayer {
private static ConsolePlayer instance; private static ConsolePlayer instance;
private final HashMap<String, Object> meta;
private ConsolePlayer() {
/**
* Direct access is deprecated.
*/
@Deprecated
public ConsolePlayer() {
PlotArea area = PS.get().getFirstPlotArea(); PlotArea area = PS.get().getFirstPlotArea();
Location loc; Location loc;
if (area != null) { if (area != null) {
@ -27,7 +20,6 @@ public class ConsolePlayer extends PlotPlayer {
} else { } else {
loc = new Location("world", 0, 0, 0); loc = new Location("world", 0, 0, 0);
} }
this.meta = new HashMap<>();
setMeta("location", loc); setMeta("location", loc);
} }
@ -46,12 +38,12 @@ public class ConsolePlayer extends PlotPlayer {
@Override @Override
public Location getLocation() { public Location getLocation() {
return (Location) getMeta("location"); return this.<Location>getMeta("location");
} }
@Override @Override
public Location getLocationFull() { public Location getLocationFull() {
return (Location) getMeta("location"); return getLocation();
} }
@Override @Override
@ -71,8 +63,7 @@ public class ConsolePlayer extends PlotPlayer {
@Override @Override
public void teleport(Location location) { public void teleport(Location location) {
Plot plot = location.getPlot(); setMeta("lastplot", location.getPlot());
setMeta("lastplot", plot);
setMeta("location", location); setMeta("location", location);
} }
@ -100,21 +91,6 @@ public class ConsolePlayer extends PlotPlayer {
@Override @Override
public void removeAttribute(String key) {} public void removeAttribute(String key) {}
@Override
public void setMeta(String key, Object value) {
this.meta.put(key, value);
}
@Override
public Object getMeta(String key) {
return this.meta.get(key);
}
@Override
public Object deleteMeta(String key) {
return this.meta.remove(key);
}
@Override @Override
public RequiredType getSuperCaller() { public RequiredType getSuperCaller() {
return RequiredType.CONSOLE; return RequiredType.CONSOLE;

View File

@ -5,6 +5,7 @@ import com.intellectualcrafters.plot.commands.RequiredType;
import com.intellectualcrafters.plot.config.Settings; import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.flag.Flags; import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.ExpireManager; import com.intellectualcrafters.plot.util.ExpireManager;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
@ -449,4 +450,20 @@ public abstract class PlotPlayer implements CommandCaller {
} }
public abstract void stopSpectating(); public abstract void stopSpectating();
public double getMoney() {
return EconHandler.manager == null ? 0 : EconHandler.manager.getMoney(this);
}
public void withdraw(double amount) {
if (EconHandler.manager != null) {
EconHandler.manager.withdrawMoney(this, amount);
}
}
public void deposit(double amount) {
if (EconHandler.manager != null) {
EconHandler.manager.depositMoney(this, amount);
}
}
} }

View File

@ -271,7 +271,7 @@ public abstract class Command {
* @return * @return
*/ */
public void execute(PlotPlayer player, String[] args, RunnableVal3<Command, Runnable, Runnable> confirm, public void execute(PlotPlayer player, String[] args, RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone) { RunnableVal2<Command, CommandResult> whenDone) throws CommandException {
if (args.length == 0 || args[0] == null) { if (args.length == 0 || args[0] == null) {
if (this.parent == null) { if (this.parent == null) {
MainCommand.getInstance().help.displayHelp(player, null, 0); MainCommand.getInstance().help.displayHelp(player, null, 0);
@ -537,4 +537,33 @@ public abstract class Command {
FAILURE, FAILURE,
SUCCESS SUCCESS
} }
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 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);
}
}
}
} }