Finish tile entities / some documentation
This commit is contained in:
parent
74a03b2b19
commit
d9d806ac4a
2
pom.xml
2
pom.xml
@ -8,7 +8,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<artifactId>FastAsyncWorldEdit</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<version>3.3.3</version>
|
||||
<name>FastAsyncWorldEdit</name>
|
||||
<packaging>jar</packaging>
|
||||
<build>
|
||||
|
@ -38,6 +38,45 @@ import com.sk89q.worldedit.function.visitor.NonRisingVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
|
||||
/**
|
||||
* Simplified overview:
|
||||
*
|
||||
* [ WorldEdit action]
|
||||
* |
|
||||
* \|/
|
||||
* [ EditSession ] - The change is processed (area restrictions, change limit, block type)
|
||||
* |
|
||||
* \|/
|
||||
* [Block change] - A block change from some location
|
||||
* |
|
||||
* \|/
|
||||
* [ Set Queue ] - The SetQueue manages the implementation specific queue
|
||||
* |
|
||||
* \|/
|
||||
* [ Fawe Queue] - A queue of chunks - check if the queue has the chunk for a change
|
||||
* |
|
||||
* \|/
|
||||
* [ Fawe Chunk Implementation ] - Otherwise create a new FaweChunk object which is a wrapper around the Chunk object
|
||||
* |
|
||||
* \|/
|
||||
* [ Execution ] - When done, the queue then sets the blocks for the chunk, performs lighting updates and sends the chunk packet to the clients
|
||||
*
|
||||
* Why it's faster:
|
||||
* - The chunk is modified directly rather than through the API
|
||||
* \ Removes some overhead, and means some processing can be done async
|
||||
* - Lighting updates are performed on the chunk level rather than for every block
|
||||
* \ e.g. A blob of stone: only the visible blocks need to have the lighting calculated
|
||||
* - Block changes are sent with a chunk packet
|
||||
* \ A chunk packet is generally quicker to create and smaller for large world edits
|
||||
* - No physics updates
|
||||
* \ Physics updates are slow, and are usually performed on each block
|
||||
* - Block data shortcuts
|
||||
* \ Some known blocks don't need to have the data set or accessed (e.g. air is never going to have data)
|
||||
* - Remove redundant extents
|
||||
* \ Up to 11 layers of extents can be removed
|
||||
* - History bypassing
|
||||
* \ FastMode bypasses history and means blocks in the world don't need to be checked and recorded
|
||||
*/
|
||||
public class Fawe {
|
||||
/**
|
||||
* The FAWE instance;
|
||||
|
@ -145,6 +145,7 @@ public class FaweAPI {
|
||||
* If a schematic is too large to be pasted normally<br>
|
||||
* - Skips any block history
|
||||
* - Ignores some block data
|
||||
* - No, it's not streaming it from disk, but it is a lot faster
|
||||
* @param file
|
||||
* @param loc
|
||||
* @return
|
||||
@ -202,6 +203,7 @@ public class FaweAPI {
|
||||
* If a schematic is too large to be pasted normally<br>
|
||||
* - Skips any block history
|
||||
* - Ignores some block data
|
||||
* - Not actually streaming from disk, but it does skip a lot of overhead
|
||||
* @param is
|
||||
* @param loc
|
||||
* @throws IOException
|
||||
@ -321,8 +323,6 @@ public class FaweAPI {
|
||||
|
||||
ids = null;
|
||||
datas = null;
|
||||
System.gc();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,7 @@ public class FaweCache {
|
||||
public final static short[] CACHE_ID = new short[65535];
|
||||
public final static byte[] CACHE_DATA = new byte[65535];
|
||||
|
||||
// Faster than java random (since the game just needs to look random)
|
||||
public final static PseudoRandom RANDOM = new PseudoRandom();
|
||||
|
||||
static {
|
||||
|
@ -34,6 +34,10 @@ public class BukkitPlayer extends FawePlayer<Player> {
|
||||
|
||||
@Override
|
||||
public void setPermission(final String perm, final boolean flag) {
|
||||
/*
|
||||
* Permissions are used to managing WorldEdit region restrictions
|
||||
* - The `/wea` command will give/remove the required bypass permission
|
||||
*/
|
||||
if (Fawe.<FaweBukkit> imp().getVault() == null) {
|
||||
this.parent.addAttachment(Fawe.<FaweBukkit> imp()).setPermission("fawe.bypass", flag);
|
||||
} else if (flag) {
|
||||
|
@ -95,11 +95,24 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Kinda a really messy class I just copied over from an old project<br>
|
||||
* - Still works, so cbf cleaning it up<br>
|
||||
* - Completely optional to have this class enabled since things get cancelled further down anyway<br>
|
||||
* - Useful since it informs the player why an edit changed no blocks etc.<br>
|
||||
* - Predicts the number of blocks changed and cancels the edit if it's too large<br>
|
||||
* - Predicts where the edit will effect and cancels it if it's outside a region<br>
|
||||
* - Restricts the brush iteration limit<br>
|
||||
*/
|
||||
@Override
|
||||
public void setupWEListener() {
|
||||
this.getServer().getPluginManager().registerEvents(new WEListener(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vault isn't required, but used for setting player permissions (WorldEdit bypass)
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void setupVault() {
|
||||
try {
|
||||
@ -109,6 +122,9 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The task manager handles sync/async tasks
|
||||
*/
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new BukkitTaskMan(this);
|
||||
@ -133,6 +149,13 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The FaweQueue is a core part of block placement<br>
|
||||
* - The queue returned here is used in the SetQueue class (SetQueue handles the implementation specific queue)<br>
|
||||
* - Block changes are grouped by chunk (as it's more efficient for lighting/packet sending)<br>
|
||||
* - The FaweQueue returned here will provide the wrapper around the chunk object (FaweChunk)<br>
|
||||
* - When a block change is requested, the SetQueue will first check if the chunk exists in the queue, or it will create and add it<br>
|
||||
*/
|
||||
@Override
|
||||
public FaweQueue getQueue() {
|
||||
if (FaweAPI.checkVersion(this.getServerVersion(), 1, 9, 0)) {
|
||||
@ -167,11 +190,17 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
/**
|
||||
* The EditSessionWrapper should have the same functionality as the normal EditSessionWrapper but with some optimizations
|
||||
*/
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(final EditSession session) {
|
||||
return new BukkitEditSessionWrapper_1_8(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* A mask manager handles region restrictions e.g. PlotSquared plots / WorldGuard regions
|
||||
*/
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
final Plugin worldguardPlugin = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard");
|
||||
|
@ -27,6 +27,16 @@ import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
/**
|
||||
* Kinda a really messy class I just copied over from an old project<br>
|
||||
* - Still works, so cbf cleaning it up<br>
|
||||
* - Completely optional to have this class enabled since things get cancelled further down anyway<br>
|
||||
* - Useful since it informs the player why an edit changed no blocks etc.<br>
|
||||
* - Predicts the number of blocks changed and cancels the edit if it's too large<br>
|
||||
* - Predicts where the edit will effect and cancels it if it's outside a region<br>
|
||||
* - Restricts the brush iteration limit<br>
|
||||
* @deprecated as I plan on replacing it at some point
|
||||
*/
|
||||
@Deprecated
|
||||
public class WEListener implements Listener {
|
||||
|
||||
|
@ -14,17 +14,18 @@ public class BukkitEditSessionWrapper_0 extends EditSessionWrapper {
|
||||
public BukkitEditSessionWrapper_0(final EditSession session) {
|
||||
super(session);
|
||||
try {
|
||||
// Try to hook into BlocksHub
|
||||
this.hook = new BlocksHubHook();
|
||||
} catch (final Throwable e) {
|
||||
|
||||
}
|
||||
} catch (final Throwable e) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent getHistoryExtent(final Extent parent, final ChangeSet set, final FawePlayer<?> player) {
|
||||
if (this.hook != null) {
|
||||
// If we are doing logging, return a custom logging extent
|
||||
return this.hook.getLoggingExtent(parent, set, player);
|
||||
}
|
||||
// Otherwise return the normal history extent
|
||||
return super.getHistoryExtent(parent, set, player);
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,20 @@ import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
|
||||
/**
|
||||
* The base object for
|
||||
*/
|
||||
public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
|
||||
|
||||
/**
|
||||
* Map of loaded chunks for quicker checking
|
||||
*/
|
||||
private final HashMap<String, HashSet<Long>> loaded = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Map of chunks in the queue
|
||||
*/
|
||||
private final ConcurrentHashMap<ChunkLoc, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
|
||||
public BukkitQueue_0() {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@ -109,8 +120,17 @@ public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
|
||||
public void onChunkUnload(final ChunkUnloadEvent event) {
|
||||
this.removeLoaded(event.getChunk());
|
||||
}
|
||||
|
||||
private final ConcurrentHashMap<ChunkLoc, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addTask(String world, int x, int y, int z, Runnable runnable) {
|
||||
// TODO Auto-generated method stub
|
||||
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
|
||||
FaweChunk<Chunk> result = this.blocks.get(wrap);
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException("Task must be accompanied by a block change or manually adding to queue!");
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(final String world, int x, final int y, int z, final short id, final byte data) {
|
||||
@ -186,6 +206,7 @@ public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -431,8 +431,19 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the server is < 1% available memory (i.e. likely to crash)<br>
|
||||
* - You can disable this in the conifg<br>
|
||||
* - Will try to free up some memory<br>
|
||||
* - Clears the queue<br>
|
||||
* - Clears worldedit history<br>
|
||||
* - Clears entities<br>
|
||||
* - Unloads chunks in vacant worlds<br>
|
||||
* - Unloads non visible chunks<br>
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
// Clear the queue
|
||||
super.clear();
|
||||
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();
|
||||
final int distance = Bukkit.getViewDistance() + 2;
|
||||
@ -526,31 +537,6 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
|
||||
}
|
||||
toUnload = null;
|
||||
players = null;
|
||||
System.gc();
|
||||
System.gc();
|
||||
free = MemUtil.calculateMemory();
|
||||
if (free > 1) {
|
||||
return;
|
||||
}
|
||||
Collection<? extends Player> online = Bukkit.getOnlinePlayers();
|
||||
if (online.size() > 0) {
|
||||
online.iterator().next().kickPlayer("java.lang.OutOfMemoryError");
|
||||
}
|
||||
online = null;
|
||||
System.gc();
|
||||
System.gc();
|
||||
free = MemUtil.calculateMemory();
|
||||
if ((free > 1) || (Bukkit.getOnlinePlayers().size() > 0)) {
|
||||
return;
|
||||
}
|
||||
for (final World world : Bukkit.getWorlds()) {
|
||||
final String name = world.getName();
|
||||
for (final Chunk chunk : world.getLoadedChunks()) {
|
||||
this.unloadChunk(name, chunk);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
public Object newChunkSection(final int i, final boolean flag, final char[] ids) {
|
||||
|
@ -28,6 +28,10 @@ import com.boydti.fawe.bukkit.FaweBukkit;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.ChunkLoc;
|
||||
|
||||
/**
|
||||
* Please ignore
|
||||
*/
|
||||
@Deprecated
|
||||
public class FaweGenerator_1_8 extends ChunkGenerator implements Listener {
|
||||
private boolean events;
|
||||
|
||||
|
@ -30,6 +30,7 @@ import org.bukkit.generator.ChunkGenerator;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.ChunkLoc;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
@ -41,7 +42,7 @@ import com.boydti.fawe.util.ReflectionUtils.RefConstructor;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefField;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefMethod;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefMethod.RefExecutor;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
|
||||
public class BukkitQueue_1_9 extends BukkitQueue_0 {
|
||||
@ -56,12 +57,10 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
|
||||
private final RefClass classBlock = getRefClass("{nms}.Block");
|
||||
private final RefClass classIBlockData = getRefClass("{nms}.IBlockData");
|
||||
private final RefMethod methodGetHandleChunk;
|
||||
private final RefConstructor MapChunk;
|
||||
private final RefMethod methodInitLighting;
|
||||
private final RefConstructor classBlockPositionConstructor;
|
||||
private final RefConstructor classChunkSectionConstructor;
|
||||
private final RefMethod methodW;
|
||||
private final RefMethod methodAreNeighborsLoaded;
|
||||
private final RefField fieldSections;
|
||||
private final RefField fieldWorld;
|
||||
private final RefMethod methodGetBlocks;
|
||||
@ -74,7 +73,6 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
|
||||
public BukkitQueue_1_9() throws NoSuchMethodException, RuntimeException {
|
||||
this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle");
|
||||
this.methodInitLighting = this.classChunk.getMethod("initLighting");
|
||||
this.MapChunk = this.classMapChunk.getConstructor(this.classChunk.getRealClass(), boolean.class, int.class);
|
||||
this.classBlockPositionConstructor = this.classBlockPosition.getConstructor(int.class, int.class, int.class);
|
||||
this.methodW = this.classWorld.getMethod("w", this.classBlockPosition.getRealClass());
|
||||
this.fieldSections = this.classChunk.getField("sections");
|
||||
@ -82,7 +80,6 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
|
||||
this.methodGetByCombinedId = this.classBlock.getMethod("getByCombinedId", int.class);
|
||||
this.methodGetBlocks = this.classChunkSection.getMethod("getBlocks");
|
||||
this.methodSetType = this.classChunkSection.getMethod("setType", int.class, int.class, int.class, this.classIBlockData.getRealClass());
|
||||
this.methodAreNeighborsLoaded = this.classChunk.getMethod("areNeighborsLoaded", int.class);
|
||||
this.classChunkSectionConstructor = this.classChunkSection.getConstructor(int.class, boolean.class, char[].class);
|
||||
this.air = this.methodGetByCombinedId.call(0);
|
||||
this.tileEntityListTick = this.classWorld.getField("tileEntityListTick");
|
||||
@ -92,12 +89,17 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
|
||||
for (final FaweChunk<Chunk> fc : fcs) {
|
||||
final Chunk chunk = fc.getChunk();
|
||||
final ChunkLoc loc = fc.getChunkLoc();
|
||||
chunk.getWorld().refreshChunk(loc.x, loc.z);
|
||||
sendChunk(fc);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void sendChunk(FaweChunk<Chunk> fc) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
final Chunk chunk = fc.getChunk();
|
||||
final ChunkLoc loc = fc.getChunkLoc();
|
||||
chunk.getWorld().refreshChunk(loc.x, loc.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(final FaweChunk<?> pc, final boolean fixAll) {
|
||||
@ -358,18 +360,28 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskManager.runTaskLater(new Runnable() {
|
||||
TaskManager.IMP.later(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ChunkLoc loc = fs.getChunkLoc();
|
||||
world.refreshChunk(loc.x, loc.z);
|
||||
sendChunk(fs);
|
||||
}
|
||||
}, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the server is < 1% available memory (i.e. likely to crash)<br>
|
||||
* - You can disable this in the conifg<br>
|
||||
* - Will try to free up some memory<br>
|
||||
* - Clears the queue<br>
|
||||
* - Clears worldedit history<br>
|
||||
* - Clears entities<br>
|
||||
* - Unloads chunks in vacant worlds<br>
|
||||
* - Unloads non visible chunks<br>
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
// Clear the queue
|
||||
super.clear();
|
||||
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();
|
||||
final int distance = Bukkit.getViewDistance() + 2;
|
||||
@ -463,31 +475,6 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
|
||||
}
|
||||
toUnload = null;
|
||||
players = null;
|
||||
System.gc();
|
||||
System.gc();
|
||||
free = MemUtil.calculateMemory();
|
||||
if (free > 1) {
|
||||
return;
|
||||
}
|
||||
Collection<? extends Player> online = Bukkit.getOnlinePlayers();
|
||||
if (online.size() > 0) {
|
||||
online.iterator().next().kickPlayer("java.lang.OutOfMemoryError");
|
||||
}
|
||||
online = null;
|
||||
System.gc();
|
||||
System.gc();
|
||||
free = MemUtil.calculateMemory();
|
||||
if ((free > 1) || (Bukkit.getOnlinePlayers().size() > 0)) {
|
||||
return;
|
||||
}
|
||||
for (final World world : Bukkit.getWorlds()) {
|
||||
final String name = world.getName();
|
||||
for (final Chunk chunk : world.getLoadedChunks()) {
|
||||
this.unloadChunk(name, chunk);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
public Object newChunkSection(final int i, final boolean flag, final char[] ids) {
|
||||
|
@ -4,6 +4,7 @@ import java.util.List;
|
||||
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
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;
|
||||
@ -104,6 +105,58 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
final int y = location.getBlockY();
|
||||
final int z = location.getBlockZ();
|
||||
switch (id) {
|
||||
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: {
|
||||
SetQueue.IMP.setBlock(this.world, x, y, z, id, (byte) block.getData());
|
||||
if (block.hasNbtData()) {
|
||||
final CompoundTag nbt = block.getNbtData();
|
||||
SetQueue.IMP.addTask(this.world, x, y, z, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
FastWorldEditExtent.super.setBlock(location, block);
|
||||
} catch (WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
@ -113,7 +166,6 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 25:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
@ -127,13 +179,10 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
case 48:
|
||||
case 49:
|
||||
case 51:
|
||||
case 52:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
@ -147,7 +196,6 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
@ -157,16 +205,10 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 117:
|
||||
case 121:
|
||||
case 122:
|
||||
case 123:
|
||||
case 124:
|
||||
case 129:
|
||||
case 133:
|
||||
case 138:
|
||||
case 137:
|
||||
case 140:
|
||||
case 165:
|
||||
case 166:
|
||||
case 169:
|
||||
@ -174,8 +216,6 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 176:
|
||||
case 177:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
@ -8,6 +10,8 @@ public abstract class FaweChunk<T> {
|
||||
|
||||
private ChunkLoc chunk;
|
||||
|
||||
private final ArrayDeque<Runnable> tasks = new ArrayDeque<Runnable>();
|
||||
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*/
|
||||
@ -44,6 +48,19 @@ public abstract class FaweChunk<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void addTask(Runnable run) {
|
||||
if (run != null) {
|
||||
tasks.add(run);
|
||||
}
|
||||
}
|
||||
|
||||
public void executeTasks() {
|
||||
for (Runnable task : tasks) {
|
||||
task.run();
|
||||
}
|
||||
tasks.clear();
|
||||
}
|
||||
|
||||
public abstract T getChunk();
|
||||
|
||||
public abstract void setBlock(final int x, final int y, final int z, final int id, final byte data);
|
||||
|
@ -187,8 +187,21 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||
return false;
|
||||
}
|
||||
SetQueue.IMP.setBlock(this.world, x, location.getBlockY(), z, id, (byte) block.getData());
|
||||
if (block.hasNbtData()) {
|
||||
SetQueue.IMP.addTask(this.world, x, location.getBlockY(), z, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ProcessedWEExtent.super.setBlock(location, block);
|
||||
} catch (WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
final int x = location.getBlockX();
|
||||
@ -282,19 +295,17 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||
case 191:
|
||||
case 192: {
|
||||
SetQueue.IMP.setBlock(this.world, x, y, z, id);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
SetQueue.IMP.setBlock(this.world, x, y, z, id, (byte) block.getData());
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -7,6 +7,7 @@ import com.boydti.fawe.object.FaweChunk;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
|
||||
public abstract class FaweQueue {
|
||||
|
||||
public abstract boolean setBlock(final String world, final int x, final int y, final int z, final short id, final byte data);
|
||||
|
||||
public abstract boolean setBiome(final String world, final int x, final int z, final BaseBiome biome);
|
||||
@ -38,5 +39,10 @@ public abstract class FaweQueue {
|
||||
// Unload chunks
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the server is < 1% available memory
|
||||
*/
|
||||
protected abstract void clear();
|
||||
|
||||
public abstract void addTask(String world, int x, int y, int z, Runnable runnable);
|
||||
}
|
||||
|
@ -9,15 +9,30 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
|
||||
public class SetQueue {
|
||||
|
||||
/**
|
||||
* The implementation specific queue
|
||||
*/
|
||||
public static final SetQueue IMP = new SetQueue();
|
||||
|
||||
public FaweQueue queue;
|
||||
|
||||
/**
|
||||
* Track the time in ticks
|
||||
*/
|
||||
private final AtomicInteger time_waiting = new AtomicInteger(2);
|
||||
private final AtomicInteger time_current = new AtomicInteger(0);
|
||||
private final ArrayDeque<Runnable> runnables = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the server
|
||||
*/
|
||||
private long last;
|
||||
private long last2;
|
||||
|
||||
/**
|
||||
* A queue of tasks that will run when the queue is empty
|
||||
*/
|
||||
private final ArrayDeque<Runnable> runnables = new ArrayDeque<>();
|
||||
|
||||
|
||||
public SetQueue() {
|
||||
TaskManager.IMP.repeat(new Runnable() {
|
||||
@ -145,4 +160,17 @@ public class SetQueue {
|
||||
public boolean isChunkLoaded(final String world, final int x, final int z) {
|
||||
return this.queue.isChunkLoaded(world, x, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a task to run when the chunk is set<br>
|
||||
* @throws IllegalArgumentException if the chunk is not in the queue
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param runnable
|
||||
*/
|
||||
public void addTask(String world, int x, int y, int z, Runnable runnable) {
|
||||
this.queue.addTask(world, x, y, z, runnable);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.FaweBukkit
|
||||
version: 3.3.1
|
||||
version: 3.3.3
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
|
Loading…
Reference in New Issue
Block a user