fix a few async issues (nbt setting/cut/plotsquared hook)
fixes #1
allow some debug options to be configurable (chunk wait / buffer size)
add region restriction option
This commit is contained in:
Jesse Boyd 2016-04-07 06:19:17 +10:00
parent fabdf0b08a
commit 42654bd784
12 changed files with 235 additions and 114 deletions

View File

@ -36,12 +36,16 @@ public class BukkitPlayer extends FawePlayer<Player> {
* Permissions are used to managing WorldEdit region restrictions
* - The `/wea` command will give/remove the required bypass permission
*/
if (Fawe.<FaweBukkit> imp().getVault() == null) {
if (Fawe.<FaweBukkit> imp().getVault() == null || Fawe.<FaweBukkit> imp().getVault().permission == null) {
this.parent.addAttachment(Fawe.<FaweBukkit> imp()).setPermission("fawe.bypass", flag);
} else if (flag) {
Fawe.<FaweBukkit> imp().getVault().permission.playerAdd(this.parent, perm);
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerAdd(this.parent, perm)) {
this.parent.addAttachment(Fawe.<FaweBukkit> imp()).setPermission("fawe.bypass", flag);
}
} else {
Fawe.<FaweBukkit> imp().getVault().permission.playerRemove(this.parent, perm);
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerRemove(this.parent, perm)) {
this.parent.addAttachment(Fawe.<FaweBukkit> imp()).setPermission("fawe.bypass", flag);
}
}
}

View File

@ -24,7 +24,6 @@ import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@ -59,13 +58,6 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
try {
Bukkit.getPluginManager().registerEvents(this, this);
Fawe.set(this);
try {
final Class<?> clazz = Class.forName("org.spigotmc.AsyncCatcher");
final Field field = clazz.getDeclaredField("enabled");
field.set(null, false);
} catch (final Throwable e) {
e.printStackTrace();
}
} catch (final Throwable e) {
e.printStackTrace();
this.getServer().shutdown();

View File

@ -74,7 +74,7 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
private RefMethod methodGetWorld;
private RefField tileEntityListTick;
public BukkitQueue_1_8(String world) {
public BukkitQueue_1_8(final String world) {
super(world);
try {
this.methodGetHandlePlayer = this.classCraftPlayer.getMethod("getHandle");
@ -95,6 +95,69 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
} catch (final NoSuchMethodException e) {
e.printStackTrace();
}
TaskManager.IMP.repeat(new Runnable() {
@Override
public void run() {
synchronized (loadQueue) {
while (loadQueue.size() > 0) {
IntegerPair loc = loadQueue.poll();
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getServer().getWorld(world);
}
if (!bukkitWorld.isChunkLoaded(loc.x, loc.z)) {
bukkitWorld.loadChunk(loc.x, loc.z);
}
}
loadQueue.notifyAll();
}
}
}, 1);
}
private ArrayDeque<IntegerPair> loadQueue = new ArrayDeque<>();
@Override
public int getCombinedId4Data(int x, int y, int z) {
if (y < 0 || y > 255) {
return 0;
}
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lcx || cz != lcz) {
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getServer().getWorld(world);
}
lcx = cx;
lcz = cz;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
if (Settings.CHUNK_WAIT > 0) {
synchronized (loadQueue) {
loadQueue.add(new IntegerPair(cx, cz));
try {
loadQueue.wait(Settings.CHUNK_WAIT);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
}
} else {
return 0;
}
}
lc = methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call();
} else if (cy == lcy) {
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
}
Object storage = ((Object[]) fieldSections.of(lc).get())[cy];
if (storage == null) {
ls = null;
return 0;
}
ls = getIdArray(storage);
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
}
@Override
@ -255,36 +318,6 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
private char[] ls;
private World bukkitWorld;
@Override
public int getCombinedId4Data(int x, int y, int z) {
if (y < 0 || y > 255) {
return 0;
}
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lcx || cz != lcz) {
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getServer().getWorld(world);
}
lcx = cx;
lcz = cz;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
}
lc = methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call();
} else if (cy == lcy) {
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
}
Object storage = ((Object[]) fieldSections.of(lc).get())[cy];
if (storage == null) {
ls = null;
return 0;
}
ls = getIdArray(storage);
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
}
@Override
public boolean setComponents(final FaweChunk<Chunk> fc) {
try {

View File

@ -70,7 +70,7 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
private final RefMethod methodGetWorld;
private final RefField tileEntityListTick;
public BukkitQueue_1_9(String world) throws NoSuchMethodException, RuntimeException {
public BukkitQueue_1_9(final String world) throws NoSuchMethodException, RuntimeException {
super(world);
this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle");
this.methodInitLighting = this.classChunk.getMethod("initLighting");
@ -87,6 +87,71 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
this.tileEntityListTick = this.classWorld.getField("tileEntityListTick");
this.methodGetWorld = this.classChunk.getMethod("getWorld");
this.methodGetCombinedId = classBlock.getMethod("getCombinedId", classIBlockData.getRealClass());
TaskManager.IMP.repeat(new Runnable() {
@Override
public void run() {
synchronized (loadQueue) {
if (loadQueue.size() > 0) {
Fawe.debug("Loading " + loadQueue.size() + " chunks.");
}
while (loadQueue.size() > 0) {
IntegerPair loc = loadQueue.poll();
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getServer().getWorld(world);
}
if (!bukkitWorld.isChunkLoaded(loc.x, loc.z)) {
bukkitWorld.loadChunk(loc.x, loc.z);
}
}
loadQueue.notifyAll();
}
}
}, 1);
}
private ArrayDeque<IntegerPair> loadQueue = new ArrayDeque<>();
@Override
public int getCombinedId4Data(int x, int y, int z) {
if (y < 0 || y > 255) {
return 0;
}
try {
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lcx || cz != lcz) {
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getServer().getWorld(world);
}
lcx = cx;
lcz = cz;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
if (Settings.CHUNK_WAIT > 0) {
synchronized (loadQueue) {
loadQueue.add(new IntegerPair(cx, cz));
try {
loadQueue.wait(Settings.CHUNK_WAIT);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
}
} else {
return 0;
}
}
lc = methodGetType.of(methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call());
}
int combined = (int) methodGetCombinedId.call(lc.call(x & 15, y, z & 15));
return ((combined & 4095) << 4) + (combined >> 12);
}
catch (Throwable e) {
e.printStackTrace();
}
return 0;
}
@Override
@ -230,35 +295,6 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
private RefExecutor lc;
private World bukkitWorld;
@Override
public int getCombinedId4Data(int x, int y, int z) {
if (y < 0 || y > 255) {
return 0;
}
try {
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lcx || cz != lcz) {
if (bukkitWorld == null) {
bukkitWorld = Bukkit.getServer().getWorld(world);
}
lcx = cx;
lcz = cz;
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
return 0;
}
lc = methodGetType.of(methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call());
}
int combined = (int) methodGetCombinedId.call(lc.call(x & 15, y, z & 15));
return ((combined & 4095) << 4) + (combined >> 12);
}
catch (Throwable e) {
e.printStackTrace();
}
return 0;
}
@Override
public boolean setComponents(final FaweChunk<Chunk> pc) {
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;

View File

@ -24,6 +24,8 @@ public class Settings {
public static int COMPRESSION_LEVEL = 0;
public static int BUFFER_SIZE = 531441;
public static boolean METRICS = true;
public static int CHUNK_WAIT = 0;
public static boolean REGION_RESTRICTIONS = true;
public static HashMap<String, FaweLimit> limits;
@ -66,6 +68,9 @@ public class Settings {
options.put("fix-all-lighting", FIX_ALL_LIGHTING);
options.put("history.use-disk", STORE_HISTORY_ON_DISK);
options.put("history.compress", false);
options.put("history.chunk-wait-ms", CHUNK_WAIT);
options.put("history.buffer-size", BUFFER_SIZE);
options.put("region-restrictions", REGION_RESTRICTIONS);
options.put("metrics", METRICS);
// Default limit
@ -91,9 +96,11 @@ public class Settings {
REQUIRE_SELECTION = config.getBoolean("require-selection-in-mask");
WE_BLACKLIST = config.getStringList("command-blacklist");
ENABLE_HARD_LIMIT = config.getBoolean("crash-mitigation");
REGION_RESTRICTIONS = config.getBoolean("region-restrictions");
METRICS = config.getBoolean("metrics");
COMPRESSION_LEVEL = config.getInt("history.compression-level", config.getBoolean("history.compress") ? 1 : 0);
BUFFER_SIZE = config.getInt("history.buffer-size", 59049);
BUFFER_SIZE = config.getInt("history.buffer-size", BUFFER_SIZE);
CHUNK_WAIT = config.getInt("history.chunk-wait-ms");
if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) {
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
}

View File

@ -69,7 +69,11 @@ public class HistoryExtent extends AbstractDelegateExtent {
this.changeSet.add(x, y, z, combined, (block.getId() << 4) + block.getData());
}
} else {
this.changeSet.add(location, getBlock(location), block);
try {
this.changeSet.add(location, getBlock(location), block);
} catch (Throwable e) {
this.changeSet.add(x, y, z, combined, block);
}
}
return true;
}

View File

@ -28,7 +28,10 @@ public class PlotSquaredFeature extends FaweMaskManager {
int min = Integer.MAX_VALUE;
for (final Plot p : pp.getPlots()) {
if (p.getArea().worldname.equals(world)) {
final double d = p.getHome().getEuclideanDistanceSquared(loc);
Location bot = p.getBottomAbs();
Location top = p.getTopAbs();
Location center = new Location(bot.getWorld(), (bot.getX() + top.getX())/2, 0, (bot.getZ() + top.getZ()) / 2);
final double d = center.getEuclideanDistanceSquared(loc);
if (d < min) {
min = (int) d;
plot = p;

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.util;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.extent.NullExtent;
@ -39,7 +40,7 @@ public class WEManager {
public HashSet<RegionWrapper> getMask(final FawePlayer<?> player) {
final HashSet<RegionWrapper> regions = new HashSet<>();
if (player.hasPermission("fawe.bypass")) {
if (player.hasPermission("fawe.bypass") || !Settings.REGION_RESTRICTIONS) {
regions.add(new RegionWrapper(Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE));
return regions;
}

View File

@ -549,7 +549,11 @@ public class EditSession implements Extent {
if (!FaweCache.hasNBT(combinedId4Data >> 4)) {
return FaweCache.CACHE_BLOCK[combinedId4Data];
}
return this.world.getLazyBlock(position);
try {
return this.world.getLazyBlock(position);
} catch (Throwable e) {
return FaweCache.CACHE_BLOCK[combinedId4Data];
}
}
@Override

View File

@ -237,7 +237,7 @@ public final class CommandManager {
locals.put(Actor.class, actor);
locals.put("arguments", event.getArguments());
long start = System.currentTimeMillis();
final long start = System.currentTimeMillis();
FawePlayer fp;
if (actor.isPlayer()) {
fp = Fawe.imp().wrap(actor.getName());
@ -292,6 +292,7 @@ public final class CommandManager {
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
final long time = System.currentTimeMillis() - start;
actor.print(BBC.PREFIX.s() + " Action completed in " + (time / 1000d) + " seconds");
}
});

View File

@ -19,14 +19,13 @@
package com.sk89q.worldedit.function.visitor;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.regions.Region;
import java.util.Iterator;
import java.util.List;
/**
@ -34,15 +33,13 @@ import java.util.List;
*/
public class RegionVisitor implements Operation {
private final Region region;
private final RegionFunction function;
private int affected = 0;
private final Iterator<BlockVector> iterator;
public RegionVisitor(final Region region, final RegionFunction function) {
public RegionVisitor(Region region, RegionFunction function) {
this.region = region;
this.function = function;
this.iterator = region.iterator();
}
/**
@ -56,11 +53,12 @@ public class RegionVisitor implements Operation {
@Override
public Operation resume(final RunContext run) throws WorldEditException {
while (this.iterator.hasNext()) {
if (this.function.apply(this.iterator.next())) {
for (Vector pt : region) {
if (function.apply(pt)) {
affected++;
}
}
return null;
}

View File

@ -5,9 +5,11 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.forge.SpongeUtil;
import com.boydti.fawe.forge.v0.SpongeQueue_0;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.util.TaskManager;
import com.flowpowered.math.vector.Vector3i;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@ -34,6 +36,69 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
public SpongeQueue_1_8(String world) {
super(world);
TaskManager.IMP.repeat(() -> {
synchronized (loadQueue) {
while (loadQueue.size() > 0) {
IntegerPair loc = loadQueue.poll();
if (spongeWorld == null) {
spongeWorld = Sponge.getServer().getWorld(world).get();
}
Chunk chunk = spongeWorld.getChunk(loc.x, 0, loc.z).orElse(null);
if (chunk == null || !chunk.isLoaded()) {
spongeWorld.loadChunk(loc.x, 0, loc.z, true);
}
}
loadQueue.notifyAll();
}
}, 1);
}
private ArrayDeque<IntegerPair> loadQueue = new ArrayDeque<>();
@Override
public int getCombinedId4Data(int x, int y, int z) {
if (y < 0 || y > 255) {
return 0;
}
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lcx || cz != lcz) {
if (spongeWorld == null) {
spongeWorld = Sponge.getServer().getWorld(world).get();
}
lcx = cx;
lcz = cz;
Chunk chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null);
if (chunk == null || !chunk.isLoaded()) {
if (Settings.CHUNK_WAIT > 0) {
synchronized (loadQueue) {
loadQueue.add(new IntegerPair(cx, cz));
try {
loadQueue.wait(Settings.CHUNK_WAIT);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null);
if (chunk == null || !chunk.isLoaded()) {
return 0;
}
} else {
return 0;
}
}
lc = (net.minecraft.world.chunk.Chunk) chunk;
} else if (cy == lcy) {
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
}
ExtendedBlockStorage storage = lc.getBlockStorageArray()[cy];
if (storage == null) {
ls = null;
return 0;
}
ls = storage.getData();
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
}
@Override
@ -86,33 +151,6 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
private net.minecraft.world.chunk.Chunk lc;
private char[] ls;
@Override
public int getCombinedId4Data(int x, int y, int z) {
if (y < 0 || y > 255) {
return 0;
}
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lcx || cz != lcz) {
if (spongeWorld == null) {
spongeWorld = Sponge.getServer().getWorld(world).get();
}
lcx = cx;
lcz = cz;
lc = (net.minecraft.world.chunk.Chunk) spongeWorld.getChunk(cx, 0, cz).get();
} else if (cy == lcy) {
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
}
ExtendedBlockStorage storage = lc.getBlockStorageArray()[cy];
if (storage == null) {
ls = null;
return 0;
}
ls = storage.getData();
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
}
@Override
public boolean setComponents(FaweChunk<Chunk> fc) {
SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc;