This commit is contained in:
Jesse Boyd 2016-04-28 15:00:49 +10:00
parent 4ec9ed3a8d
commit 3b9408d381
28 changed files with 419 additions and 188 deletions

View File

@ -10,7 +10,7 @@ buildscript {
}
group = 'com.boydti.fawe'
version = '3.4.1'
version = '3.4.2'
description = """FastAsyncWorldEdit"""
subprojects {

View File

@ -1,6 +1,6 @@
name: FastAsyncWorldEdit
main: com.boydti.fawe.bukkit.FaweBukkit
version: 3.4.1
version: 3.4.2
description: Fast Async WorldEdit plugin
authors: [Empire92]
loadbefore: [WorldEdit]

View File

@ -13,6 +13,8 @@ import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.bukkit.BukkitUtil;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import org.bukkit.Bukkit;
@ -56,6 +58,35 @@ public class BukkitQueue_All extends BukkitQueue_0 {
}
}
private volatile boolean timingsEnabled;
@Override
public void startSet(boolean parallel) {
if (parallel) {
try {
Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");
fieldEnabled.setAccessible(true);
timingsEnabled = (boolean) fieldEnabled.get(null);
if (timingsEnabled) {
fieldEnabled.set(null, false);
Method methodCheck = Class.forName("co.aikar.timings.TimingsManager").getDeclaredMethod("recheckEnabled");
methodCheck.setAccessible(true);
methodCheck.invoke(null);
}
} catch (Throwable ignore) {}
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, false); } catch (Throwable ignore) {}
}
}
@Override
public void endSet(boolean parallel) {
if (parallel) {
try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled);
} catch (Throwable ignore) {ignore.printStackTrace();}
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {}
}
}
@Override
public Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs) {
return new ArrayList<>();

View File

@ -129,7 +129,7 @@ public class BukkitQueue_1_8 extends BukkitQueue_All {
@Override
public void run() {
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
TaskManager.IMP.task(new Runnable() {
TaskManager.IMP.sync(new Runnable() {
@Override
public void run() {
if (!result) {

View File

@ -115,7 +115,7 @@ public class BukkitQueue_1_9 extends BukkitQueue_All {
@Override
public void run() {
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
TaskManager.IMP.task(new Runnable() {
TaskManager.IMP.sync(new Runnable() {
@Override
public void run() {
if (!result) {

View File

@ -45,8 +45,6 @@ import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
private IBlockData air = Block.getByCombinedId(0);
public BukkitQueue_1_9_R1(final String world) throws NoSuchMethodException, RuntimeException {
super(world);
}
@ -87,7 +85,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
@Override
public void run() {
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
TaskManager.IMP.task(new Runnable() {
TaskManager.IMP.sync(new Runnable() {
@Override
public void run() {
if (!result) {
@ -304,7 +302,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
continue;
}
DataPaletteBlock nibble = section.getBlocks();
Field fieldBits = nibble.getClass().getDeclaredField("b");
fieldBits.setAccessible(true);
DataBits bits = (DataBits) fieldBits.get(nibble);
@ -424,12 +421,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
}
}
}
TaskManager.IMP.later(new Runnable() {
@Override
public void run() {
sendChunk(fs);
}
}, 1);
sendChunk(fs);
return true;
}

View File

@ -1,6 +1,6 @@
name: FastAsyncWorldEdit
main: com.boydti.fawe.bukkit.FaweBukkit
version: 3.4.1
version: 3.4.2
description: Fast Async WorldEdit plugin
authors: [Empire92]
loadbefore: [WorldEdit]

View File

@ -51,6 +51,7 @@ public class Cancel extends FaweCommand {
session.bypassReorderHistory = nullExtent;
session.faweExtent = nullExtent;
queue.clear();
SetQueue.IMP.dequeue(queue);
}
}
}

View File

@ -5,8 +5,10 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.BufferedRandomAccessFile;
import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
@ -173,10 +175,11 @@ public class DiskOptimizedClipboard extends FaweClipboard {
if (raf != null) {
close();
}
lastAccessed = System.currentTimeMillis();
this.raf = new BufferedRandomAccessFile(file, "rw", Settings.BUFFER_SIZE);
long size = width * height * length * 2l;
long size = width * height * length * 2l + HEADER_SIZE;
if (raf.length() != size) {
raf.setLength(size + HEADER_SIZE);
raf.setLength(size);
// write length etc
raf.seek(0);
last = 0;
@ -208,6 +211,54 @@ public class DiskOptimizedClipboard extends FaweClipboard {
private int zlast;
private int zlasti;
@Override
public void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air) {
try {
if (raf == null) {
open();
}
raf.seek(HEADER_SIZE);
BlockVector pos = new BlockVector(0, 0, 0);
int x = 0;
int y = 0;
int z = 0;
long len = (raf.length());
for (long i = HEADER_SIZE; i < len; i+=2) {
pos.x = x;
pos.y = y;
pos.z = z;
if (++x >= width) {
x = 0;
if (++z >= length) {
z = 0;
++y;
}
}
raf.seek(i);
raf.read(buffer);
int id = ((((int) buffer[1] & 0xFF) << 4) + (((int) buffer[0] & 0xFF) >> 4));
if (id == 0 && !air) {
continue;
}
BaseBlock block;
if (!FaweCache.hasData(id)) {
block = FaweCache.CACHE_BLOCK[id << 4];
} else {
block = FaweCache.CACHE_BLOCK[(id << 4) + (buffer[0] & 0xF)];
}
if (FaweCache.hasNBT(id)) {
CompoundTag nbt = nbtMap.get(new IntegerTrio((int) pos.x, (int) pos.y, (int) pos.z));
if (nbt != null) {
block = new BaseBlock(block.getId(), block.getData());
block.setNbtData(nbt);
}
}
task.run(pos, block);
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public BaseBlock getBlock(int x, int y, int z) {
@ -218,6 +269,7 @@ public class DiskOptimizedClipboard extends FaweClipboard {
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1));
lastAccessed = System.currentTimeMillis();
}
raf.read(buffer);
last = i;
@ -248,10 +300,10 @@ public class DiskOptimizedClipboard extends FaweClipboard {
if (raf == null) {
open();
}
lastAccessed = System.currentTimeMillis();
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1));
lastAccessed = System.currentTimeMillis();
}
last = i;
final int id = block.getId();

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.object.RunnableVal2;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
@ -25,6 +26,8 @@ public abstract class FaweClipboard {
public void setOrigin(Vector offset) {} // Do nothing
public abstract void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air);
/**
* Stores entity data.
*/

View File

@ -8,6 +8,26 @@ import java.util.List;
public abstract class LazyClipboard extends FaweClipboard {
// private final int width, height, length;
//
// public LazyClipboard(int width, int height, int length) {
// this.width = width;
// this.height = height;
// this.length = length;
// }
//
// @Override
// public void forEach(RunnableVal2<Vector, BaseBlock> task, boolean air) {
// BlockVector pos = new BlockVector(0, 0, 0);
// for (pos.x = 0; pos.x < width; pos.x++) {
// for (pos.z = 0; pos.z < width; pos.z++) {
// for (pos.y = 0; pos.y < width; pos.y++) {
// task.run(pos, getBlock((int) pos.x, (int) pos.y, (int) pos.z));
// }
// }
// }
// }
@Override
public abstract BaseBlock getBlock(int x, int y, int z);

View File

@ -2,7 +2,11 @@ package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.object.RunnableVal2;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -69,6 +73,63 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
return block;
}
@Override
public void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air) {
BlockVector pos = new BlockVector(0, 0, 0);
int y1max = ((height + 15) >> 4);
for (int x = 0; x < width; x++) {
int i1 = x;
for (int z = 0; z < length; z++) {
int i2 = i1 + z * width;
for (int y = 0; y < y1max; y++) {
int y1 = y << 4;
int i = i2 + y * area;
byte[] idArray = ids[i];
if (idArray == null) {
if (!air) {
continue;
}
for (int y2 = 0; y2 < 16; y2++) {
pos.x = x;
pos.z = z;
pos.y = y1 + y2;
task.run(pos, EditSession.nullBlock);
}
continue;
}
for (int y2 = 0; y2 < idArray.length; y2++) {
int id = idArray[y2] & 0xFF;
if (id == 0 && !air) {
continue;
}
pos.x = x;
pos.z = z;
pos.y = y1 + y2;
BaseBlock block;
if (!FaweCache.hasData(id) || datas == null) {
block = FaweCache.CACHE_BLOCK[id << 4];
} else {
byte[] dataArray = datas[i];
if (dataArray == null) {
block = FaweCache.CACHE_BLOCK[id << 4];
} else {
block = FaweCache.CACHE_BLOCK[(id << 4) + dataArray[y2]];
}
}
if (FaweCache.hasNBT(id)) {
CompoundTag nbt = nbtMap.get(new IntegerTrio((int) pos.x, (int) pos.y, (int) pos.z));
if (nbt != null) {
block = new BaseBlock(block.getId(), block.getData());
block.setNbtData(nbt);
}
}
task.run(pos, block);
}
}
}
}
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) {
final int id = block.getId();

View File

@ -14,6 +14,7 @@ public abstract class FaweQueue {
public final String world;
public LinkedBlockingDeque<EditSession> sessions;
public long modified = System.currentTimeMillis();
public FaweQueue(String world) {
this.world = world;
@ -47,6 +48,10 @@ public abstract class FaweQueue {
public abstract boolean regenerateChunk(int x, int z);
public void startSet(boolean parallel) {}
public void endSet(boolean parallel) {}
/**
* Gets the FaweChunk and sets the requested blocks
* @return

View File

@ -4,8 +4,6 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.RunnableVal2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
@ -55,6 +53,7 @@ public class SetQueue {
@Override
public void run() {
if (inactiveQueues.size() == 0 && activeQueues.size() == 0) {
lastSuccess = System.currentTimeMillis();
tasks();
return;
}
@ -81,21 +80,11 @@ public class SetQueue {
return;
}
if (Settings.UNSAFE_PARALLEL_THREADS <= 1) {
SET_TASK.value2.startSet(false);
SET_TASK.run();
SET_TASK.value2.endSet(false);
} else {
boolean timingsEnabled = true;
try {
Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");
fieldEnabled.setAccessible(true);
timingsEnabled = (boolean) fieldEnabled.get(null);
if (timingsEnabled) {
fieldEnabled.set(null, false);
Method methodCheck = Class.forName("co.aikar.timings.TimingsManager").getDeclaredMethod("recheckEnabled");
methodCheck.setAccessible(true);
methodCheck.invoke(null);
}
} catch (Throwable ignore) {ignore.printStackTrace();}
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, false); } catch (Throwable ignore) {}
SET_TASK.value2.startSet(true);
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < Settings.UNSAFE_PARALLEL_THREADS; i++) {
threads.add(new Thread(SET_TASK));
@ -110,9 +99,7 @@ public class SetQueue {
e.printStackTrace();
}
}
try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled);
} catch (Throwable ignore) {ignore.printStackTrace();}
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {}
SET_TASK.value2.endSet(true);
}
}
}, 1);
@ -120,7 +107,14 @@ public class SetQueue {
public void enqueue(FaweQueue queue) {
inactiveQueues.remove(queue);
activeQueues.add(queue);
if (queue.size() > 0 && !activeQueues.contains(queue)) {
activeQueues.add(queue);
}
}
public void dequeue(FaweQueue queue) {
inactiveQueues.remove(queue);
activeQueues.remove(queue);
}
public List<FaweQueue> getAllQueues() {
@ -150,6 +144,7 @@ public class SetQueue {
while (activeQueues.size() > 0) {
FaweQueue queue = activeQueues.peek();
if (queue != null && queue.size() > 0) {
queue.modified = System.currentTimeMillis();
return queue;
} else {
activeQueues.poll();
@ -157,25 +152,21 @@ public class SetQueue {
}
if (inactiveQueues.size() > 0) {
ArrayList<FaweQueue> tmp = new ArrayList<>(inactiveQueues);
if (Settings.QUEUE_MAX_WAIT != -1) {
if (Settings.QUEUE_MAX_WAIT >= 0) {
long now = System.currentTimeMillis();
if (lastSuccess == 0) {
lastSuccess = now;
}
long diff = now - lastSuccess;
if (diff > Settings.QUEUE_MAX_WAIT) {
for (FaweQueue queue : tmp) {
if (queue != null && queue.size() > 0) {
return queue;
} else {
activeQueues.poll();
if (lastSuccess != 0) {
long diff = now - lastSuccess;
if (diff > Settings.QUEUE_MAX_WAIT) {
for (FaweQueue queue : tmp) {
if (queue != null && queue.size() > 0) {
queue.modified = now;
return queue;
} else if (now - queue.modified > Settings.QUEUE_DISCARD_AFTER) {
inactiveQueues.remove(queue);
}
}
return null;
}
if (diff > Settings.QUEUE_DISCARD_AFTER) {
// These edits never finished
inactiveQueues.clear();
}
return null;
}
}
if (Settings.QUEUE_SIZE != -1) {
@ -186,9 +177,8 @@ public class SetQueue {
if (total > Settings.QUEUE_SIZE) {
for (FaweQueue queue : tmp) {
if (queue != null && queue.size() > 0) {
queue.modified = System.currentTimeMillis();
return queue;
} else {
activeQueues.poll();
}
}
}

View File

@ -48,16 +48,21 @@ public abstract class TaskManager {
if (async) {
async(r);
} else {
if (Fawe.get().getMainThread() == Thread.currentThread()) {
if (r != null) {
r.run();
}
} else {
task(r);
}
r.run();
}
}
public void sync(final Runnable r, boolean async) {
if (async) {
async(r);
} else if (r != null && Thread.currentThread() == Fawe.get().getMainThread()){
r.run();
} else {
task(r);
}
}
/**
* Run a task later on the main thread
* @param r

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.clipboard.LazyClipboard;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -26,6 +27,7 @@ import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
@ -38,11 +40,13 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
@ -110,6 +114,19 @@ public class ClipboardCommands {
public List<? extends Entity> getEntities() {
return editSession.getEntities(region);
}
@Override
public void forEach(RunnableVal2<Vector, BaseBlock> task, boolean air) {
Iterator<BlockVector> iter = region.iterator();
while (iter.hasNext()) {
BlockVector pos = iter.next();
BaseBlock block = getBlock((int) pos.x, (int) pos.y, (int) pos.z);
if (!air && block == EditSession.nullBlock) {
continue;
}
task.run(pos, block);
}
}
};
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, lazyClipboard);
@ -198,13 +215,63 @@ public class ClipboardCommands {
)
@CommandPermissions("worldedit.clipboard.paste")
@Logging(PLACEMENT)
public void paste(Player player, LocalSession session, EditSession editSession,
public void paste(Player player, LocalSession session, final EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
if (holder.getTransform().isIdentity()) {
place(player, session, editSession, ignoreAirBlocks, atOrigin, selectPasted);
return;
}
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
Operation operation = holder
.createPaste(editSession, editSession.getWorld().getWorldData())
.to(to)
.ignoreAirBlocks(ignoreAirBlocks)
.build();
Operations.completeLegacy(operation);
if (selectPasted) {
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max);
session.setRegionSelector(player.getWorld(), selector);
selector.learnChanges();
selector.explainRegionAdjust(player, session);
}
player.print("The clipboard has been pasted at " + to);
}
@Command(
aliases = { "/place" },
usage = "",
flags = "sao",
desc = "Place the clipboard's contents",
help =
"Places the clipboard's contents.\n" +
"Flags:\n" +
" -a skips air blocks\n" +
" -o pastes at the original position\n" +
" -s selects the region after pasting",
min = 0,
max = 0
)
// Skips all transforms
@CommandPermissions("worldedit.clipboard.place")
@Logging(PLACEMENT)
public void place(Player player, LocalSession session, final EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion().clone();
Vector origin = clipboard.getOrigin();
final Transform transform = holder.getTransform();
// Optimize for CuboidRegion
if (region instanceof CuboidRegion) {
CuboidRegion cuboid = (CuboidRegion) region;
Vector min = cuboid.getMinimumPoint();
@ -213,30 +280,28 @@ public class ClipboardCommands {
cuboid.setPos1(new Vector(0, 0, 0));
}
Vector to = atOrigin ? origin : session.getPlacementPosition(player);
int mx = region.getMinimumPoint().getBlockX();
int my = region.getMinimumPoint().getBlockY();
int mz = region.getMinimumPoint().getBlockZ();
int tx = to.getBlockX() - origin.getBlockX();
int ty = to.getBlockY() - origin.getBlockY();
int tz = to.getBlockZ() - origin.getBlockZ();
Iterator<BlockVector> iter = region.iterator();
final int tx = to.getBlockX() - origin.getBlockX();
final int ty = to.getBlockY() - origin.getBlockY();
final int tz = to.getBlockZ() - origin.getBlockZ();
// Optimize for BlockArrayClipboard
if (clipboard instanceof BlockArrayClipboard) {
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
while (iter.hasNext()) {
BlockVector loc = iter.next();
int x = (int) loc.x;
int y = (int) loc.y;
int z = (int) loc.z;
BaseBlock block = bac.getBlockAbs(x, y, z);
if (block == EditSession.nullBlock && ignoreAirBlocks) {
continue;
bac.IMP.forEach(new RunnableVal2<Vector, BaseBlock>() {
@Override
public void run(Vector pos, BaseBlock block) {
pos.x += tx;
pos.y += ty;
pos.z += tz;
try {
editSession.setBlock(pos, block);
} catch (MaxChangedBlocksException e) {
throw new RuntimeException(e);
}
}
loc.x += tx;
loc.y += ty;
loc.z += tz;
editSession.setBlock(loc, block);
}
}, !ignoreAirBlocks);
} else {
// Generic optimization for unknown region type
Iterator<BlockVector> iter = region.iterator();
while (iter.hasNext()) {
BlockVector loc = iter.next();
BaseBlock block = clipboard.getBlock(loc);
@ -246,7 +311,7 @@ public class ClipboardCommands {
loc.x += tx;
loc.y += ty;
loc.z += tz;
editSession.setBlock(loc, block);
editSession.setBlock(transform.apply(loc), block);
}
}
// entities
@ -260,7 +325,7 @@ public class ClipboardCommands {
selector.learnChanges();
selector.explainRegionAdjust(player, session);
}
player.print("The clipboard has been pasted at " + to);
player.print("The clipboard has been placed at " + to);
}
@Command(

View File

@ -98,48 +98,37 @@ public class SchematicCommands {
player.printError("Unknown schematic format: " + formatName);
return;
}
final Closer closer = Closer.create();
try {
final String filePath = f.getCanonicalPath();
final String dirPath = dir.getCanonicalPath();
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
final Closer closer = Closer.create();
try {
final String filePath = f.getCanonicalPath();
final String dirPath = dir.getCanonicalPath();
if (!filePath.substring(0, dirPath.length()).equals(dirPath)) {
player.printError("Clipboard file could not read or it does not exist.");
} else {
final FileInputStream fis = closer.register(new FileInputStream(f));
final BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
final ClipboardReader reader = format.getReader(bis);
if (!filePath.substring(0, dirPath.length()).equals(dirPath)) {
player.printError("Clipboard file could not read or it does not exist.");
} else {
final FileInputStream fis = closer.register(new FileInputStream(f));
final BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
final ClipboardReader reader = format.getReader(bis);
final WorldData worldData = player.getWorld().getWorldData();
final Clipboard clipboard;
if (reader instanceof SchematicReader) {
clipboard = ((SchematicReader) reader).read(player.getWorld().getWorldData(), player.getUniqueId());
} else {
clipboard = reader.read(player.getWorld().getWorldData());
}
session.setClipboard(new ClipboardHolder(clipboard, worldData));
log.info(player.getName() + " loaded " + filePath);
player.print(filename + " loaded. Paste it with //paste");
}
} catch (final IOException e) {
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
log.log(Level.WARNING, "Failed to load a saved clipboard", e);
} finally {
try {
closer.close();
} catch (final IOException ignored) {}
}
}
});
final WorldData worldData = player.getWorld().getWorldData();
final Clipboard clipboard;
if (reader instanceof SchematicReader) {
clipboard = ((SchematicReader) reader).read(player.getWorld().getWorldData(), player.getUniqueId());
} else {
clipboard = reader.read(player.getWorld().getWorldData());
}
session.setClipboard(new ClipboardHolder(clipboard, worldData));
log.info(player.getName() + " loaded " + filePath);
player.print(filename + " loaded. Paste it with //paste");
}
});
} catch (final IOException e) {
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
log.log(Level.WARNING, "Failed to load a saved clipboard", e);
} finally {
try {
closer.close();
} catch (final IOException ignored) {}
}
}
@Command(aliases = { "save" }, usage = "[<format>] <filename>", desc = "Save a schematic into your clipboard")

View File

@ -19,6 +19,14 @@
package com.sk89q.worldedit.command.composition;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.WEManager;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
@ -28,16 +36,25 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.argument.CommandArgs;
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.List;
@ -82,60 +99,60 @@ public class SelectionCommand extends SimpleCommand<Operation> {
Operation operation = operationFactory.createFromContext(editContext);
// Shortcut
// if (selection instanceof CuboidRegion && editSession.hasFastMode() && operation instanceof RegionVisitor) {
// CuboidRegion cuboid = (CuboidRegion) selection;
// RegionFunction function = ((RegionVisitor) operation).function;
// RegionWrapper current = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint());
// FawePlayer fp = FawePlayer.wrap(player);
// HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
//
// if (function instanceof BlockReplace && mask.size() == 1 && mask.iterator().next().contains(current)) {
// try {
// BlockReplace replace = ((BlockReplace) function);
// Field field = replace.getClass().getDeclaredField("pattern");
// field.setAccessible(true);
// Pattern pattern = (Pattern) field.get(replace);
// if (pattern instanceof BlockPattern) {
// BaseBlock block = ((BlockPattern) pattern).getBlock();
// final FaweQueue queue = editSession.getQueue();
// final int minY = cuboid.getMinimumY();
// final int maxY = cuboid.getMaximumY();
//
// final int id = block.getId();
// final byte data = (byte) block.getData();
// final FaweChunk<?> fc = queue.getChunk(0, 0);
// fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data);
//
// int bcx = (current.minX) >> 4;
// int bcz = (current.minZ) >> 4;
//
// int tcx = (current.maxX) >> 4;
// int tcz = (current.maxZ) >> 4;
// // [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge]
// MainUtil.chunkTaskSync(current, new RunnableVal<int[]>() {
// @Override
// public void run(int[] value) {
// FaweChunk newChunk;
// if (value[6] == 0) {
// newChunk = fc.copy(true);
// newChunk.setLoc(queue, value[0], value[1]);
// } else {
// newChunk = queue.getChunk(value[0], value[1]);
// newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, id, data);
// }
// newChunk.addToQueue();
// }
// });
// queue.enqueue();
// editSession.setChangeSet(new NullChangeSet());
// actor.print("[FAWE] Finished queueing " + cuboid.getArea() + " blocks.");
// return null;
// }
// } catch (Throwable e) {
// e.printStackTrace();
// }
// }
// }
if (selection instanceof CuboidRegion && editSession.hasFastMode() && operation instanceof RegionVisitor) {
CuboidRegion cuboid = (CuboidRegion) selection;
RegionFunction function = ((RegionVisitor) operation).function;
RegionWrapper current = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint());
FawePlayer fp = FawePlayer.wrap(player);
HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
if (function instanceof BlockReplace && mask.size() == 1 && mask.iterator().next().contains(current)) {
try {
BlockReplace replace = ((BlockReplace) function);
Field field = replace.getClass().getDeclaredField("pattern");
field.setAccessible(true);
Pattern pattern = (Pattern) field.get(replace);
if (pattern instanceof BlockPattern) {
BaseBlock block = ((BlockPattern) pattern).getBlock();
final FaweQueue queue = editSession.getQueue();
final int minY = cuboid.getMinimumY();
final int maxY = cuboid.getMaximumY();
final int id = block.getId();
final byte data = (byte) block.getData();
final FaweChunk<?> fc = queue.getChunk(0, 0);
fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data);
int bcx = (current.minX) >> 4;
int bcz = (current.minZ) >> 4;
int tcx = (current.maxX) >> 4;
int tcz = (current.maxZ) >> 4;
// [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge]
MainUtil.chunkTaskSync(current, new RunnableVal<int[]>() {
@Override
public void run(int[] value) {
FaweChunk newChunk;
if (value[6] == 0) {
newChunk = fc.copy(true);
newChunk.setLoc(queue, value[0], value[1]);
} else {
newChunk = queue.getChunk(value[0], value[1]);
newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, id, data);
}
newChunk.addToQueue();
}
});
queue.enqueue();
editSession.setChangeSet(new NullChangeSet());
actor.print("[FAWE] Finished queueing " + cuboid.getArea() + " blocks.");
return null;
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
Operations.completeBlindly(operation);
List<String> messages = Lists.newArrayList();

View File

@ -130,7 +130,7 @@ public class FaweForge implements IFawe {
@Override
public void startMetrics() {
try {
ForgeMetrics metrics = new ForgeMetrics("FastAsyncWorldEdit", "3.4.1");
ForgeMetrics metrics = new ForgeMetrics("FastAsyncWorldEdit", "3.4.2");
metrics.start();
debug("[FAWE] &6Metrics enabled.");
} catch (Throwable e) {

View File

@ -19,7 +19,7 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import org.apache.logging.log4j.Logger;
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.4.1", acceptableRemoteVersions = "*")
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.4.2", acceptableRemoteVersions = "*")
public class ForgeMain {
private static FaweForge IMP;
private Logger logger;

View File

@ -335,7 +335,7 @@ public class ForgeQueue_All extends FaweQueue {
@Override
public void run() {
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
TaskManager.IMP.task(new Runnable() {
TaskManager.IMP.sync(new Runnable() {
@Override
public void run() {
if (!result) {

View File

@ -2,7 +2,7 @@
"modid": "com.boydti.fawe",
"name": "FastAsyncWorldEdit",
"description": "Extreme WorldEdit optimizations, no lag, low memory usage, area + tile + entity limits, block logging + rollback",
"version": "3.4.1",
"version": "3.4.2",
"mcVersion": "1.7.10",
"dependencies": [
"WorldEdit"

View File

@ -131,7 +131,7 @@ public class FaweForge implements IFawe {
@Override
public void startMetrics() {
try {
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.4.1");
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.4.2");
metrics.start();
debug("[FAWE] &6Metrics enabled.");
} catch (Throwable e) {

View File

@ -19,7 +19,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import org.apache.logging.log4j.Logger;
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.4.1", acceptableRemoteVersions = "*")
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.4.2", acceptableRemoteVersions = "*")
public class ForgeMain {
private static com.boydti.fawe.forge.FaweForge IMP;
private Logger logger;

View File

@ -290,7 +290,7 @@ public class ForgeQueue_All extends FaweQueue {
@Override
public void run() {
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
TaskManager.IMP.task(new Runnable() {
TaskManager.IMP.sync(new Runnable() {
@Override
public void run() {
if (!result) {

View File

@ -8,7 +8,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<artifactId>FastAsyncWorldEdit</artifactId>
<version>3.4.1</version>
<version>3.4.2</version>
<name>FastAsyncWorldEdit</name>
<packaging>jar</packaging>
<build>

View File

@ -18,7 +18,7 @@ import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.profile.GameProfileManager;
import org.spongepowered.api.world.World;
@Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.4.1", authors = "Empire92")
@Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.4.2", authors = "Empire92")
public class SpongeMain {
public PluginContainer plugin;

View File

@ -119,7 +119,7 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
@Override
public void run() {
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
TaskManager.IMP.task(new Runnable() {
TaskManager.IMP.sync(new Runnable() {
@Override
public void run() {
if (!result) {