diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java index 5c42e3e6..af9eaadb 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java @@ -2,21 +2,42 @@ package com.boydti.fawe.bukkit; import com.boydti.fawe.Fawe; import com.boydti.fawe.object.EditSessionWrapper; +import com.boydti.fawe.object.FaweCommand; +import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; import com.sk89q.worldedit.EditSession; import com.thevoxelbox.voxelsniper.SnipeData; import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.command.VoxelPerformerCommand; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; public abstract class ABukkitMain extends JavaPlugin { @Override public void onEnable() { - new FaweBukkit(this); + FaweBukkit imp = new FaweBukkit(this); try { SnipeData.inject(); Sniper.inject(); + VoxelPerformerCommand.inject(); + imp.setupCommand("/p", new FaweCommand("voxelsniper.sniper") { + @Override + public boolean execute(FawePlayer fp, String... args) { + Player player = (Player) fp.parent; + return (Bukkit.getPluginManager().getPlugin("VoxelSniper")).onCommand(player, new Command("/p") { + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + return false; + } + }, null, args); + + } + }); Fawe.debug("Injected VoxelSniper classes"); } catch (Throwable ignore) {} } @@ -24,4 +45,4 @@ public abstract class ABukkitMain extends JavaPlugin { public abstract FaweQueue getQueue(String world); public abstract EditSessionWrapper getEditSessionWrapper(EditSession session); -} +} \ No newline at end of file diff --git a/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java b/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java index 6ead4a1f..a147fc35 100644 --- a/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java +++ b/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java @@ -2,10 +2,17 @@ package com.thevoxelbox.voxelsniper; import com.boydti.fawe.FaweAPI; import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.ChangeSetFaweQueue; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.MaskedFaweQueue; import com.boydti.fawe.object.RegionWrapper; +import com.boydti.fawe.object.changeset.DiskStorageHistory; +import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.changeset.FaweStreamChangeSet; +import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.WEManager; import com.google.common.base.Preconditions; @@ -15,13 +22,13 @@ import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.Maps; import com.google.common.collect.MutableClassToInstanceMap; +import com.sk89q.worldedit.LocalSession; import com.thevoxelbox.voxelsniper.brush.IBrush; import com.thevoxelbox.voxelsniper.brush.SnipeBrush; import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; import com.thevoxelbox.voxelsniper.brush.perform.Performer; import com.thevoxelbox.voxelsniper.event.SniperMaterialChangedEvent; import com.thevoxelbox.voxelsniper.event.SniperReplaceMaterialChangedEvent; -import java.util.LinkedList; import java.util.Map; import java.util.UUID; import org.bukkit.Bukkit; @@ -41,7 +48,7 @@ public class Sniper { private VoxelSniper plugin; private final UUID player; private boolean enabled = true; - private LinkedList undoList = new LinkedList(); +// private LinkedList undoList = new LinkedList<>(); private Map tools = Maps.newHashMap(); public Sniper(VoxelSniper plugin, Player player) { @@ -73,6 +80,7 @@ public class Sniper { // Added private AsyncWorld tmpWorld; private MaskedFaweQueue mask; + private ChangeSetFaweQueue change; // Added public World getWorld() { @@ -102,14 +110,16 @@ public class Sniper { { Player player = getPlayer(); FawePlayer fp = FawePlayer.wrap(player); - RegionWrapper[] mask = WEManager.IMP.getMask(fp).toArray(new RegionWrapper[0]); - if (tmpWorld == null || !player.getWorld().getName().equals(tmpWorld.getName())) { - queue = FaweAPI.createQueue(fp.getLocation().world, true); - this.mask = (MaskedFaweQueue) (queue = new MaskedFaweQueue(queue, mask)); - tmpWorld = new AsyncWorld(player.getWorld(), queue); - } else if (this.mask != null) { - this.mask.setMask(mask); + if (fp.getMeta("fawe_action") != null) { + return false; } + RegionWrapper[] mask = WEManager.IMP.getMask(fp).toArray(new RegionWrapper[0]); + queue = FaweAPI.createQueue(fp.getLocation().world, true); + this.mask = (MaskedFaweQueue) (queue = new MaskedFaweQueue(queue, mask)); + com.sk89q.worldedit.world.World worldEditWorld = fp.getWorld(); + FaweStreamChangeSet changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(worldEditWorld, fp.getUUID()) : new MemoryOptimizedHistory(worldEditWorld); + this.change = (ChangeSetFaweQueue) (queue = new ChangeSetFaweQueue(changeSet, queue)); + tmpWorld = new AsyncWorld(player.getWorld(), queue); if (clickedBlock != null) { clickedBlock = tmpWorld.getBlockAt(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); } @@ -292,16 +302,24 @@ public class Sniper { TaskManager.IMP.async(new Runnable() { @Override public void run() { - if (sniperTool.getCurrentBrush() instanceof PerformBrush) { - PerformBrush performerBrush = (PerformBrush) sniperTool.getCurrentBrush(); - performerBrush.initP(snipeData); + FawePlayer fp = FawePlayer.wrap(getPlayer()); + fp.setMeta("fawe_action", true); + try { + if (sniperTool.getCurrentBrush() instanceof PerformBrush) { + PerformBrush performerBrush = (PerformBrush) sniperTool.getCurrentBrush(); + performerBrush.initP(snipeData); + world.commit(); + } + boolean result = sniperTool.getCurrentBrush().perform(snipeAction, snipeData, targetBlock, lastBlock); + if (result) { + MetricsManager.increaseBrushUsage(sniperTool.getCurrentBrush().getName()); + } world.commit(); + } catch (Throwable e) { + e.printStackTrace(); + } finally { + fp.deleteMeta("fawe_action"); } - boolean result = sniperTool.getCurrentBrush().perform(snipeAction, snipeData, targetBlock, lastBlock); - if (result) { - MetricsManager.increaseBrushUsage(sniperTool.getCurrentBrush().getName()); - } - world.commit(); } }); return true; @@ -373,15 +391,21 @@ public class Sniper { } public void storeUndo(Undo undo) { - if (VoxelSniper.getInstance().getVoxelSniperConfiguration().getUndoCacheSize() <= 0) { - return; - } - if (undo != null && undo.getSize() > 0) { - while (undoList.size() >= plugin.getVoxelSniperConfiguration().getUndoCacheSize()) { - this.undoList.pollLast(); - } - undoList.push(undo); + if (change != null) { + FaweChangeSet changeSet = change.getChangeSet(); + FawePlayer fp = FawePlayer.wrap(getPlayer()); + LocalSession session = fp.getSession(); + session.remember(changeSet.toEditSession(fp.getPlayer())); } +// if (VoxelSniper.getInstance().getVoxelSniperConfiguration().getUndoCacheSize() <= 0) { +// return; +// } +// if (undo != null && undo.getSize() > 0) { +// while (undoList.size() >= plugin.getVoxelSniperConfiguration().getUndoCacheSize()) { +// this.undoList.pollLast(); +// } +// undoList.push(undo); +// } } public void undo() { @@ -389,20 +413,18 @@ public class Sniper { } public void undo(int amount) { - int sum = 0; - if (this.undoList.isEmpty()) { - getPlayer().sendMessage(ChatColor.GREEN + "There's nothing to undo."); - } else { - for (int x = 0; x < amount && !undoList.isEmpty(); x++) { - Undo undo = this.undoList.pop(); - if (undo != null) { - undo.undo(); - sum += undo.getSize(); - } else { - break; - } + FawePlayer fp = FawePlayer.wrap(getPlayer()); + int count = 0; + for (int i = 0; i < amount; i++) { + if (fp.getSession().undo(null, fp.getPlayer()) == null) { + break; } - getPlayer().sendMessage(ChatColor.GREEN + "Undo successful: " + ChatColor.RED + sum + ChatColor.GREEN + " blocks have been replaced."); + count++; + } + if (count > 0) { + BBC.COMMAND_UNDO_SUCCESS.send(fp); + } else { + BBC.COMMAND_UNDO_FAIL.send(fp); } } diff --git a/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPerformerCommand.java b/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPerformerCommand.java new file mode 100644 index 00000000..9a775562 --- /dev/null +++ b/bukkit0/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPerformerCommand.java @@ -0,0 +1,58 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import com.thevoxelbox.voxelsniper.brush.IBrush; +import com.thevoxelbox.voxelsniper.brush.perform.Performer; +import java.util.logging.Level; +import org.bukkit.entity.Player; + +public class VoxelPerformerCommand + extends VoxelCommand +{ + public VoxelPerformerCommand(VoxelSniper plugin) + { + super("VoxelPerformer", plugin); + setIdentifier("/p"); + setPermission("voxelsniper.sniper"); + } + + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = this.plugin.getSniperManager().getSniperForPlayer(player); + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + try + { + if ((args == null) || (args.length == 0)) + { + IBrush brush = sniper.getBrush(sniper.getCurrentToolId()); + if ((brush instanceof Performer)) { + ((Performer)brush).parse(new String[] { "m" }, snipeData); + } else { + player.sendMessage("This brush is not a performer brush."); + } + } + else + { + IBrush brush = sniper.getBrush(sniper.getCurrentToolId()); + if ((brush instanceof Performer)) { + ((Performer)brush).parse(args, snipeData); + } else { + player.sendMessage("This brush is not a performer brush."); + } + } + return true; + } + catch (Exception exception) + { + this.plugin.getLogger().log(Level.WARNING, "Command error from " + player.getName(), exception); + } + return true; + } + + public static Class inject() { + return VoxelPerformerCommand.class; + } +} diff --git a/bukkit18/src/main/resources/plugin.yml b/bukkit18/src/main/resources/plugin.yml index 3549a844..785d462f 100644 --- a/bukkit18/src/main/resources/plugin.yml +++ b/bukkit18/src/main/resources/plugin.yml @@ -30,6 +30,9 @@ commands: fcancel: description: (FAWE) Cancel your edit aliases: [fawecancel,/fcancel,/cancel,/fawecancel] + '/p': + description: VoxelSniper perform command + aliases: [perform,/perform] permissions: fawe.bypass: default: false diff --git a/bukkit19/src/main/resources/plugin.yml b/bukkit19/src/main/resources/plugin.yml index 17f77a6d..80981eb9 100644 --- a/bukkit19/src/main/resources/plugin.yml +++ b/bukkit19/src/main/resources/plugin.yml @@ -30,6 +30,9 @@ commands: fcancel: description: (FAWE) Cancel your edit aliases: [fawecancel,/fcancel,/cancel,/fawecancel] + '/p': + description: VoxelSniper perform command + aliases: [perform,/perform] permissions: fawe.bypass: default: false diff --git a/core/src/main/java/com/boydti/fawe/object/ChangeSetFaweQueue.java b/core/src/main/java/com/boydti/fawe/object/ChangeSetFaweQueue.java new file mode 100644 index 00000000..1d53dda7 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/ChangeSetFaweQueue.java @@ -0,0 +1,55 @@ +package com.boydti.fawe.object; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.util.DelegateFaweQueue; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.world.biome.BaseBiome; + +public class ChangeSetFaweQueue extends DelegateFaweQueue { + private final FaweChangeSet set; + + public ChangeSetFaweQueue(FaweChangeSet set, FaweQueue parent) { + super(parent); + this.set = set; + } + + public FaweChangeSet getChangeSet() { + return set; + } + + @Override + public boolean setBlock(int x, int y, int z, short id, byte data) { + if (super.setBlock(x, y, z, id, data)) { + int combinedFrom = getParent().getCombinedId4Data(x, y, z); + if (FaweCache.hasNBT(combinedFrom >> 4)) { + CompoundTag nbt = getParent().getTileEntity(x, y, z); + if (nbt != null) { + set.addTileRemove(nbt); + } + } + int combinedTo = (id << 4) + data; + set.add(x, y, z, combinedFrom, combinedTo); + return true; + } + return false; + } + + @Override + public boolean setBiome(int x, int z, BaseBiome biome) { + // TODO undo biome change + return super.setBiome(x, z, biome); + } + + @Override + public void setTile(int x, int y, int z, CompoundTag tag) { + super.setTile(x, y, z, tag); + set.addTileCreate(tag); + } + + @Override + public void setEntity(int x, int y, int z, CompoundTag tag) { + super.setEntity(x, y, z, tag); + set.addEntityCreate(tag); + } +} diff --git a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java index 40589414..6732e5b8 100644 --- a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java @@ -19,6 +19,10 @@ public class DelegateFaweQueue extends FaweQueue { this.parent = parent; } + public FaweQueue getParent() { + return parent; + } + @Override public String getWorldName() { return parent.getWorldName();