This commit is contained in:
Jesse Boyd 2016-04-25 02:20:26 +10:00
parent 053d7a6482
commit 0da4f6f63a
34 changed files with 558 additions and 339 deletions

View File

@ -27,6 +27,9 @@ commands:
frb:
description: (FAWE) Rollback an edit
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
fcancel:
description: (FAWE) Cancel your edit
aliases: [fawecancel,/fcancel,/cancel,/fawecancel]
permissions:
fawe.bypass:
default: false

View File

@ -206,7 +206,6 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
} catch (Throwable ignore) {}
if (hasNMS) {
try {
ReflectionUtils.init();
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
fieldDirtyCount.setAccessible(true);
int mod = fieldDirtyCount.getModifiers();

View File

@ -165,6 +165,7 @@ public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
@Override
public void clear() {
this.blocks.clear();
this.chunks.clear();
}
@Override

View File

@ -256,12 +256,6 @@ public class BukkitQueue_All extends BukkitQueue_0 {
} else {
return 0;
}
long diff = System.currentTimeMillis() - start;
if (average == 0) {
average = diff;
} else {
average = ((average * 15) + diff) / 16;
}
}
lastChunk = getCachedChunk(cx, cz);
lastSection = getCachedSection(lastChunk, cy);

View File

@ -204,7 +204,6 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}

View File

@ -443,7 +443,8 @@ public class BukkitQueue_1_8 extends BukkitQueue_All {
* - Unloads non visible chunks<br>
*/
@Override
public void clear() {
public void saveMemory() {
super.saveMemory();
// Clear the queue
super.clear();
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();

View File

@ -204,7 +204,6 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}

View File

@ -413,7 +413,8 @@ public class BukkitQueue_1_9 extends BukkitQueue_All {
* - Unloads non visible chunks<br>
*/
@Override
public void clear() {
public void saveMemory() {
super.saveMemory();
// Clear the queue
super.clear();
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();

View File

@ -444,7 +444,8 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
* - Unloads non visible chunks<br>
*/
@Override
public void clear() {
public void saveMemory() {
super.saveMemory();
// Clear the queue
super.clear();
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();

View File

@ -27,6 +27,9 @@ commands:
frb:
description: (FAWE) Rollback an edit
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
fcancel:
description: (FAWE) Cancel your edit
aliases: [fawecancel,/fcancel,/cancel,/fawecancel]
permissions:
fawe.bypass:
default: false

View File

@ -1,5 +1,6 @@
package com.boydti.fawe;
import com.boydti.fawe.command.Cancel;
import com.boydti.fawe.command.FixLighting;
import com.boydti.fawe.command.Reload;
import com.boydti.fawe.command.Rollback;
@ -201,6 +202,7 @@ public class Fawe {
this.IMP.setupCommand("wrg", new WorldEditRegion());
this.IMP.setupCommand("fawe", new Reload());
this.IMP.setupCommand("frb", new Rollback());
this.IMP.setupCommand("fcancel", new Cancel());
}
public void setupConfigs() {

View File

@ -0,0 +1,62 @@
package com.boydti.fawe.command;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.extent.FaweExtent;
import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.WEManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.world.World;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class Cancel extends FaweCommand {
public Cancel() {
super("fawe.cancel", false);
}
@Override
public boolean execute(final FawePlayer player, final String... args) {
if (player == null) {
return false;
}
UUID uuid = player.getUUID();
List<FaweQueue> queues = SetQueue.IMP.getAllQueues();
int cancelled = 0;
for (FaweQueue queue : queues) {
Set<EditSession> sessions = queue.getEditSessions();
for (EditSession session : sessions) {
Actor actor = session.actor;
if (actor == null) {
continue;
}
if (uuid.equals(actor.getUniqueId())) {
// Cancel this
FaweExtent fe = session.getFaweExtent();
if (fe != null) {
cancelled++;
try {
WEManager.IMP.cancelEdit(fe, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
} catch (Throwable ignore) {}
World world = session.getWorld();
NullExtent nullExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
session.bypassHistory = nullExtent;
session.bypassNone = nullExtent;
session.bypassReorderHistory = nullExtent;
session.faweExtent = nullExtent;
queue.clear();
}
}
}
}
BBC.WORLDEDIT_CANCEL_COUNT.send(player,cancelled);
return true;
}
}

View File

@ -39,9 +39,9 @@ public enum BBC {
WORLDEDIT_BYPASSED("&7Currently bypassing WorldEdit restriction.", "Info"),
WORLDEDIT_UNMASKED("&6Your WorldEdit is now unrestricted.", "Info"),
WORLDEDIT_RESTRICTED("&6Your WorldEdit is now restricted.", "Info"),
WORLDEDIT_OOM("&cYour WorldEdit action was cancelled due to low memory.", "Info"),
WORLDEDIT_CANCEL_COUNT("&cCancelled %s0 edits.", "Cancel"),
WORLDEDIT_CANCEL_REASON("&cYour WorldEdit action was cancelled:&7 %s0&c.", "Cancel"),
WORLDEDIT_CANCEL_REASON_MANUAL("Manual cancellation", "Cancel"),
WORLDEDIT_CANCEL_REASON_LOW_MEMORY("Low memory", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_CHANGES("Too many blocks changed", "Cancel"),
WORLDEDIT_CANCEL_REASON_MAX_CHECKS("Too many block checks", "Cancel"),

View File

@ -32,6 +32,7 @@ public class Settings {
public static int QUEUE_MAX_WAIT = 1000;
public static int QUEUE_DISCARD_AFTER = 60000;
public static List<String> ALLOWED_3RDPARTY_EXTENTS;
public static boolean EXTENT_DEBUG = true;
public static boolean FIX_ALL_LIGHTING = true;
public static boolean ASYNC_LIGHTING = true;
@ -93,6 +94,7 @@ public class Settings {
options.put("queue.max-wait-ms", QUEUE_MAX_WAIT);
options.put("queue.discard-after-ms", QUEUE_DISCARD_AFTER);
options.put("extent.allowed-plugins", new ArrayList<String>());
options.put("extent.debug", EXTENT_DEBUG);
options.put("metrics", METRICS);
// Default limit
@ -128,8 +130,9 @@ public class Settings {
QUEUE_SIZE = config.getInt("queue.target-size");
QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms");
QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms");
ALLOWED_3RDPARTY_EXTENTS = config.getStringList("extent.allowed-plugins");
EXTENT_DEBUG = config.getBoolean("extent.debug");
if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) {
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;

View File

@ -5,9 +5,15 @@ import com.boydti.fawe.util.TaskManager;
public abstract class FaweCommand<T> {
public final String perm;
public final boolean safe;
public FaweCommand(final String perm) {
public FaweCommand(String perm) {
this(perm, true);
}
public FaweCommand(final String perm, final boolean safe) {
this.perm = perm;
this.safe = safe;
}
public String getPerm() {
@ -15,7 +21,7 @@ public abstract class FaweCommand<T> {
}
public boolean executeSafe(final FawePlayer<T> player, final String... args) {
if (player == null) {
if (player == null || !safe) {
execute(player, args);
return true;
} else {

View File

@ -0,0 +1,4 @@
package com.boydti.fawe.object.clipboard;
public class DiskOptimizedClipboard {
}

View File

@ -0,0 +1,92 @@
package com.boydti.fawe.object.clipboard;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Location;
import java.util.List;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class FaweClipboard {
public final int length;
public final int height;
public final int width;
public final int area;
public FaweClipboard(int width, int height, int length) {
this.width = width;
this.height = height;
this.length = length;
this.area = width * length;
}
public abstract BaseBlock getBlock(int x, int y, int z);
public abstract boolean setBlock(int x, int y, int z, BaseBlock block);
public abstract Entity createEntity(Extent world, double x, double y, double z, float yaw, float pitch, BaseEntity entity);
public abstract List<? extends Entity> getEntities();
public abstract boolean remove(ClipboardEntity clipboardEntity);
/**
* Stores entity data.
*/
public class ClipboardEntity implements Entity {
private final BaseEntity entity;
private final Extent world;
private final double x,y,z;
private final float yaw,pitch;
public ClipboardEntity(Extent world, double x, double y, double z, float yaw, float pitch, BaseEntity entity) {
checkNotNull(entity);
this.world = world;
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
this.pitch = pitch;
this.entity = new BaseEntity(entity);
}
@Override
public boolean remove() {
return FaweClipboard.this.remove(this);
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return null;
}
/**
* Get the entity state. This is not a copy.
*
* @return the entity
*/
BaseEntity getEntity() {
return entity;
}
@Override
public BaseEntity getState() {
return new BaseEntity(entity);
}
@Override
public Location getLocation() {
return new Location(world, x, y, z, yaw, pitch);
}
@Override
public Extent getExtent() {
return world;
}
}
}

View File

@ -0,0 +1,246 @@
package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.IntegerTrio;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
public class MemoryOptimizedClipboard extends FaweClipboard {
// x,z,y+15>>4 | y&15
private final byte[][] ids;
private byte[][] datas;
private final HashMap<IntegerTrio, CompoundTag> nbtMap;
private final HashSet<ClipboardEntity> entities;
public MemoryOptimizedClipboard(int width, int height, int length) {
super(width, height, length);
ids = new byte[width * length * ((height + 15) >> 4)][];
nbtMap = new HashMap<>();
entities = new HashSet<ClipboardEntity>();
}
@Override
public BaseBlock getBlock(int x, int y, int z) {
int i = x + z * width + (y >> 4) * area;
byte[] idArray = ids[i];
if (idArray == null) {
return FaweCache.CACHE_BLOCK[0];
}
int y2 = y & 0xF;
int id = idArray[y2] & 0xFF;
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(x, y, z));
if (nbt != null) {
block = new BaseBlock(block.getId(), block.getData());
block.setNbtData(nbt);
}
}
return block;
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) {
final int id = block.getId();
switch (id) {
case 0:
return true;
case 54:
case 130:
case 142:
case 27:
case 137:
case 52:
case 154:
case 84:
case 25:
case 144:
case 138:
case 176:
case 177:
case 63:
case 119:
case 68:
case 323:
case 117:
case 116:
case 28:
case 66:
case 157:
case 61:
case 62:
case 140:
case 146:
case 149:
case 150:
case 158:
case 23:
case 123:
case 124:
case 29:
case 33:
case 151:
case 178: {
if (block.hasNbtData()) {
nbtMap.put(new IntegerTrio(x, y, z), block.getNbtData());
}
int i = x + z * width + (y >> 4) * area;
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
idArray = new byte[16];
ids[i] = idArray;
}
idArray[y2] = (byte) id;
if (FaweCache.hasData(id)) {
int data = block.getData();
if (data == 0) {
return true;
}
if (datas == null) {
datas = new byte[area * ((height + 15) >> 4)][];
}
byte[] dataArray = datas[i];
if (dataArray == null) {
dataArray = datas[i] = new byte[16];
}
dataArray[y2] = (byte) data;
}
return true;
}
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 39:
case 40:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 51:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 10:
case 11:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 122:
case 129:
case 133:
case 165:
case 166:
case 169:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192: {
int i = x + z * width + (y >> 4) * area;
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
idArray = new byte[16];
ids[i] = idArray;
}
idArray[y2] = (byte) id;
return true;
}
default: {
int i = x + z * width + (y >> 4) * area;
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
idArray = new byte[16];
ids[i] = idArray;
}
idArray[y2] = (byte) id;
int data = block.getData();
if (data == 0) {
return true;
}
if (datas == null) {
datas = new byte[area * ((height + 15) >> 4)][];
}
byte[] dataArray = datas[i];
if (dataArray == null) {
dataArray = datas[i] = new byte[16];
}
dataArray[y2] = (byte) data;
return true;
}
}
}
@Override
public Entity createEntity(Extent world, double x, double y, double z, float yaw, float pitch, BaseEntity entity) {
FaweClipboard.ClipboardEntity ret = new ClipboardEntity(world, x, y, z, yaw, pitch, entity);
entities.add(ret);
return ret;
}
@Override
public List<? extends Entity> getEntities() {
return new ArrayList<>(entities);
}
@Override
public boolean remove(ClipboardEntity clipboardEntity) {
return entities.remove(clipboardEntity);
}
}

View File

@ -4,6 +4,7 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
public abstract class FaweExtent extends AbstractDelegateExtent {
/**
* Create a new instance.
*

View File

@ -16,41 +16,48 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList;
import java.util.List;
public class NullExtent implements Extent {
public class NullExtent extends FaweExtent {
private final BBC reason;
/**
* Create a new instance.
*
* @param extent the extent
*/
public NullExtent(Extent extent, BBC failReason) {
super(extent);
this.reason = failReason;
}
@Override
public BaseBiome getBiome(final Vector2D arg0) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
throw new FaweException(reason);
}
@Override
public BaseBlock getBlock(final Vector arg0) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
throw new FaweException(reason);
}
@Override
public BaseBlock getLazyBlock(final Vector arg0) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
}
@Override
public Operation commit() {
return null;
throw new FaweException(reason);
}
@Override
public boolean setBiome(final Vector2D arg0, final BaseBiome arg1) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
throw new FaweException(reason);
}
@Override
public boolean setBlock(final Vector arg0, final BaseBlock arg1) throws WorldEditException {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
throw new FaweException(reason);
}
@Override
public Entity createEntity(final Location arg0, final BaseEntity arg1) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
throw new FaweException(reason);
}
@Override
@ -73,4 +80,16 @@ public class NullExtent implements Extent {
return new Vector(0, 0, 0);
}
@Override
public boolean contains(int x, int y, int z) { return false; }
@Override
protected Operation commitBefore() {
return null;
}
@Override
public Extent getExtent() {
return this;
}
}

View File

@ -24,7 +24,7 @@ public class SafeExtentWrapper extends AbstractDelegateExtent {
if (super.setBlock(location, block)) {
if (MemUtil.isMemoryLimited()) {
if (this.player != null) {
BBC.WORLDEDIT_OOM.send(this.player);
player.sendMessage(BBC.WORLDEDIT_CANCEL_REASON.format(BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY.s()));
if (Perm.hasPermission(this.player, "worldedit.fast")) {
BBC.WORLDEDIT_OOM_ADMIN.send(this.player);
}

View File

@ -41,10 +41,8 @@ public class PlotSquaredFeature extends FaweMaskManager {
}
if (plot != null) {
final PlotId id = plot.getId();
boolean hasPerm = false;
if (plot.owner != null) {
hasPerm = plot.isOwner(pp.getUUID()) || plot.getTrusted().contains(pp.getUUID()) || (plot.getMembers().contains(pp.getUUID()) && pp.hasPermission("fawe.plotsquared.member"));
if (hasPerm) {
if (plot.isOwner(pp.getUUID()) || plot.getTrusted().contains(pp.getUUID()) || (plot.getMembers().contains(pp.getUUID()) && pp.hasPermission("fawe.plotsquared.member"))) {
RegionWrapper region = plot.getLargestRegion();
HashSet<RegionWrapper> regions = plot.getRegions();

View File

@ -6,15 +6,33 @@ import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.LinkedBlockingDeque;
public abstract class FaweQueue {
public final String world;
public LinkedBlockingDeque<EditSession> sessions;
public FaweQueue(String world) {
this.world = world;
}
public void addEditSession(EditSession session) {
if (session == null) {
return;
}
if (this.sessions == null) {
sessions = new LinkedBlockingDeque<>();
}
sessions.add(session);
}
public Set<EditSession> getEditSessions() {
return sessions == null ? new HashSet<EditSession>() : new HashSet<>(sessions);
}
public abstract boolean setBlock(final int x, final int y, final int z, final short id, final byte data);
public abstract boolean setBiome(final int x, final int z, final BaseBiome biome);
@ -51,7 +69,7 @@ public abstract class FaweQueue {
/**
* This method is called when the server is < 1% available memory
*/
protected abstract void clear();
public abstract void clear();
public abstract void addTask(int x, int z, Runnable runnable);

View File

@ -21,19 +21,17 @@ public class ReflectionUtils {
/**
* prefix of bukkit classes
*/
private static String preClassB;
private static volatile String preClassB = null;
/**
* prefix of minecraft classes
*/
private static String preClassM = null;
private static volatile String preClassM = null;
/**
* boolean value, TRUE if server uses forge or MCPC+
*/
private static boolean forge = false;
/** check server version and class names */
public static void init() {
preClassM = "net.minecraft.server";
preClassB = "org.bukkit.craftbukkit";
if (Bukkit.getServer() != null) {
if (Bukkit.getVersion().contains("MCPC") || Bukkit.getVersion().contains("Forge")) {
forge = true;
@ -43,7 +41,7 @@ public class ReflectionUtils {
String[] pas = bukkitServerClass.getName().split("\\.");
if (pas.length == 5) {
final String verB = pas[3];
preClassB += "." + verB;
preClassB = "org.bukkit.craftbukkit." + verB;
}
try {
final Method getHandle = bukkitServerClass.getDeclaredMethod("getHandle");
@ -52,7 +50,7 @@ public class ReflectionUtils {
pas = handleServerClass.getName().split("\\.");
if (pas.length == 5) {
final String verM = pas[3];
preClassM += "." + verM;
preClassM = "net.minecraft.server." + verM;
}
} catch (final Exception ignored) {
ignored.printStackTrace();
@ -233,7 +231,7 @@ public class ReflectionUtils {
return getRefClass(Class.forName(className));
} catch (final ClassNotFoundException ignored) {}
}
throw new RuntimeException("no class found");
throw new RuntimeException("no class found: " + classes[0].replace("{cb}", preClassB).replace("{nms}", preClassM).replace("{nm}", "net.minecraft"));
}
/**

View File

@ -40,7 +40,7 @@ public class SetQueue {
final int mem = MemUtil.calculateMemory();
if (mem != Integer.MAX_VALUE) {
if ((mem <= 1) && Settings.ENABLE_HARD_LIMIT) {
for (FaweQueue queue : getQueues()) {
for (FaweQueue queue : getAllQueues()) {
queue.saveMemory();
}
return;
@ -71,10 +71,21 @@ public class SetQueue {
activeQueues.add(queue);
}
public List<FaweQueue> getQueues() {
public List<FaweQueue> getAllQueues() {
ArrayList<FaweQueue> list = new ArrayList<FaweQueue>(activeQueues.size() + inactiveQueues.size());
list.addAll(inactiveQueues);
list.addAll(activeQueues);
return list;
}
public List<FaweQueue> getActiveQueues() {
return new ArrayList<>(activeQueues);
}
public List<FaweQueue> getInactiveQueues() {
return new ArrayList<>(inactiveQueues);
}
public FaweQueue getNewQueue(String world, boolean autoqueue) {
FaweQueue queue = Fawe.imp().getNewQueue(world);
if (autoqueue) {
@ -96,6 +107,9 @@ public class SetQueue {
ArrayList<FaweQueue> tmp = new ArrayList<>(inactiveQueues);
if (Settings.QUEUE_MAX_WAIT != -1) {
long now = System.currentTimeMillis();
if (lastSuccess == 0) {
lastSuccess = now;
}
long diff = now - lastSuccess;
if (diff > Settings.QUEUE_MAX_WAIT) {
for (FaweQueue queue : tmp) {

View File

@ -26,7 +26,7 @@ public class WEManager {
try {
final Field field = AbstractDelegateExtent.class.getDeclaredField("extent");
field.setAccessible(true);
field.set(parent, new NullExtent());
field.set(parent, new NullExtent((Extent) field.get(parent), reason));
} catch (final Exception e) {
e.printStackTrace();
}

View File

@ -160,20 +160,20 @@ public class EditSession implements Extent {
BEFORE_HISTORY, BEFORE_REORDER, BEFORE_CHANGE
}
private World world;
private Actor actor;
private FaweChangeSet changeSet;
private final EditSessionWrapper wrapper;
private FaweExtent faweExtent;
private MaskingExtent maskingExtent;
private final Extent bypassReorderHistory;
private final Extent bypassHistory;
private final Extent bypassNone;
private SurvivalModeExtent lazySurvivalExtent;
private boolean fastmode;
private Mask oldMask;
private FaweLimit limit = FaweLimit.MAX;
private FaweQueue queue;
public World world;
public Actor actor;
public FaweChangeSet changeSet;
public EditSessionWrapper wrapper;
public FaweExtent faweExtent;
public MaskingExtent maskingExtent;
public Extent bypassReorderHistory;
public Extent bypassHistory;
public Extent bypassNone;
public SurvivalModeExtent lazySurvivalExtent;
public boolean fastmode;
public Mask oldMask;
public FaweLimit limit = FaweLimit.MAX;
public FaweQueue queue;
public static BaseBiome nullBiome = new BaseBiome(0);
public static BaseBlock nullBlock = new BaseBlock(0);
@ -220,13 +220,13 @@ public class EditSession implements Extent {
checkNotNull(eventBus);
checkArgument(maxBlocks >= -1, "maxBlocks >= -1 required");
checkNotNull(event);
this.actor = event.getActor();
// Wrap world
this.blockBag = blockBag;
this.maxBlocks = maxBlocks;
// Invalid; return null extent
if (world == null) {
final Extent extent = new NullExtent();
FaweExtent extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.bypassReorderHistory = extent;
this.bypassHistory = extent;
this.bypassNone = extent;
@ -234,8 +234,8 @@ public class EditSession implements Extent {
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
return;
}
this.actor = event.getActor();
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true);
queue.addEditSession(this);
// Set the world of the event to the actual world (workaround for CoreProtect)
try {
Class<? extends EditSessionEvent> eventClass = event.getClass();
@ -266,7 +266,7 @@ public class EditSession implements Extent {
}
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
Extent extent;
final FawePlayer<Object> fp = FawePlayer.wrap(actor);
final FawePlayer fp = FawePlayer.wrap(actor);
final LocalSession session = fp.getSession();
this.fastmode = session.hasFastMode();
if (fp.hasWorldEditBypass()) {
@ -287,7 +287,7 @@ public class EditSession implements Extent {
final HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
if (mask.size() == 0) {
// No allowed area; return null extent
extent = new NullExtent();
extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.bypassReorderHistory = extent;
this.bypassHistory = extent;
this.bypassNone = extent;
@ -310,12 +310,12 @@ public class EditSession implements Extent {
return;
} else {
if (MemUtil.isMemoryLimited()) {
BBC.WORLDEDIT_OOM.send(fp);
fp.sendMessage(BBC.WORLDEDIT_CANCEL_REASON.format(BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY.s()));
if (Perm.hasPermission(fp, "worldedit.fast")) {
BBC.WORLDEDIT_OOM_ADMIN.send(fp);
}
// Memory limit reached; return null extent
extent = new NullExtent();
extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
this.bypassReorderHistory = extent;
this.bypassHistory = extent;
this.bypassNone = extent;
@ -370,11 +370,14 @@ public class EditSession implements Extent {
eventBus.post(event);
final Extent toReturn = event.getExtent();
if (toReturn != extent) {
String className = toReturn.getClass().getName().toLowerCase();
String className = toReturn.getClass().getSimpleName().toLowerCase();
if (className.contains("coreprotect")) {
Fawe.debug("&cUnsafe extent detected: " + toReturn.getClass().getCanonicalName() + " !");
Fawe.debug("&8 - &7Use BlocksHub instead");
Fawe.debug("&8 - &7Or use FAWE rollback");
if (Settings.EXTENT_DEBUG) {
Fawe.debug("&cUnsafe extent detected: " + toReturn.getClass().getCanonicalName() + " !");
Fawe.debug("&8 - &7Use BlocksHub instead");
Fawe.debug("&8 - &7Or use FAWE rollback");
Fawe.debug("&8 - &7Change `extent.debug: false` to hide this message");
}
return extent;
}
for (String allowed : Settings.ALLOWED_3RDPARTY_EXTENTS) {
@ -382,11 +385,13 @@ public class EditSession implements Extent {
return toReturn;
}
}
Fawe.debug("&cPotentially inefficient WorldEdit extent: " + toReturn.getClass().getCanonicalName());
Fawe.debug("&8 - &7For area restrictions, it is recommended to use the FaweAPI");
Fawe.debug("&8 - &7Ignore this if not an area restriction");
if (Settings.EXTENT_DEBUG) {
Fawe.debug("&cPotentially inefficient WorldEdit extent: " + toReturn.getClass().getSimpleName());
Fawe.debug("&8 - &7For area restrictions, it is recommended to use the FaweAPI");
Fawe.debug("&8 - &7To allow this plugin add it to the FAWE `allowed-plugins` list");
}
}
return toReturn;
return extent;
}
/**

View File

@ -19,9 +19,8 @@
package com.sk89q.worldedit.extent.clipboard;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.IntegerTrio;
import com.sk89q.jnbt.CompoundTag;
import com.boydti.fawe.object.clipboard.FaweClipboard;
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
@ -29,14 +28,12 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Nullable;
@ -51,13 +48,11 @@ public class BlockArrayClipboard implements Clipboard {
private final Region region;
// x,z,y+15>>4 | y&15
private final byte[][] ids;
private byte[][] datas;
public FaweClipboard IMP;
private final Vector size;
private final HashMap<IntegerTrio, CompoundTag> nbtMap;
private final List<ClipboardEntity> entities = new ArrayList<ClipboardEntity>();
private int mx;
private int my;
private int mz;
@ -78,14 +73,13 @@ public class BlockArrayClipboard implements Clipboard {
checkNotNull(region);
this.region = region.clone();
this.size = getDimensions();
this.dx = size.getBlockX();
this.dxz = dx * size.getBlockZ();
ids = new byte[dx * size.getBlockZ() * ((size.getBlockY() + 15) >> 4)][];
nbtMap = new HashMap<>();
this.IMP = new MemoryOptimizedClipboard(size.getBlockX(), size.getBlockY(), size.getBlockZ());
this.origin = region.getMinimumPoint();
this.mx = origin.getBlockX();
this.my = origin.getBlockY();
this.mz = origin.getBlockZ();
}
@Override
@ -121,7 +115,7 @@ public class BlockArrayClipboard implements Clipboard {
@Override
public List<? extends Entity> getEntities(Region region) {
List<Entity> filtered = new ArrayList<Entity>();
for (Entity entity : entities) {
for (Entity entity : getEntities()) {
if (region.contains(entity.getLocation().toVector())) {
filtered.add(entity);
}
@ -131,15 +125,13 @@ public class BlockArrayClipboard implements Clipboard {
@Override
public List<? extends Entity> getEntities() {
return Collections.unmodifiableList(entities);
return IMP.getEntities();
}
@Nullable
@Override
public Entity createEntity(Location location, BaseEntity entity) {
ClipboardEntity ret = new ClipboardEntity(location, entity);
entities.add(ret);
return ret;
return IMP.createEntity(location.getExtent(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch(), entity);
}
@Override
@ -148,34 +140,8 @@ public class BlockArrayClipboard implements Clipboard {
int x = position.getBlockX() - mx;
int y = position.getBlockY() - my;
int z = position.getBlockZ() - mz;
int i = x + z * dx + (y >> 4) * dxz;
byte[] idArray = ids[i];
if (idArray == null) {
return FaweCache.CACHE_BLOCK[0];
}
int y2 = y & 0xF;
int id = idArray[y2] & 0xFF;
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(x, y, z));
if (nbt != null) {
block = new BaseBlock(block.getId(), block.getData());
block.setNbtData(nbt);
}
}
return block;
return IMP.getBlock(x, y, z);
}
return EditSession.nullBlock;
}
@ -199,172 +165,7 @@ public class BlockArrayClipboard implements Clipboard {
x -= mx;
y -= my;
z -= mz;
final int id = block.getId();
switch (id) {
case 0:
return true;
case 54:
case 130:
case 142:
case 27:
case 137:
case 52:
case 154:
case 84:
case 25:
case 144:
case 138:
case 176:
case 177:
case 63:
case 119:
case 68:
case 323:
case 117:
case 116:
case 28:
case 66:
case 157:
case 61:
case 62:
case 140:
case 146:
case 149:
case 150:
case 158:
case 23:
case 123:
case 124:
case 29:
case 33:
case 151:
case 178: {
if (block.hasNbtData()) {
nbtMap.put(new IntegerTrio(x, y, z), block.getNbtData());
}
int i = x + z * dx + (y >> 4) * dxz;
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
idArray = new byte[16];
ids[i] = idArray;
}
idArray[y2] = (byte) id;
if (FaweCache.hasData(id)) {
int data = block.getData();
if (data == 0) {
return true;
}
if (datas == null) {
datas = new byte[dx * size.getBlockZ() * ((size.getBlockY() + 15) >> 4)][];
}
byte[] dataArray = datas[i];
if (dataArray == null) {
dataArray = datas[i] = new byte[16];
}
dataArray[y2] = (byte) data;
}
return true;
}
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 39:
case 40:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 51:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 10:
case 11:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 122:
case 129:
case 133:
case 165:
case 166:
case 169:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192: {
int i = x + z * dx + (y >> 4) * dxz;
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
idArray = new byte[16];
ids[i] = idArray;
}
idArray[y2] = (byte) id;
return true;
}
default: {
int i = x + z * dx + (y >> 4) * dxz;
int y2 = y & 0xF;
byte[] idArray = ids[i];
if (idArray == null) {
idArray = new byte[16];
ids[i] = idArray;
}
idArray[y2] = (byte) id;
int data = block.getData();
if (data == 0) {
return true;
}
if (datas == null) {
datas = new byte[dx * size.getBlockZ() * ((size.getBlockY() + 15) >> 4)][];
}
byte[] dataArray = datas[i];
if (dataArray == null) {
dataArray = datas[i] = new byte[16];
}
dataArray[y2] = (byte) data;
return true;
}
}
return IMP.setBlock(x, y, z, block);
}
@Override
@ -383,57 +184,6 @@ public class BlockArrayClipboard implements Clipboard {
return null;
}
/**
* Stores entity data.
*/
private class ClipboardEntity implements Entity {
private final Location location;
private final BaseEntity entity;
ClipboardEntity(Location location, BaseEntity entity) {
checkNotNull(location);
checkNotNull(entity);
this.location = location;
this.entity = new BaseEntity(entity);
}
@Override
public boolean remove() {
return entities.remove(this);
}
@Nullable
@Override
public <T> T getFacet(Class<? extends T> cls) {
return null;
}
/**
* Get the entity state. This is not a copy.
*
* @return the entity
*/
BaseEntity getEntity() {
return entity;
}
@Override
public BaseEntity getState() {
return new BaseEntity(entity);
}
@Override
public Location getLocation() {
return location;
}
@Override
public Extent getExtent() {
return location.getExtent();
}
}
public static Class<?> inject() {
return BlockArrayClipboard.class;
}

View File

@ -202,7 +202,6 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}

View File

@ -318,6 +318,7 @@ public class ForgeQueue_All extends FaweQueue {
@Override
public void clear() {
this.blocks.clear();
this.chunks.clear();
}
@Override

View File

@ -194,7 +194,6 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}

View File

@ -273,6 +273,7 @@ public class ForgeQueue_All extends FaweQueue {
@Override
public void clear() {
this.blocks.clear();
this.chunks.clear();
}
@Override

View File

@ -142,6 +142,7 @@ public abstract class SpongeQueue_0 extends FaweQueue {
@Override
public void clear() {
this.blocks.clear();
this.chunks.clear();
}
@Override

View File

@ -195,7 +195,6 @@ public class SpongeChunk_1_8 extends FaweChunk<Chunk> {
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}