Check database before claiming plot

This commit is contained in:
Jesse Boyd 2017-04-15 12:40:23 +10:00
parent 7eb7cd9b53
commit 37977f1da4
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
8 changed files with 197 additions and 79 deletions

View File

@ -3,15 +3,16 @@ package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Expression;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ByteArrayUtilities;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.Permissions;
import com.plotsquared.general.commands.CommandDeclaration;
@ -54,7 +55,7 @@ public class Auto extends SubCommand {
}
@Override
public boolean onCommand(PlotPlayer player, String[] args) {
public boolean onCommand(final PlotPlayer player, String[] args) {
PlotArea plotarea = player.getApplicablePlotArea();
if (plotarea == null) {
if (EconHandler.manager != null) {
@ -155,48 +156,85 @@ public class Auto extends SubCommand {
}
}
// TODO handle type 2 the same as normal worlds!
if (plotarea.TYPE == 2) {
PlotId bot = plotarea.getMin();
PlotId top = plotarea.getMax();
PlotId origin = new PlotId(MathMan.average(bot.x, top.x), MathMan.average(bot.y, top.y));
PlotId id = new PlotId(0, 0);
int width = Math.max(top.x - bot.x + 1, top.y - bot.y + 1);
int max = width * width;
//
for (int i = 0; i <= max; i++) {
PlotId currentId = new PlotId(origin.x + id.x, origin.y + id.y);
Plot current = plotarea.getPlotAbs(currentId);
if (current.canClaim(player)) {
current.claim(player, true, null);
return true;
}
id = getNextPlotId(id, 1);
}
// no free plots
MainUtil.sendMessage(player, C.NO_FREE_PLOTS);
return false;
}
while (true) {
PlotId start = getNextPlotId(getLastPlotId(plotarea), 1);
PlotId end = new PlotId(start.x + size_x - 1, start.y + size_z - 1);
plotarea.setMeta("lastPlot", start);
if (plotarea.canClaim(player, start, end)) {
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 (size_x == 1 && size_z == 1) {
final String finalSchematic = schematic;
autoClaimSafe(player, plotarea, null, new RunnableVal<Plot>() {
@Override
public void run(Plot value) {
if (value == null) {
MainUtil.sendMessage(player, C.NO_FREE_PLOTS);
} else {
value.claim(player, true, finalSchematic, false);
}
}
if (size_x != 1 || size_z != 1) {
if (!plotarea.mergePlots(MainUtil.getPlotSelectionIds(start, end), true, true)) {
return false;
});
return true;
} else {
if (plotarea.TYPE == 2) {
// TODO
MainUtil.sendMessage(player, C.NO_FREE_PLOTS);
return false;
}
while (true) {
PlotId start = getNextPlotId(getLastPlotId(plotarea), 1);
PlotId end = new PlotId(start.x + size_x - 1, start.y + size_z - 1);
plotarea.setMeta("lastPlot", start);
if (plotarea.canClaim(player, start, end)) {
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 (size_x != 1 || size_z != 1) {
if (!plotarea.mergePlots(MainUtil.getPlotSelectionIds(start, end), true, true)) {
return false;
}
}
break;
}
}
return true;
}
}
public void autoClaimSafe(final PlotPlayer player, final PlotArea area, PlotId start, final RunnableVal<Plot> whenDone) {
if (area.TYPE == 2) {
PlotId min = area.getMin();
PlotId max = area.getMax();
if (start == null) start = new PlotId(min.x, min.y);
while (!area.canClaim(player, start, start)) {
if (++start.x > max.x) {
start.x = min.x;
if (++start.y > max.y) {
whenDone.run(null);
return;
}
}
break;
start.recalculateHash();
}
} else {
if (start == null) start = getLastPlotId(area);
while (!area.canClaim(player, start, start)) {
start = getNextPlotId(start, 1);
}
}
return true;
Plot plot = area.getPlotAbs(start);
if (plot.canClaim(player)) {
plot.owner = player.getUUID();
final PlotId finalStart = getNextPlotId(start, 1);
area.setMeta("lastPlot", finalStart);
whenDone.value = plot;
DBFunc.createPlotSafe(plot, whenDone, new Runnable() {
@Override
public void run() {
autoClaimSafe(player, area, finalStart, whenDone);
}
});
return;
}
autoClaimSafe(player, area, start, whenDone);
}
public PlotId getLastPlotId(PlotArea area) {

View File

@ -2,6 +2,7 @@ package com.intellectualcrafters.plot.commands;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.Expression;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
@ -21,13 +22,13 @@ import com.plotsquared.general.commands.CommandDeclaration;
public class Claim extends SubCommand {
@Override
public boolean onCommand(PlotPlayer player, String[] args) {
public boolean onCommand(final PlotPlayer player, String[] args) {
String schematic = "";
if (args.length >= 1) {
schematic = args[0];
}
Location loc = player.getLocation();
Plot plot = loc.getPlotAbs();
final Plot plot = loc.getPlotAbs();
if (plot == null) {
return sendMessage(player, C.NOT_IN_PLOT);
}
@ -47,7 +48,7 @@ public class Claim extends SubCommand {
if (!plot.canClaim(player)) {
return sendMessage(player, C.PLOT_IS_CLAIMED);
}
PlotArea area = plot.getArea();
final PlotArea area = plot.getArea();
if (!schematic.isEmpty()) {
if (area.SCHEMATIC_CLAIM_SPECIFY) {
if (!area.SCHEMATICS.contains(schematic.toLowerCase())) {
@ -81,6 +82,24 @@ public class Claim extends SubCommand {
}
sendMessage(player, C.REMOVED_GRANTED_PLOT, "1", "" + (grants - 1));
}
return plot.claim(player, false, schematic) || sendMessage(player, C.PLOT_NOT_CLAIMED);
plot.owner = player.getUUID();
if (plot.canClaim(player)) {
final String finalSchematic = schematic;
DBFunc.createPlotSafe(plot, new Runnable() {
@Override
public void run() {
plot.claim(player, true, finalSchematic, false);
}
}, new Runnable() {
@Override
public void run() {
sendMessage(player, C.PLOT_NOT_CLAIMED);
}
});
return true;
} else {
sendMessage(player, C.PLOT_NOT_CLAIMED);
}
return false;
}
}

View File

@ -42,7 +42,7 @@ public interface AbstractDB {
*
* @param plot the plot to create
*/
void createPlot(Plot plot);
void createPlotSafe(final Plot plot, final Runnable success, final Runnable failure);
/**
* Create tables.

View File

@ -125,16 +125,11 @@ public class DBFunc {
DBFunc.dbManager.createPlotsAndData(plots, whenDone);
}
/**
* Create a plot
*
* @param plot Plot to create
*/
public static void createPlot(Plot plot) {
if (plot.temp == -1 || dbManager == null) {
public static void createPlotSafe(final Plot plot, final Runnable success, final Runnable failure) {
if (dbManager == null) {
return;
}
DBFunc.dbManager.createPlot(plot);
DBFunc.dbManager.createPlotSafe(plot, success, failure);
}
/**

View File

@ -1,5 +1,6 @@
package com.intellectualcrafters.plot.database;
import com.google.common.base.Charsets;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.Settings;
@ -53,6 +54,7 @@ public class SQLManager implements AbstractDB {
public final String CREATE_SETTINGS;
public final String CREATE_TIERS;
public final String CREATE_PLOT;
public final String CREATE_PLOT_SAFE;
public final String CREATE_CLUSTER;
private final String prefix;
// Private Final
@ -116,6 +118,12 @@ public class SQLManager implements AbstractDB {
this.CREATE_SETTINGS = "INSERT INTO `" + this.prefix + "plot_settings` (`plot_plot_id`) values ";
this.CREATE_TIERS = "INSERT INTO `" + this.prefix + "plot_%tier%` (`plot_plot_id`, `user_uuid`) values ";
this.CREATE_PLOT = "INSERT INTO `" + this.prefix + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) VALUES(?, ?, ?, ?, ?)";
if (mySQL) {
this.CREATE_PLOT_SAFE = "INSERT OR IGNORE INTO `" + this.prefix + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) SELECT ?, ?, ?, ?, ? FROM DUAL WHERE NOT EXISTS (SELECT null FROM `" + this.prefix + "plot` WHERE `world` = ? AND `plot_id_x` = ? AND `plot_id_z` = ?)";
} else {
this.CREATE_PLOT_SAFE = "INSERT OR IGNORE INTO `" + this.prefix + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) SELECT ?, ?, ?, ?, ? WHERE NOT EXISTS (SELECT null FROM `" + this.prefix + "plot` WHERE `world` = ? AND `plot_id_x` = ? AND `plot_id_z` = ?)";
}
this.CREATE_CLUSTER =
"INSERT INTO `" + this.prefix + "cluster`(`pos1_x`, `pos1_z`, `pos2_x`, `pos2_z`, `owner`, `world`) VALUES(?, ?, ?, ?, ?, ?)";
try {
@ -994,14 +1002,9 @@ public class SQLManager implements AbstractDB {
});
}
/**
* Create a plot.
*
* @param plot
*/
@Override
public void createPlot(final Plot plot) {
addPlotTask(plot, new UniqueStatement("createPlot") {
public void createPlotSafe(final Plot plot, final Runnable success, final Runnable failure) {
final long timestamp = plot.getTimestamp();
addPlotTask(plot, new UniqueStatement("createPlotSafe_" + plot.hashCode()) {
@Override
public void set(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, plot.getId().x);
@ -1009,11 +1012,45 @@ public class SQLManager implements AbstractDB {
stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.getArea().toString());
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
stmt.setString(6, plot.getArea().toString());
stmt.setInt(7, plot.getId().x);
stmt.setInt(8, plot.getId().y);
}
@Override
public PreparedStatement get() throws SQLException {
return SQLManager.this.connection.prepareStatement(SQLManager.this.CREATE_PLOT);
return SQLManager.this.connection.prepareStatement(SQLManager.this.CREATE_PLOT_SAFE, Statement.KEEP_CURRENT_RESULT );
}
@Override
public void execute(PreparedStatement statement) {
}
@Override
public void addBatch(PreparedStatement statement) throws SQLException {
int inserted = statement.executeUpdate();
if (inserted > 0) {
try (ResultSet keys = statement.getGeneratedKeys()) {
if (keys.next()) {
plot.temp = keys.getInt(1);
addPlotTask(plot, new UniqueStatement("createPlotAndSettings_settings_" + plot.hashCode()) {
@Override
public void set(PreparedStatement stmt) throws SQLException {
stmt.setInt(1, getId(plot));
}
@Override
public PreparedStatement get() throws SQLException {
return SQLManager.this.connection.prepareStatement("INSERT INTO `" + SQLManager.this.prefix + "plot_settings`(`plot_plot_id`) VALUES(?)");
}
});
if (success != null) addNotifyTask(success);
return;
}
}
}
if (failure != null) failure.run();
}
});
}
@ -1040,7 +1077,7 @@ public class SQLManager implements AbstractDB {
stmt.setInt(1, plot.getId().x);
stmt.setInt(2, plot.getId().y);
stmt.setString(3, plot.owner.toString());
stmt.setString(4, plot.getArea().worldname);
stmt.setString(4, plot.getArea().toString());
stmt.setTimestamp(5, new Timestamp(plot.getTimestamp()));
}
@ -1055,9 +1092,10 @@ public class SQLManager implements AbstractDB {
@Override
public void addBatch(PreparedStatement statement) throws SQLException {
statement.executeUpdate();
ResultSet keys = statement.getGeneratedKeys();
if (keys.next()) {
plot.temp = keys.getInt(1);
try (ResultSet keys = statement.getGeneratedKeys()) {
if (keys.next()) {
plot.temp = keys.getInt(1);
}
}
}
});
@ -1069,8 +1107,7 @@ public class SQLManager implements AbstractDB {
@Override
public PreparedStatement get() throws SQLException {
return SQLManager.this.connection
.prepareStatement("INSERT INTO `" + SQLManager.this.prefix + "plot_settings`(`plot_plot_id`) VALUES(?)");
return SQLManager.this.connection.prepareStatement("INSERT INTO `" + SQLManager.this.prefix + "plot_settings`(`plot_plot_id`) VALUES(?)");
}
});
addNotifyTask(whenDone);
@ -1714,7 +1751,15 @@ public class SQLManager implements AbstractDB {
o = resultSet.getString("owner");
user = uuids.get(o);
if (user == null) {
user = UUID.fromString(o);
try {
user = UUID.fromString(o);
} catch (IllegalArgumentException e) {
if (Settings.UUID.FORCE_LOWERCASE) {
user = UUID.nameUUIDFromBytes(("OfflinePlayer:" + o.toLowerCase()).getBytes(Charsets.UTF_8));
} else {
user = UUID.nameUUIDFromBytes(("OfflinePlayer:" + o).getBytes(Charsets.UTF_8));
}
}
uuids.put(o, user);
}
long time;
@ -2722,7 +2767,7 @@ public class SQLManager implements AbstractDB {
for (String element : flags_string) {
if (element.contains(":")) {
String[] split = element.split(":");
String flag_str = split[1].replaceAll("\u00AF", ":").replaceAll("<EFBFBD>", ",");
String flag_str = split[1].replaceAll("\u00AF", ":").replaceAll("´", ",");
Flag flag = FlagManager.getOrCreateFlag(split[0]);
if (flag == null) {
flag = new StringFlag(split[0]) {
@ -2776,7 +2821,7 @@ public class SQLManager implements AbstractDB {
flag_string.append(',');
}
flag_string.append(flag.getKey().getName()).append(':')
.append(flag.getKey().valueToString(flag.getValue()).replaceAll(":", "¯").replaceAll(",", "´"));
.append(flag.getKey().valueToString(flag.getValue()).replaceAll(":", "\u00AF").replaceAll(",", "´"));
i++;
}
addClusterTask(cluster, new UniqueStatement("setFlags") {

View File

@ -1330,9 +1330,17 @@ public class Plot {
if (!canClaim(player)) {
return false;
}
return claim(player, teleport, schematic, true);
}
public boolean claim(final PlotPlayer player, boolean teleport, String schematic, boolean updateDB) {
boolean result = EventUtil.manager.callClaim(player, this, false);
if (!result || !create(player.getUUID(), true)) {
return false;
if (updateDB) {
if (!result || (!create(player.getUUID(), true))) {
return false;
}
} else {
area.addPlot(this);
}
setSign(player.getName());
MainUtil.sendMessage(player, C.CLAIMED);

View File

@ -744,10 +744,19 @@ public abstract class PlotArea {
}
public boolean canClaim(PlotPlayer player, PlotId pos1, PlotId pos2) {
if (pos1.x == pos2.x && pos1.y == pos2.y) {
if (getOwnedPlot(pos1) != null) {
return false;
}
Plot plot = getPlotAbs(pos1);
if (plot == null) return false;
return plot.canClaim(player);
}
for (int x = pos1.x; x <= pos2.x; x++) {
for (int y = pos1.y; y <= pos2.y; y++) {
PlotId id = new PlotId(x, y);
Plot plot = getPlotAbs(id);
if (plot == null) return false;
if (!plot.canClaim(player)) {
return false;
}

View File

@ -16,6 +16,7 @@ import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import java.util.ArrayDeque;
@ -25,6 +26,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
@ -244,16 +246,17 @@ public class ExpireManager {
ExpireManager.this.running = 0;
return;
}
final Plot plot = plots.poll();
Plot plot = plots.poll();
PlotArea area = plot.getArea();
final Plot newPlot = area.getPlot(plot.getId());
final ArrayDeque<ExpiryTask> applicable = new ArrayDeque<>(tasks);
final Collection<ExpiryTask> expired = isExpired(applicable, plot);
final Collection<ExpiryTask> expired = isExpired(applicable, newPlot);
if (expired.isEmpty()) {
continue;
}
for (ExpiryTask expiryTask : expired) {
if (!expiryTask.needsAnalysis()) {
expiredTask.run(plot, new Runnable() {
expiredTask.run(newPlot, new Runnable() {
@Override
public void run() {
TaskManager.IMP.taskLaterAsync(task, 1);
@ -268,7 +271,7 @@ public class ExpireManager {
passesComplexity(changed, expired, new RunnableVal<Boolean>() {
@Override
public void run(Boolean confirmation) {
expiredTask.run(plot, new Runnable() {
expiredTask.run(newPlot, new Runnable() {
@Override
public void run() {
TaskManager.IMP.taskLaterAsync(task, 1);
@ -278,7 +281,7 @@ public class ExpireManager {
}, new Runnable() {
@Override
public void run() {
FlagManager.addPlotFlag(plot, Flags.ANALYSIS, changed.asList());
FlagManager.addPlotFlag(newPlot, Flags.ANALYSIS, changed.asList());
TaskManager.runTaskLaterAsync(task, 20);
}
});
@ -287,11 +290,11 @@ public class ExpireManager {
final Runnable doAnalysis = new Runnable() {
@Override
public void run() {
HybridUtils.manager.analyzePlot(plot, handleAnalysis);
HybridUtils.manager.analyzePlot(newPlot, handleAnalysis);
}
};
PlotAnalysis analysis = plot.getComplexity(null);
PlotAnalysis analysis = newPlot.getComplexity(null);
if (analysis != null) {
passesComplexity(analysis, expired, new RunnableVal<Boolean>() {
@Override
@ -352,11 +355,12 @@ public class ExpireManager {
MainUtil.sendMessage(player, C.PLOT_REMOVED_USER, plot.toString());
}
}
Set<Plot> plots = plot.getConnectedPlots();
plot.deletePlot(whenDone);
PlotAnalysis changed = plot.getComplexity(null);
int changes = changed == null ? 0 : changed.changes_sd;
int modified = changed == null ? 0 : changed.changes;
PS.debug("$2[&5Expire&dManager$2] &cDeleted expired plot: " + plot + " User:" + plot.owner + " Delta:" + changes + "/" + modified);
PS.debug("$2[&5Expire&dManager$2] &cDeleted expired plot: " + plot + " User:" + plot.owner + " Delta:" + changes + "/" + modified + " Connected: " + StringMan.getString(plots));
PS.debug("$4 - Area: " + plot.getArea());
if (plot.hasOwner()) {
PS.debug("$4 - Owner: " + UUIDHandler.getName(plot.owner));