From bc46688a98a424219551680c8c2f332ffd5e1bd8 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 6 Mar 2017 21:37:16 +1100 Subject: [PATCH] Fixes #450 --- .../fawe/bukkit/wrapper/AsyncWorld.java | 12 +- .../boydti/fawe/example/CharFaweChunk.java | 8 ++ .../java/com/sk89q/worldedit/EditSession.java | 7 +- .../com/thevoxelbox/voxelsniper/Sniper.java | 136 +++++++++--------- 4 files changed, 92 insertions(+), 71 deletions(-) diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index c345dacd..2772477e 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -137,6 +137,11 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue setParent(queue); } + @Override + public String toString() { + return super.toString() + ":" + queue.toString(); + } + public World getBukkitWorld() { return parent; } @@ -153,7 +158,8 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue */ public synchronized static AsyncWorld create(final WorldCreator creator) { BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(creator.name(), true, false); - World world = queue.createWorld(creator); + World world = queue.createWorld( + creator); return wrap(world); } @@ -245,7 +251,7 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue @Override @Deprecated public int getBlockTypeIdAt(int x, int y, int z) { - return queue.getCombinedId4Data(x, y & 0xFF, z, 0) >> 4; + return queue.getCachedCombinedId4Data(x, y & 0xFF, z, 0) >> 4; } @Override @@ -257,7 +263,7 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue @Override public int getHighestBlockYAt(int x, int z) { for (int y = getMaxHeight() - 1; y >= 0; y--) { - if (queue.getCombinedId4Data(x, y, z, 0) != 0) { + if (queue.getCachedCombinedId4Data(x, y, z, 0) != 0) { return y; } } diff --git a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java index 27cad6f1..862988b9 100644 --- a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java @@ -94,6 +94,14 @@ public abstract class CharFaweChunk extends FaweChunk return total; } + public int getTotalAir() { + int total = 0; + for (int i = 0; i < air.length; i++) { + total += Math.min(4096, this.air[i]); + } + return total; + } + @Override public int getBitMask() { int bitMask = 0; diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index 34ba7ce5..23baac82 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -247,6 +247,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting if (combineStages == null) { combineStages = Settings.IMP.HISTORY.COMBINE_STAGES && !(queue instanceof MCAQueue); } + if (limit.FAST_PLACEMENT) { + combineStages = false; + } if (checkMemory) { if (MemUtil.isMemoryLimitedSlow()) { if (Perm.hasPermission(player, "worldedit.fast")) { @@ -292,7 +295,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } else { changeSet = new DiskStorageHistory(world, uuid); } - } else if (Settings.IMP.HISTORY.COMBINE_STAGES && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) { + } else if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) { changeSet = new CPUOptimizedChangeSet(world); } else { changeSet = new MemoryOptimizedHistory(world); @@ -308,7 +311,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting if (this.blockBag != null && limit.INVENTORY_MODE > 0) { changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1); } - if (combineStages && limit.FAST_PLACEMENT) { + if (combineStages) { changeTask = changeSet; changeSet.addChangeTask(queue); } else { diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java index e312ca98..2078e7e5 100644 --- a/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java @@ -4,22 +4,22 @@ import com.boydti.fawe.Fawe; 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.logging.LoggingChangeSet; 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.RunnableVal; import com.boydti.fawe.object.changeset.FaweChangeSet; -import com.boydti.fawe.util.StringMan; +import com.boydti.fawe.util.SetQueue; +import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.WEManager; import com.google.common.base.Preconditions; import com.google.common.collect.BiMap; import com.google.common.collect.ClassToInstanceMap; 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; @@ -28,11 +28,13 @@ 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.HashMap; import java.util.Map; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; @@ -47,7 +49,7 @@ public class Sniper { private final UUID player; private boolean enabled = true; // private LinkedList undoList = new LinkedList<>(); - private Map tools = Maps.newHashMap(); + private Map tools = new HashMap<>(); public Sniper(VoxelSniper plugin, Player player) { this.plugin = plugin; @@ -77,57 +79,20 @@ public class Sniper { // Added private AsyncWorld permanentWorld; - private MaskedFaweQueue maskQueue; - private ChangeSetFaweQueue changeQueue; - private FaweQueue baseQueue; public void storeUndo(Undo undo) { - ChangeSetFaweQueue tmpQueue; - synchronized (this) { - tmpQueue = changeQueue; - maskQueue = null; - baseQueue = null; - changeQueue = null; - } - if (tmpQueue != null) { - FaweChangeSet changeSet = tmpQueue.getChangeSet(); - changeSet.closeAsync(); - FawePlayer fp = FawePlayer.wrap(getPlayer()); - LocalSession session = fp.getSession(); - session.remember(changeSet.toEditSession(fp)); - } } // Added public AsyncWorld getWorld() { - synchronized (this) { - if (permanentWorld == null) { - permanentWorld = new AsyncWorld(null, null); - } - if (this.maskQueue == null) { - Player player = getPlayer(); - FawePlayer fp = FawePlayer.wrap(player); - if (this.baseQueue == null || !StringMan.isEqual(baseQueue.getWorldName(), player.getWorld().getName())) { - this.baseQueue = FaweAPI.createQueue(fp.getLocation().world, false); - } - RegionWrapper[] mask = WEManager.IMP.getMask(fp); - this.maskQueue = new MaskedFaweQueue(baseQueue, mask); - com.sk89q.worldedit.world.World worldEditWorld = fp.getWorld(); - FaweChangeSet changeSet = FaweChangeSet.getDefaultChangeSet(worldEditWorld, fp.getUUID()); - if (Fawe.imp().getBlocksHubApi() != null) { - changeSet = LoggingChangeSet.wrap(fp, changeSet); - } - this.changeQueue = new ChangeSetFaweQueue(changeSet, maskQueue); - permanentWorld.changeWorld(player.getWorld(), changeQueue); - } - return permanentWorld; - } - } - - public void resetMask() { - synchronized (this) { - maskQueue = null; + AsyncWorld world = permanentWorld; + if (world == null) { + Player bukkitPlayer = getPlayer(); + World bukkitWorld = bukkitPlayer.getWorld(); + world = AsyncWorld.wrap(bukkitWorld); + permanentWorld = world; } + return world; } public Player getPlayer() { @@ -143,15 +108,23 @@ public class Sniper { * @param clickedFace Face of that targeted Block * @return true if command visibly processed, false otherwise. */ - public boolean snipe(Action action, Material itemInHand, Block clickedBlock, BlockFace clickedFace) { + public boolean snipe(final Action action, final Material itemInHand, final Block clickedBlock, final BlockFace clickedFace) { try { Player player = getPlayer(); - FawePlayer fp = FawePlayer.wrap(player); - resetMask(); - if (clickedBlock != null) { - clickedBlock = getWorld().getBlockAt(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); - } - return snipe(action, itemInHand, getWorld(), clickedBlock, clickedFace); + final FawePlayer fp = FawePlayer.wrap(player); + TaskManager.IMP.taskNow(new Runnable() { + @Override + public void run() { + if (!fp.runAction(new Runnable() { + @Override + public void run() { + snipeOnCurrentThread(fp, action, itemInHand, clickedBlock, clickedFace); + } + }, true, false)) { + BBC.WORLDEDIT_COMMAND_LIMIT.send(fp); + } + } + }, Fawe.isMainThread()); } catch (Throwable e) { e.printStackTrace(); } @@ -159,7 +132,33 @@ public class Sniper { } // Old method (plus world arg) - public boolean snipe(final Action action, final Material itemInHand, final AsyncWorld world, final Block clickedBlock, final BlockFace clickedFace) { + public synchronized boolean snipeOnCurrentThread(FawePlayer fp, final Action action, final Material itemInHand, Block clickedBlock, final BlockFace clickedFace) { + Player bukkitPlayer = getPlayer(); + World bukkitWorld = bukkitPlayer.getWorld(); + + FaweQueue baseQueue = FaweAPI.createQueue(fp.getLocation().world, false); + RegionWrapper[] mask = WEManager.IMP.getMask(fp); + MaskedFaweQueue maskQueue = new MaskedFaweQueue(baseQueue, mask); + com.sk89q.worldedit.world.World worldEditWorld = fp.getWorld(); + FaweChangeSet changeSet = FaweChangeSet.getDefaultChangeSet(worldEditWorld, fp.getUUID()); + if (Fawe.imp().getBlocksHubApi() != null) { + changeSet = LoggingChangeSet.wrap(fp, changeSet); + } + FaweQueue changeQueue; + if (Settings.IMP.HISTORY.COMBINE_STAGES) { + changeQueue = maskQueue; + changeSet.addChangeTask(baseQueue); + } else { + changeQueue = new ChangeSetFaweQueue(changeSet, maskQueue); + } + AsyncWorld world = getWorld(); + world.changeWorld(bukkitWorld, changeQueue); + + if (clickedBlock != null) { + clickedBlock = world.getBlockAt(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); + } + + String toolId = getToolId(itemInHand); SniperTool sniperTool = tools.get(toolId); @@ -320,17 +319,22 @@ public class Sniper { PerformBrush performerBrush = (PerformBrush) sniperTool.getCurrentBrush(); performerBrush.initP(snipeData); } - final FawePlayer fp = FawePlayer.wrap(getPlayer()); - fp.runAsyncIfFree(new RunnableVal() { - @Override - public void run(Boolean value) { - boolean result = brush.perform(snipeAction, snipeData, targetBlock, lastBlock); - if (result) { - MetricsManager.increaseBrushUsage(brush.getName()); - } - world.commit(); + + boolean result = brush.perform(snipeAction, snipeData, targetBlock, lastBlock); + if (Fawe.isMainThread()) { + SetQueue.IMP.flush(changeQueue); + } else { + changeQueue.flush(); + } + if (changeSet != null) { + if (Settings.IMP.HISTORY.COMBINE_STAGES) { + changeSet.closeAsync(); + } else { + changeSet.close(); } - }); + LocalSession session = fp.getSession(); + session.remember(changeSet.toEditSession(fp)); + } return true; } }