Optimize undo / use AsyncWorld with RangeBlockHelper / Fix performer
queue / Rename  command
This commit is contained in:
Jesse Boyd 2016-05-24 06:47:12 +10:00
parent 4ac02d6297
commit 89222036ea
9 changed files with 352 additions and 124 deletions

View File

@ -8,7 +8,6 @@ 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;
@ -24,12 +23,25 @@ public abstract class ABukkitMain extends JavaPlugin {
try {
SnipeData.inject();
Sniper.inject();
VoxelPerformerCommand.inject();
// Forward the commands so //p and //d will work
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") {
return (Bukkit.getPluginManager().getPlugin("VoxelSniper")).onCommand(player, new Command("p") {
@Override
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
return false;
}
}, null, args);
}
});
imp.setupCommand("/d", 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("d") {
@Override
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
return false;

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit.wrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
@ -24,6 +25,20 @@ public class AsyncChunk implements Chunk {
this.z = z;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Chunk)) {
return false;
}
Chunk other = (Chunk) obj;
return other.getX() == x && other.getZ() == z && world.equals(other.getWorld());
}
@Override
public int hashCode() {
return MathMan.pair((short) x, (short) z);
}
@Override
public int getX() {
return x;

View File

@ -5,6 +5,7 @@ import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.TaskManager;
import com.intellectualcrafters.plot.util.StringMan;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.world.biome.BaseBiome;
@ -78,6 +79,13 @@ public class AsyncWorld implements World {
}
}
public static AsyncWorld wrap(World world) {
if (world instanceof AsyncWorld) {
return (AsyncWorld) world;
}
return new AsyncWorld(world, false);
}
public void commit() {
queue.enqueue();
}
@ -177,6 +185,20 @@ public class AsyncWorld implements World {
}
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof World)) {
return false;
}
World other = (World) obj;
return StringMan.isEqual(other.getName(), getName());
}
@Override
public int hashCode() {
return this.getUID().hashCode();
}
@Override
public boolean isChunkLoaded(int x, int z) {
return parent.isChunkLoaded(x, z);

View File

@ -0,0 +1,258 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.thevoxelbox.voxelsniper;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
public class RangeBlockHelper {
private static final int MAXIMUM_WORLD_HEIGHT = 255;
private static final double DEFAULT_PLAYER_VIEW_HEIGHT = 1.65D;
private static final double DEFAULT_LOCATION_VIEW_HEIGHT = 0.0D;
private static final double DEFAULT_STEP = 0.2D;
private static final int DEFAULT_RANGE = 250;
private Location playerLoc;
private double rotX;
private double rotY;
private double viewHeight;
private double rotXSin;
private double rotXCos;
private double rotYSin;
private double rotYCos;
private double length;
private double hLength;
private double step;
private double range;
private double playerX;
private double playerY;
private double playerZ;
private double xOffset;
private double yOffset;
private double zOffset;
private int lastX;
private int lastY;
private int lastZ;
private int targetX;
private int targetY;
private int targetZ;
private World world;
public RangeBlockHelper(Location location) {
this.init(location, 250.0D, 0.2D, 0.0D);
}
public RangeBlockHelper(Location location, int range, double step) {
this.world = location.getWorld();
this.init(location, (double)range, step, 0.0D);
}
public RangeBlockHelper(Player player, int range, double step) {
if (player != null) {
this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld();
}
this.init(player.getLocation(), (double)range, step, 1.65D);
}
public RangeBlockHelper(Player player, World world) {
if (player != null && (world == null || player.getWorld().getName().equals(world.getName()))) {
this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld();
} else {
this.world = world;
}
this.init(player.getLocation(), 250.0D, 0.2D, 1.65D);
}
public RangeBlockHelper(Player player, World world, double range) {
if (player != null && (world == null || player.getWorld().getName().equals(world.getName()))) {
this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld();
} else {
this.world = world;
}
this.init(player.getLocation(), range, 0.2D, 1.65D);
this.fromOffworld();
}
public final void fromOffworld() {
if(this.targetY <= 255) {
if(this.targetY < 0) {
while(this.targetY < 0 && this.length <= this.range) {
this.lastX = this.targetX;
this.lastY = this.targetY;
this.lastZ = this.targetZ;
while(true) {
this.length += this.step;
this.hLength = this.length * this.rotYCos;
this.yOffset = this.length * this.rotYSin;
this.xOffset = this.hLength * this.rotXCos;
this.zOffset = this.hLength * this.rotXSin;
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
if(this.length > this.range || this.targetX != this.lastX || this.targetY != this.lastY || this.targetZ != this.lastZ) {
break;
}
}
}
}
} else {
while(this.targetY > 255 && this.length <= this.range) {
this.lastX = this.targetX;
this.lastY = this.targetY;
this.lastZ = this.targetZ;
while(true) {
this.length += this.step;
this.hLength = this.length * this.rotYCos;
this.yOffset = this.length * this.rotYSin;
this.xOffset = this.hLength * this.rotXCos;
this.zOffset = this.hLength * this.rotXSin;
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
if(this.length > this.range || this.targetX != this.lastX || this.targetY != this.lastY || this.targetZ != this.lastZ) {
break;
}
}
}
}
}
public final Block getCurBlock() {
return this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.world.getBlockAt(this.targetX, this.targetY, this.targetZ):null;
}
public final Block getFaceBlock() {
while(this.getNextBlock() != null && this.getCurBlock().getTypeId() == 0) {
;
}
if(this.getCurBlock() != null) {
return this.getLastBlock();
} else {
return null;
}
}
public final Block getLastBlock() {
return this.lastY <= 255 && this.lastY >= 0?this.world.getBlockAt(this.lastX, this.lastY, this.lastZ):null;
}
public final Block getNextBlock() {
this.lastX = this.targetX;
this.lastY = this.targetY;
this.lastZ = this.targetZ;
do {
this.length += this.step;
this.hLength = this.length * this.rotYCos;
this.yOffset = this.length * this.rotYSin;
this.xOffset = this.hLength * this.rotXCos;
this.zOffset = this.hLength * this.rotXSin;
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
} while(this.length <= this.range && this.targetX == this.lastX && this.targetY == this.lastY && this.targetZ == this.lastZ);
return this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.world.getBlockAt(this.targetX, this.targetY, this.targetZ):null;
}
public final Block getRangeBlock() {
this.fromOffworld();
return this.length > this.range?null:this.getRange();
}
public final Block getTargetBlock() {
this.fromOffworld();
while(this.getNextBlock() != null && this.getCurBlock().getTypeId() == 0) {
;
}
return this.getCurBlock();
}
public final void setCurBlock(int type) {
if(this.getCurBlock() != null) {
this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setTypeId(type);
}
}
public final void setFaceBlock(int type) {
while(this.getNextBlock() != null && this.getCurBlock().getTypeId() == 0) {
;
}
if(this.getCurBlock() != null) {
this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setTypeId(type);
}
}
public final void setLastBlock(int type) {
if(this.getLastBlock() != null) {
this.world.getBlockAt(this.lastX, this.lastY, this.lastZ).setTypeId(type);
}
}
public final void setTargetBlock(int type) {
while(this.getNextBlock() != null && this.getCurBlock().getTypeId() == 0) {
;
}
if(this.getCurBlock() != null) {
this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setTypeId(type);
}
}
private Block getRange() {
this.lastX = this.targetX;
this.lastY = this.targetY;
this.lastZ = this.targetZ;
do {
this.length += this.step;
this.hLength = this.length * this.rotYCos;
this.yOffset = this.length * this.rotYSin;
this.xOffset = this.hLength * this.rotXCos;
this.zOffset = this.hLength * this.rotXSin;
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
} while(this.length <= this.range && this.targetX == this.lastX && this.targetY == this.lastY && this.targetZ == this.lastZ);
return this.world.getBlockTypeIdAt(this.targetX, this.targetY, this.targetZ) != 0?this.world.getBlockAt(this.targetX, this.targetY, this.targetZ):(this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.getRange():this.world.getBlockAt(this.lastX, this.lastY, this.lastZ));
}
private void init(Location location, double range, double step, double viewHeight) {
this.playerLoc = location;
this.viewHeight = viewHeight;
this.playerX = this.playerLoc.getX();
this.playerY = this.playerLoc.getY() + this.viewHeight;
this.playerZ = this.playerLoc.getZ();
this.range = range;
this.step = step;
this.length = 0.0D;
this.rotX = (double)((this.playerLoc.getYaw() + 90.0F) % 360.0F);
this.rotY = (double)(this.playerLoc.getPitch() * -1.0F);
this.rotYCos = Math.cos(Math.toRadians(this.rotY));
this.rotYSin = Math.sin(Math.toRadians(this.rotY));
this.rotXCos = Math.cos(Math.toRadians(this.rotX));
this.rotXSin = Math.sin(Math.toRadians(this.rotX));
this.targetX = (int)Math.floor(this.playerLoc.getX());
this.targetY = (int)Math.floor(this.playerLoc.getY() + this.viewHeight);
this.targetZ = (int)Math.floor(this.playerLoc.getZ());
this.lastX = this.targetX;
this.lastY = this.targetY;
this.lastZ = this.targetZ;
}
}

View File

@ -34,7 +34,6 @@ 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;
@ -79,13 +78,24 @@ public class Sniper {
// Added
private AsyncWorld tmpWorld;
private MaskedFaweQueue mask;
private ChangeSetFaweQueue change;
private MaskedFaweQueue maskQueue;
private ChangeSetFaweQueue changeQueue;
private FaweQueue baseQueue;
// Added
public World getWorld() {
public AsyncWorld getWorld() {
if (this.tmpWorld == null) {
return new AsyncWorld(getPlayer().getWorld(), false);
Player player = getPlayer();
FawePlayer<Player> fp = FawePlayer.wrap(player);
if (this.baseQueue == null) {
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();
FaweStreamChangeSet changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(worldEditWorld, fp.getUUID()) : new MemoryOptimizedHistory(worldEditWorld);
this.changeQueue = new ChangeSetFaweQueue(changeSet, maskQueue);
tmpWorld = new AsyncWorld(player.getWorld(), changeQueue);
}
return tmpWorld;
}
@ -106,25 +116,18 @@ public class Sniper {
public boolean snipe(Action action, Material itemInHand, Block clickedBlock, BlockFace clickedFace) {
try {
// Added
FaweQueue queue;
{
Player player = getPlayer();
FawePlayer<Player> fp = FawePlayer.wrap(player);
if (fp.getMeta("fawe_action") != null) {
return false;
}
RegionWrapper[] mask = WEManager.IMP.getMask(fp);
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);
tmpWorld = null;
if (clickedBlock != null) {
clickedBlock = tmpWorld.getBlockAt(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());
clickedBlock = getWorld().getBlockAt(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());
}
}
return snipe(action, itemInHand, tmpWorld, clickedBlock, clickedFace);
return snipe(action, itemInHand, getWorld(), clickedBlock, clickedFace);
} catch (Throwable e) {
e.printStackTrace();
}
@ -299,20 +302,20 @@ public class Sniper {
// MetricsManager.increaseBrushUsage(sniperTool.getCurrentBrush().getName());
// }
// return result;
IBrush brush = sniperTool.getCurrentBrush();
if (sniperTool.getCurrentBrush() instanceof PerformBrush) {
PerformBrush performerBrush = (PerformBrush) sniperTool.getCurrentBrush();
performerBrush.initP(snipeData);
}
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
FawePlayer<Player> 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);
boolean result = brush.perform(snipeAction, snipeData, targetBlock, lastBlock);
if (result) {
MetricsManager.increaseBrushUsage(sniperTool.getCurrentBrush().getName());
MetricsManager.increaseBrushUsage(brush.getName());
}
world.commit();
} catch (Throwable e) {
@ -391,21 +394,12 @@ public class Sniper {
}
public void storeUndo(Undo undo) {
if (change != null) {
FaweChangeSet changeSet = change.getChangeSet();
if (changeQueue != null) {
FaweChangeSet changeSet = changeQueue.getChangeSet();
FawePlayer<Object> 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() {
@ -478,7 +472,7 @@ public class Sniper {
messageHelper = new Message(snipeData);
snipeData.setVoxelMessage(messageHelper);
IBrush newBrushInstance = instanciateBrush(currentBrush);
IBrush newBrushInstance = instantiateBrush(currentBrush);
if (snipeData.owner().getPlayer().hasPermission(newBrushInstance.getPermissionNode())) {
brushes.put(currentBrush, newBrushInstance);
this.currentBrush = currentBrush;
@ -528,7 +522,7 @@ public class Sniper {
Preconditions.checkNotNull(brush, "Can't set brush to null.");
IBrush brushInstance = brushes.get(brush);
if (brushInstance == null) {
brushInstance = instanciateBrush(brush);
brushInstance = instantiateBrush(brush);
Preconditions.checkNotNull(brushInstance, "Could not instanciate brush class.");
if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode())) {
brushes.put(brush, brushInstance);
@ -554,7 +548,7 @@ public class Sniper {
return setCurrentBrush(previousBrush);
}
private IBrush instanciateBrush(Class<? extends IBrush> brush) {
private IBrush instantiateBrush(Class<? extends IBrush> brush) {
try {
return brush.newInstance();
} catch (InstantiationException e) {

View File

@ -1,13 +1,8 @@
package com.thevoxelbox.voxelsniper;
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.Set;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.util.Vector;
/**
* Holds {@link BlockState}s that can be later on used to reset those block
@ -15,17 +10,13 @@ import org.bukkit.util.Vector;
*/
public class Undo {
private final Set<Vector> containing = Sets.newHashSet();
private final ArrayDeque<BlockState> all;
int size;
private World world;
/**
* Default constructor of a Undo container.
*/
public Undo() {
all = new ArrayDeque<BlockState>();
}
public Undo() {}
/**
* Get the number of blocks in the collection.
@ -33,7 +24,7 @@ public class Undo {
* @return size of the Undo collection
*/
public int getSize() {
return containing.size();
return size;
}
/**
@ -42,27 +33,15 @@ public class Undo {
* @param block Block to be added
*/
public void put(Block block) {
if (world == null) {
world = block.getWorld();
}
Vector pos = block.getLocation().toVector();
if (this.containing.contains(pos)) {
return;
}
this.containing.add(pos);
all.add(block.getState());
size++;
}
/**
* Set the blockstates of all recorded blocks back to the state when they
* were inserted.
*/
public void undo() {
for (BlockState blockState : all) {
blockState.update(true, false);
}
if (world instanceof AsyncWorld) {
((AsyncWorld) world).commit();
}
}
}

View File

@ -1,58 +0,0 @@
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;
}
}

View File

@ -33,6 +33,9 @@ commands:
'/p':
description: VoxelSniper perform command
aliases: [perform,/perform]
'/d':
description: VoxelSniper default command
aliases: [default,/default]
permissions:
fawe.bypass:
default: false

View File

@ -33,6 +33,9 @@ commands:
'/p':
description: VoxelSniper perform command
aliases: [perform,/perform]
'/d':
description: VoxelSniper default command
aliases: [default,/default]
permissions:
fawe.bypass:
default: false