mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-24 19:46:34 +01:00
Fix entity mask + More work on rollback
This commit is contained in:
parent
e5ebccd053
commit
895de11a09
@ -219,6 +219,12 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
return world.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserName(UUID uuid) {
|
||||
String name = Bukkit.getOfflinePlayer(uuid).getName();
|
||||
return name != null ? name : uuid.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A mask manager handles region restrictions e.g. PlotSquared plots / WorldGuard regions
|
||||
*/
|
||||
|
@ -32,6 +32,7 @@ import com.sk89q.worldedit.command.NavigationCommands;
|
||||
import com.sk89q.worldedit.command.RegionCommands;
|
||||
import com.sk89q.worldedit.command.SchematicCommands;
|
||||
import com.sk89q.worldedit.command.ScriptingCommands;
|
||||
import com.sk89q.worldedit.command.ToolCommands;
|
||||
import com.sk89q.worldedit.command.composition.SelectionCommand;
|
||||
import com.sk89q.worldedit.command.tool.brush.GravityBrush;
|
||||
import com.sk89q.worldedit.event.extent.EditSessionEvent;
|
||||
@ -277,6 +278,7 @@ public class Fawe {
|
||||
LocalSession.inject(); // Add remember order / queue flushing
|
||||
// Commands
|
||||
BrushCommands.inject(); // Translations + heightmap
|
||||
ToolCommands.inject(); // Translations + inspect
|
||||
ClipboardCommands.inject(); // Translations + lazycopy + paste optimizations
|
||||
SchematicCommands.inject(); // Translations
|
||||
ScriptingCommands.inject(); // Translations
|
||||
|
@ -16,6 +16,7 @@ import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.CuboidClipboard;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import java.awt.Color;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
@ -507,6 +508,18 @@ public class FaweCache {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMaterialName(int combined) {
|
||||
return getMaterialName(getId(combined), getData(combined));
|
||||
}
|
||||
|
||||
public static String getMaterialName(int id, int data) {
|
||||
BundledBlockData.BlockEntry entry = BundledBlockData.getInstance().findById(id);
|
||||
if (entry == null) {
|
||||
return data != 0 ? id + ":" + data : id + "";
|
||||
}
|
||||
return data != 0 ? entry.id.replace("minecraft:","") + ":" + data : entry.id.replace("minecraft:","");
|
||||
}
|
||||
|
||||
public static Map<String, Object> asMap(Object... pairs) {
|
||||
HashMap<String, Object> map = new HashMap<String, Object>(pairs.length >> 1);
|
||||
for (int i = 0; i < pairs.length; i+=2) {
|
||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.command;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
@ -27,6 +28,24 @@ public class Rollback extends FaweCommand {
|
||||
|
||||
@Override
|
||||
public boolean execute(final FawePlayer player, final String... args) {
|
||||
if (!Settings.HISTORY.USE_DATABASE) {
|
||||
BBC.SETTING_DISABLE.send(player, "history.use-database");
|
||||
return false;
|
||||
}
|
||||
if (args.length != 3) {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb u:<uuid> r:<radius> t:<time>");
|
||||
return false;
|
||||
}
|
||||
switch (args[0]) {
|
||||
case "i":
|
||||
case "info":
|
||||
case "undo":
|
||||
case "revert":
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb u:<uuid> r:<radius> t:<time>");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (args.length < 1) {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb <info|undo> u:<uuid> r:<radius> t:<time>");
|
||||
return false;
|
||||
|
@ -41,6 +41,7 @@ public enum BBC {
|
||||
WORLDEDIT_RESTRICTED("&6Your WorldEdit is now restricted.", "Info"),
|
||||
WORLDEDIT_OOM_ADMIN("&cPossible options:\n&8 - &7//fast\n&8 - &7Do smaller edits\n&8 - &7Allocate more memory\n&8 - &7Disable this safeguard", "Info"),
|
||||
COMPRESSED("History compressed. Saved ~ %s0b (%s1x smaller)", "Info"),
|
||||
|
||||
ACTION_COMPLETE("Action completed in %s0 seconds", "Info"),
|
||||
GENERATING_LINK("Uploading %s, please wait...", "Web"),
|
||||
GENERATING_LINK_FAILED("&cFailed to generate download link!", "Web"),
|
||||
@ -90,7 +91,23 @@ public enum BBC {
|
||||
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
|
||||
BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2).", "WorldEdit.Brush"),
|
||||
BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_INSPECT("Inspect brush shape equipped (%s0).", "WorldEdit.Brush"),
|
||||
|
||||
TOOL_INSPECT("Inspect tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_INSPECT_INFO("&7%s0 changed %s1 to %s2 %s3 ago","Info"),
|
||||
TOOL_INSPECT_INFO_FOOTER("&6Total: &7%s0 changes","Info"),
|
||||
TOOL_NONE("Tool unbound from your current item.", "WorldEdit.Tool"),
|
||||
TOOL_INFO("Info tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_TREE("Tree tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_TREE_ERROR("Tree type %s0 is unknown.", "WorldEdit.Tool"),
|
||||
TOOL_REPL("Block replacer tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_CYCLER("Block data cycler tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_FLOOD_FILL("Block flood fill tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_FLOOD_FILL_RANGE_ERROR("Maximum range: %s0.", "WorldEdit.Tool"),
|
||||
TOOL_DELTREE("Floating tree remover tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_FARWAND("Far wand tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_LRBUILD_BOUND("Long-range building tool bound to %s0.", "WorldEdit.Tool"),
|
||||
TOOL_LRBUILD_INFO("Left-click set to %s0; right-click set to %s1.", "WorldEdit.Tool"),
|
||||
|
||||
|
||||
SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"),
|
||||
SCHEMATIC_FORMAT("Available clipboard formats (Name: Lookup names)", "Worldedit.Schematic"),
|
||||
@ -116,9 +133,11 @@ public enum BBC {
|
||||
|
||||
COMMAND_SYNTAX("&cUsage: &7%s0", "Error"),
|
||||
NO_PERM("&cYou are lacking the permission node: %s0", "Error"),
|
||||
SETTING_DISABLE("&cLacking setting: %s0","Error"),
|
||||
SCHEMATIC_NOT_FOUND("&cSchematic not found: &7%s0", "Error"),
|
||||
NO_REGION("&cYou have no current WorldEdit region", "Error"),
|
||||
NOT_PLAYER("&cYou must be a player to perform this action!", "Error"),
|
||||
PLAYER_NOT_FOUND("&cPlayer not found:&7 %s0", "Error"),
|
||||
OOM(
|
||||
"&8[&cCritical&8] &cDetected low memory i.e. < 1%. FAWE will take the following actions:\n&8 - &7Terminate WE block placement\n&8 - &7Clear WE history\n&8 - &7Unload non essential chunks\n&8 - &7Kill entities\n&8 - &7Garbage collect\n&cIgnore this if trying to crash server.\n&7Note: Low memory is likely (but not necessarily) caused by WE",
|
||||
"Error"),
|
||||
|
@ -4,6 +4,8 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class DBHandler {
|
||||
public final static DBHandler IMP = new DBHandler();
|
||||
|
||||
private Map<String, RollbackDatabase> databases = new ConcurrentHashMap<>();
|
||||
|
||||
public RollbackDatabase getDatabase(String world) {
|
||||
|
@ -5,9 +5,9 @@ import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.change.MutablePlayerBlockChange;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -30,8 +30,9 @@ public class RollbackDatabase {
|
||||
|
||||
private String INSERT_EDIT;
|
||||
private String CREATE_TABLE;
|
||||
private String GET_EDITS_POINT;
|
||||
// private String GET_EDITS_POINT;
|
||||
private String GET_EDITS;
|
||||
private String GET_EDITS_USER;
|
||||
private String PURGE;
|
||||
|
||||
private ConcurrentLinkedQueue<RollbackOptimizedHistory> historyChanges = new ConcurrentLinkedQueue<>();
|
||||
@ -40,13 +41,15 @@ public class RollbackDatabase {
|
||||
public RollbackDatabase(final String world) throws SQLException, ClassNotFoundException {
|
||||
this.prefix = "";
|
||||
this.world = world;
|
||||
this.dbLocation = new File(Fawe.imp().getDirectory(), "history" + File.separator + world);
|
||||
this.dbLocation = new File(Fawe.imp().getDirectory(), "history" + File.separator + world + File.separator + "summary.db");
|
||||
connection = openConnection();
|
||||
CREATE_TABLE = "CREATE TABLE IF NOT EXISTS `" + prefix + "edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL,`x1` INT NOT NULL,`y1` INT NOT NULL,`z1` INT NOT NULL,`x2` INT NOT NULL,`y2` INT NOT NULL,`z2` INT NOT NULL,`time` INT NOT NULL, PRIMARY KEY (player, id))";
|
||||
INSERT_EDIT = "INSERT INTO `" + prefix + "edits` (`player`,`id`,`x1`,`y1`,`z1`,`x2`,`y2`,`z2`,`time`) VALUES(?,?,?,?,?,?,?,?,?)";
|
||||
PURGE = "DELETE FROM `" + prefix + "edits` WHERE `time`<?";
|
||||
GET_EDITS = "SELECT `player`,`id`,`x1`,`y1`,`z1`,`x2`,`y2`,`z2`,`time` WHERE `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=? AND `time`>?";
|
||||
GET_EDITS_POINT = "SELECT `player`,`id`,`time` WHERE `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=?";
|
||||
// GET_EDITS_POINT = "SELECT `player`,`id` FROM `" + prefix + "edits` WHERE `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=?";
|
||||
GET_EDITS = "SELECT `player`,`id` FROM `" + prefix + "edits` WHERE `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=? AND `time`>?";
|
||||
GET_EDITS_USER = "SELECT `player`,`id` FROM `" + prefix + "edits` WHERE `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=? AND `time`>? AND `player`=?";
|
||||
init();
|
||||
purge((int) TimeUnit.DAYS.toMillis(Settings.HISTORY.DELETE_AFTER_DAYS));
|
||||
TaskManager.IMP.async(new Runnable() {
|
||||
@Override
|
||||
@ -72,6 +75,14 @@ public class RollbackDatabase {
|
||||
});
|
||||
}
|
||||
|
||||
public void init() {
|
||||
try (PreparedStatement stmt = connection.prepareStatement(CREATE_TABLE)) {
|
||||
stmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addFinishTask(Runnable run) {
|
||||
notify.add(run);
|
||||
}
|
||||
@ -92,32 +103,40 @@ public class RollbackDatabase {
|
||||
});
|
||||
}
|
||||
|
||||
public void getPotentialEdits(final int x, final int y, final int z, final RunnableVal<DiskStorageHistory> onEach, final Runnable onFail) {
|
||||
public void getPotentialEdits(final UUID uuid, final long minTime, final Vector pos1, final Vector pos2, final RunnableVal<DiskStorageHistory> onEach, final Runnable whenDone) {
|
||||
final World world = FaweAPI.getWorld(this.world);
|
||||
addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try (PreparedStatement stmt = connection.prepareStatement(GET_EDITS_POINT)) {
|
||||
stmt.setInt(1, x);
|
||||
stmt.setInt(2, x);
|
||||
stmt.setInt(3, y);
|
||||
stmt.setInt(4, y);
|
||||
stmt.setInt(5, z);
|
||||
stmt.setInt(6, z);
|
||||
try (PreparedStatement stmt = connection.prepareStatement(uuid == null ? GET_EDITS : GET_EDITS_USER)) {
|
||||
stmt.setInt(1, pos1.getBlockX());
|
||||
stmt.setInt(2, pos2.getBlockX());
|
||||
stmt.setByte(3, (byte) (pos1.getBlockY() - 128));
|
||||
stmt.setByte(4, (byte) (pos2.getBlockY() - 128));
|
||||
stmt.setInt(5, pos1.getBlockZ());
|
||||
stmt.setInt(6, pos2.getBlockZ());
|
||||
stmt.setInt(7, (int) (minTime / 1000));
|
||||
if (uuid != null) {
|
||||
byte[] uuidBytes = ByteBuffer.allocate(16).putLong(uuid.getMostSignificantBits()).putLong(uuid.getLeastSignificantBits()).array();
|
||||
stmt.setBytes(8, uuidBytes);
|
||||
}
|
||||
ResultSet result = stmt.executeQuery();
|
||||
if (!result.next()) {
|
||||
TaskManager.IMP.taskNow(onFail, false);
|
||||
TaskManager.IMP.taskNow(whenDone, false);
|
||||
return;
|
||||
}
|
||||
do {
|
||||
byte[] uuid = result.getBytes(1);
|
||||
byte[] uuidBytes = result.getBytes(1);
|
||||
int index = result.getInt(2);
|
||||
long time = 1000l * result.getInt(3);
|
||||
DiskStorageHistory history = new DiskStorageHistory(world, UUID.nameUUIDFromBytes(uuid), index);
|
||||
ByteBuffer bb = ByteBuffer.wrap(uuidBytes);
|
||||
long high = bb.getLong();
|
||||
long low = bb.getLong();
|
||||
DiskStorageHistory history = new DiskStorageHistory(world, new UUID(high, low), index);
|
||||
if (history.getBDFile().exists()) {
|
||||
onEach.run(history);
|
||||
}
|
||||
} while (result.next());
|
||||
TaskManager.IMP.taskNow(whenDone, false);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -125,10 +144,6 @@ public class RollbackDatabase {
|
||||
});
|
||||
}
|
||||
|
||||
public int getBlocks(int originX, int originZ, int radius, UUID uuid, long timeDiff, RunnableVal<MutablePlayerBlockChange> result) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void logEdit(RollbackOptimizedHistory history) {
|
||||
historyChanges.add(history);
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
package com.boydti.fawe.logging.rollback;
|
||||
|
||||
public class RollbackDatabase {
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.boydti.fawe.logging.rollback;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.database.DBHandler;
|
||||
import com.boydti.fawe.database.RollbackDatabase;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.IOException;
|
||||
@ -57,6 +60,8 @@ public class RollbackOptimizedHistory extends DiskStorageHistory {
|
||||
public boolean flush() {
|
||||
if (super.flush()) {
|
||||
// Save to DB
|
||||
RollbackDatabase db = DBHandler.IMP.getDatabase(Fawe.imp().getWorldName(getWorld()));
|
||||
db.logEdit(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1,24 +1,117 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.database.DBHandler;
|
||||
import com.boydti.fawe.database.RollbackDatabase;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.change.MutableFullBlockChange;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.WorldVectorFace;
|
||||
import com.sk89q.worldedit.command.tool.BrushTool;
|
||||
import com.sk89q.worldedit.command.tool.DoubleActionTraceTool;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class InspectBrush implements Brush {
|
||||
public class InspectBrush extends BrushTool implements DoubleActionTraceTool {
|
||||
|
||||
private final Player player;
|
||||
private final int radius;
|
||||
|
||||
public InspectBrush(Player player, double radius) {
|
||||
this.player = player;
|
||||
this.radius = (int) radius;
|
||||
/**
|
||||
* Construct the tool.
|
||||
*/
|
||||
public InspectBrush() {
|
||||
super("worldedit.brush.inspect");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
// TODO
|
||||
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
|
||||
return perform(player, session, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
|
||||
return perform(player, session, true);
|
||||
}
|
||||
|
||||
public WorldVector getTarget(Player player, boolean adjacent) {
|
||||
WorldVector target = null;
|
||||
int range = this.range > -1 ? getRange() : MAX_RANGE;
|
||||
if (adjacent) {
|
||||
WorldVectorFace face = player.getBlockTraceFace(range, true);
|
||||
return face.getFaceVector();
|
||||
} else {
|
||||
return player.getBlockTrace(getRange(), true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean perform(final Player player, LocalSession session, boolean rightClick) {
|
||||
if (!session.isToolControlEnabled() || !player.hasPermission("worldedit.brush.inspect")) {
|
||||
BBC.NO_PERM.send(player, "worldedit.brush.inspect");
|
||||
return false;
|
||||
}
|
||||
if (!Settings.HISTORY.USE_DATABASE) {
|
||||
BBC.SETTING_DISABLE.send(player, "history.use-disk");
|
||||
return false;
|
||||
}
|
||||
WorldVector target = getTarget(player, rightClick);
|
||||
final int x = target.getBlockX();
|
||||
final int y = target.getBlockY();
|
||||
final int z = target.getBlockZ();
|
||||
World world = player.getWorld();
|
||||
final FawePlayer fp = FawePlayer.wrap(player);
|
||||
EditSessionBuilder editSession = new EditSessionBuilder(world).player(fp);
|
||||
String worldName = Fawe.imp().getWorldName(world);
|
||||
RollbackDatabase db = DBHandler.IMP.getDatabase(worldName);
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
db.getPotentialEdits(null, 0, target, target, new RunnableVal<DiskStorageHistory>() {
|
||||
@Override
|
||||
public void run(DiskStorageHistory value) {
|
||||
try {
|
||||
Iterator<MutableFullBlockChange> iter = value.getFullBlockIterator(false);
|
||||
while (iter.hasNext()) {
|
||||
MutableFullBlockChange change = iter.next();
|
||||
if (change.x != x || change.y != y || change.z != z) {
|
||||
continue;
|
||||
}
|
||||
int from = change.from;
|
||||
int to = change.to;
|
||||
UUID uuid = value.getUUID();
|
||||
String name = Fawe.imp().getName(uuid);
|
||||
int index = value.getIndex();
|
||||
long age = System.currentTimeMillis() - value.getBDFile().lastModified();
|
||||
String ageFormatted = MainUtil.secToTime(age / 1000);
|
||||
BBC.TOOL_INSPECT_INFO.send(fp, name, FaweCache.getMaterialName(from), FaweCache.getMaterialName(to), ageFormatted);
|
||||
count.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BBC.TOOL_INSPECT_INFO_FOOTER.send(fp, count);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor actor) {
|
||||
return actor.hasPermission("worldedit.brush.inspect");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package com.boydti.fawe.object.change;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||
import com.boydti.fawe.util.ExtentTraverser;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.UndoContext;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
|
||||
public class MutableFullBlockChange implements Change {
|
||||
|
||||
public int z;
|
||||
public int y;
|
||||
public int x;
|
||||
public int from;
|
||||
public int to;
|
||||
|
||||
|
||||
public MutableFullBlockChange(int x, int y, int z, int combinedFrom, int combinedTo) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.from = combinedFrom;
|
||||
this.to = combinedTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(UndoContext context) throws WorldEditException {
|
||||
create(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo(UndoContext context) throws WorldEditException {
|
||||
create(context);
|
||||
}
|
||||
|
||||
public void create(UndoContext context) {
|
||||
Extent extent = context.getExtent();
|
||||
ExtentTraverser<FastWorldEditExtent> find = new ExtentTraverser(extent).find(FastWorldEditExtent.class);
|
||||
if (find != null) {
|
||||
FastWorldEditExtent fwee = find.get();
|
||||
fwee.getQueue().setBlock(x, y, z, FaweCache.getId(from), FaweCache.getData(from));
|
||||
} else {
|
||||
Fawe.debug("FAWE doesn't support: " + extent + " for " + getClass() + " (bug Empire92)");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.boydti.fawe.object.change;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MutablePlayerBlockChange extends MutableBlockChange {
|
||||
private final UUID uuid;
|
||||
|
||||
public MutablePlayerBlockChange(UUID uuid, int x, int y, int z, short id, byte data) {
|
||||
super(x, y, z, id, data);
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public UUID getUIID() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweInputStream;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.change.MutableBlockChange;
|
||||
import com.boydti.fawe.object.change.MutableEntityChange;
|
||||
import com.boydti.fawe.object.change.MutableFullBlockChange;
|
||||
import com.boydti.fawe.object.change.MutableTileChange;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -226,6 +228,65 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
||||
};
|
||||
}
|
||||
|
||||
public Iterator<MutableFullBlockChange> getFullBlockIterator(final boolean dir) throws IOException {
|
||||
final FaweInputStream is = new FaweInputStream(getBlockIS());
|
||||
if (is == null) {
|
||||
return new ArrayList<MutableFullBlockChange>().iterator();
|
||||
}
|
||||
final MutableFullBlockChange change = new MutableFullBlockChange(0, 0, 0, 0, 0);
|
||||
return new Iterator<MutableFullBlockChange>() {
|
||||
private MutableFullBlockChange last = read();
|
||||
public MutableFullBlockChange read() {
|
||||
try {
|
||||
int read0 = is.read();
|
||||
if (read0 == -1) {
|
||||
return null;
|
||||
}
|
||||
int x = ((byte) read0 & 0xFF) + ((byte) is.read() << 8) + originX;
|
||||
int z = ((byte) is.read() & 0xFF) + ((byte) is.read() << 8) + originZ;
|
||||
int y = is.read() & 0xff;
|
||||
change.x = x;
|
||||
change.y = y;
|
||||
change.z = z;
|
||||
change.from = ((byte) is.read() & 0xFF) + ((byte) is.read() << 8);
|
||||
change.to = ((byte) is.read() & 0xFF) + ((byte) is.read() << 8);
|
||||
return change;
|
||||
} catch (Exception ignoreEOF) {
|
||||
MainUtil.handleError(ignoreEOF);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (last == null) {
|
||||
last = read();
|
||||
}
|
||||
if (last != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableFullBlockChange next() {
|
||||
MutableFullBlockChange tmp = last;
|
||||
last = null;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalArgumentException("CANNOT REMOVE");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Iterator<MutableEntityChange> getEntityIterator(final NBTInputStream is, final boolean create, final boolean dir) {
|
||||
if (is == null) {
|
||||
return new ArrayList<MutableEntityChange>().iterator();
|
||||
|
@ -33,7 +33,16 @@ public class ProcessedWEExtent extends FaweRegionExtent {
|
||||
if (!limit.MAX_ENTITIES() || entity == null) {
|
||||
return null;
|
||||
}
|
||||
return super.createEntity(location, entity);
|
||||
if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) {
|
||||
if (!limit.MAX_CHANGES()) {
|
||||
WEManager.IMP.cancelEditSafe(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
|
||||
return null;
|
||||
}
|
||||
return super.createEntity(location, entity);
|
||||
} else if (!limit.MAX_FAILS()) {
|
||||
WEManager.IMP.cancelEditSafe(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,7 +22,7 @@ public class WEManager {
|
||||
|
||||
public final ArrayDeque<FaweMaskManager> managers = new ArrayDeque<>();
|
||||
|
||||
public void cancelEdit(Extent parent, BBC reason) throws WorldEditException {
|
||||
public void cancelEditSafe(Extent parent, BBC reason) throws FaweException {
|
||||
try {
|
||||
final Field field = AbstractDelegateExtent.class.getDeclaredField("extent");
|
||||
field.setAccessible(true);
|
||||
@ -33,6 +33,10 @@ public class WEManager {
|
||||
throw new FaweException(reason);
|
||||
}
|
||||
|
||||
public void cancelEdit(Extent parent, BBC reason) throws WorldEditException {
|
||||
cancelEditSafe(parent, reason);
|
||||
}
|
||||
|
||||
public boolean maskContains(final HashSet<RegionWrapper> mask, final int x, final int z) {
|
||||
for (final RegionWrapper region : mask) {
|
||||
if ((x >= region.minX) && (x <= region.maxX) && (z >= region.minZ) && (z <= region.maxZ)) {
|
||||
|
@ -27,7 +27,6 @@ import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.CommandBrush;
|
||||
import com.boydti.fawe.object.brush.CopyBrush;
|
||||
import com.boydti.fawe.object.brush.HeightBrush;
|
||||
import com.boydti.fawe.object.brush.InspectBrush;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
@ -80,24 +79,6 @@ public class BrushCommands {
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "inspect", "i" },
|
||||
usage = "<radius>",
|
||||
desc = "Inspect edits within a radius",
|
||||
help =
|
||||
"Chooses the inspect brush",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.inspect")
|
||||
public void inspectBrush(Player player, LocalSession session, EditSession editSession, @Optional("1") double radius) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setSize(radius);
|
||||
tool.setBrush(new InspectBrush(player, radius), "worldedit.brush.inspect");
|
||||
BBC.BRUSH_INSPECT.send(player, radius);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "sphere", "s" },
|
||||
usage = "<pattern> [radius]",
|
||||
|
@ -19,12 +19,22 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -45,6 +55,34 @@ public class HistoryCommands {
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/frb", "frb", "fawerollback", "/fawerollback" },
|
||||
usage = "<user> <radius> <time>",
|
||||
desc = "Undo edits within a radius",
|
||||
min = 3,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.history.undo")
|
||||
public void faweRollback(Player player, LocalSession session, String user, int radius, String time) throws WorldEditException {
|
||||
UUID other = Fawe.imp().getUUID(user);
|
||||
if (other == null) {
|
||||
BBC.PLAYER_NOT_FOUND.send(player, user);
|
||||
return;
|
||||
}
|
||||
long timeDiff = MainUtil.timeToSec(time) * 1000;
|
||||
if (timeDiff == 0) {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb " + user + " " + radius + " <time>");
|
||||
return;
|
||||
}
|
||||
radius = Math.max(Math.min(500, radius), 0);
|
||||
World world = player.getWorld();
|
||||
WorldVector origin = player.getPosition();
|
||||
Vector bot = origin.subtract(radius, radius, radius);
|
||||
Vector top = origin.add(radius, radius, radius);
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/undo", "undo" },
|
||||
usage = "[times] [player]",
|
||||
|
215
core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java
Normal file
215
core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.brush.InspectBrush;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.command.tool.BlockDataCyler;
|
||||
import com.sk89q.worldedit.command.tool.BlockReplacer;
|
||||
import com.sk89q.worldedit.command.tool.DistanceWand;
|
||||
import com.sk89q.worldedit.command.tool.FloatingTreeRemover;
|
||||
import com.sk89q.worldedit.command.tool.FloodFillTool;
|
||||
import com.sk89q.worldedit.command.tool.LongRangeBuildTool;
|
||||
import com.sk89q.worldedit.command.tool.QueryTool;
|
||||
import com.sk89q.worldedit.command.tool.TreePlanter;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.patterns.Pattern;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
public class ToolCommands {
|
||||
private final WorldEdit we;
|
||||
|
||||
public ToolCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "inspect", "i" },
|
||||
usage = "",
|
||||
desc = "Inspect edits within a radius",
|
||||
help =
|
||||
"Chooses the inspect brush",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.inspect")
|
||||
public void inspectBrush(Player player, LocalSession session, EditSession editSession, @Optional("1") double radius) throws WorldEditException {
|
||||
session.setTool(player.getItemInHand(), new InspectBrush());
|
||||
BBC.TOOL_INSPECT.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "none" },
|
||||
usage = "",
|
||||
desc = "Unbind a bound tool from your current item",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
public void none(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
session.setTool(player.getItemInHand(), null);
|
||||
BBC.TOOL_NONE.send(player);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "info" },
|
||||
usage = "",
|
||||
desc = "Block information tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.info")
|
||||
public void info(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
session.setTool(player.getItemInHand(), new QueryTool());
|
||||
BBC.TOOL_INFO.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "tree" },
|
||||
usage = "[type]",
|
||||
desc = "Tree generator tool",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.tree")
|
||||
@SuppressWarnings("deprecation")
|
||||
public void tree(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
TreeGenerator.TreeType type = args.argsLength() > 0 ?
|
||||
type = TreeGenerator.lookup(args.getString(0))
|
||||
: TreeGenerator.TreeType.TREE;
|
||||
|
||||
if (type == null) {
|
||||
BBC.TOOL_TREE_ERROR.send(player, args.getString(0));
|
||||
return;
|
||||
}
|
||||
|
||||
session.setTool(player.getItemInHand(), new TreePlanter(new TreeGenerator(type)));
|
||||
BBC.TOOL_TREE.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "repl" },
|
||||
usage = "<block>",
|
||||
desc = "Block replacer tool",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.replacer")
|
||||
public void repl(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
BaseBlock targetBlock = we.getBlock(player, args.getString(0));
|
||||
session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock));
|
||||
BBC.TOOL_REPL.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cycler" },
|
||||
usage = "",
|
||||
desc = "Block data cycler tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.data-cycler")
|
||||
public void cycler(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setTool(player.getItemInHand(), new BlockDataCyler());
|
||||
BBC.TOOL_CYCLER.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "floodfill", "flood" },
|
||||
usage = "<pattern> <range>",
|
||||
desc = "Flood fill tool",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.flood-fill")
|
||||
public void floodFill(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
int range = args.getInteger(1);
|
||||
|
||||
if (range > config.maxSuperPickaxeSize) {
|
||||
BBC.TOOL_FLOOD_FILL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize);
|
||||
return;
|
||||
}
|
||||
|
||||
Pattern pattern = we.getBlockPattern(player, args.getString(0));
|
||||
session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern));
|
||||
BBC.TOOL_FLOOD_FILL.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "deltree" },
|
||||
usage = "",
|
||||
desc = "Floating tree remover tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.deltree")
|
||||
public void deltree(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
session.setTool(player.getItemInHand(), new FloatingTreeRemover());
|
||||
BBC.TOOL_DELTREE.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "farwand" },
|
||||
usage = "",
|
||||
desc = "Wand at a distance tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.farwand")
|
||||
public void farwand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
session.setTool(player.getItemInHand(), new DistanceWand());
|
||||
BBC.TOOL_FARWAND.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "lrbuild", "/lrbuild" },
|
||||
usage = "<leftclick block> <rightclick block>",
|
||||
desc = "Long-range building tool",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.lrbuild")
|
||||
public void longrangebuildtool(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
BaseBlock secondary = we.getBlock(player, args.getString(0));
|
||||
BaseBlock primary = we.getBlock(player, args.getString(1));
|
||||
session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary));
|
||||
BBC.TOOL_LRBUILD_BOUND.send(player, ItemType.toHeldName(player.getItemInHand()));
|
||||
BBC.TOOL_LRBUILD_INFO.send(player, ItemType.toName(secondary.getType()), ItemType.toName(primary.getType()));
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ToolCommands.class;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user