Queue, editsession and history optimizations

Streamlined the queue so now the queue doesn't need to be fetched on
each block
Removed block reording from editsession as it alone takes half a
second/million blocks
Replaced block fetch from history extent with optimized algorithm.
This commit is contained in:
Jesse Boyd 2016-04-04 04:03:35 +10:00
parent 491b6bc646
commit fb15a425a7
31 changed files with 569 additions and 1038 deletions

View File

@ -27,5 +27,4 @@ public class BukkitCommand implements CommandExecutor {
this.cmd.execute(plr, args);
return true;
}
}

View File

@ -184,15 +184,15 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
* - 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() {
public FaweQueue getNewQueue(String world) {
if (FaweAPI.checkVersion(this.getServerVersion(), 1, 9, 0)) {
try {
return new BukkitQueue_1_9();
return new BukkitQueue_1_9(world);
} catch (final Throwable e) {
e.printStackTrace();
}
}
return new BukkitQueue_1_8();
return new BukkitQueue_1_8(world);
}
private int[] version;

View File

@ -1,181 +1,103 @@
package com.boydti.fawe.bukkit.v0;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.plugin.Plugin;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
/**
* 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<>();
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
public BukkitQueue_0() {
public BukkitQueue_0(String world) {
super(world);
TaskManager.IMP.task(new Runnable() {
@Override
public void run() {
Bukkit.getPluginManager().registerEvents(BukkitQueue_0.this, (Plugin) Fawe.imp());
}
});
for (final World world : Bukkit.getWorlds()) {
for (final Chunk chunk : world.getLoadedChunks()) {
this.addLoaded(chunk);
}
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onWorldLoad(final WorldLoadEvent event) {
final World world = event.getWorld();
for (final Chunk chunk : world.getLoadedChunks()) {
this.addLoaded(chunk);
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onWorldUnload(final WorldUnloadEvent event) {
this.loaded.remove(event.getWorld().getName());
}
public void addLoaded(final Chunk chunk) {
final String world = chunk.getWorld().getName();
final long x = chunk.getX();
final long z = chunk.getZ();
final long id = (x << 32) | (z & 0xFFFFFFFFL);
HashSet<Long> map = this.loaded.get(world);
if (map != null) {
map.add(id);
} else {
map = new HashSet<>(Arrays.asList(id));
this.loaded.put(world, map);
}
}
public void removeLoaded(final Chunk chunk) {
final String world = chunk.getWorld().getName();
final long x = chunk.getX();
final long z = chunk.getZ();
final long id = (x << 32) | (z & 0xFFFFFFFFL);
final HashSet<Long> map = this.loaded.get(world);
if (map != null) {
map.remove(id);
}
}
@Override
public boolean isChunkLoaded(final String world, final int x, final int z) {
final long id = ((long) x << 32) | (z & 0xFFFFFFFFL);
final HashSet<Long> map = this.loaded.get(world);
if (map != null) {
return map.contains(id);
}
return false;
public boolean isChunkLoaded(int x, int z) {
return Bukkit.getWorld(world).isChunkLoaded(x, z);
// long id = ((long) x << 32) | (z & 0xFFFFFFFFL);
// HashSet<Long> map = this.loaded.get(world);
// if (map != null) {
// return map.contains(id);
// }
// return false;
};
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onChunkLoad(final ChunkLoadEvent event) {
final Chunk chunk = event.getChunk();
this.addLoaded(chunk);
if (Settings.FIX_ALL_LIGHTING) {
this.fixLighting(this.getChunk(new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ())), false);
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onChunkUnload(final ChunkUnloadEvent event) {
this.removeLoaded(event.getChunk());
}
@Override
public void addTask(String world, int x, int y, int z, Runnable runnable) {
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
FaweChunk<Chunk> result = this.blocks.get(wrap);
public void addTask(int x, int z, Runnable runnable) {
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
FaweChunk<Chunk> result = this.blocks.get(pair);
if (result == null) {
result = this.getChunk(wrap);
result = this.getChunk(x, z);
result.addTask(runnable);
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
if (previous == null) {
return;
}
this.blocks.put(wrap, previous);
this.blocks.put(pair, previous);
result = previous;
}
result.addTask(runnable);
}
@Override
public boolean setBlock(final String world, int x, final int y, int z, final short id, final byte data) {
public boolean setBlock(int x, int y, int z, short id, byte data) {
if ((y > 255) || (y < 0)) {
return false;
}
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
x = x & 15;
z = z & 15;
FaweChunk<Chunk> result = this.blocks.get(wrap);
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
FaweChunk<Chunk> result = this.blocks.get(pair);
if (result == null) {
result = this.getChunk(wrap);
result.setBlock(x, y, z, id, data);
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
result = this.getChunk(x >> 4, z >> 4);
result.setBlock(x & 15, y, z & 15, id, data);
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
if (previous == null) {
return true;
}
this.blocks.put(wrap, previous);
this.blocks.put(pair, previous);
result = previous;
}
result.setBlock(x, y, z, id, data);
result.setBlock(x & 15, y, z & 15, id, data);
return true;
}
@Override
public boolean setBiome(final String world, int x, int z, final BaseBiome biome) {
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
x = x & 15;
z = z & 15;
FaweChunk<Chunk> result = this.blocks.get(wrap);
public boolean setBiome(int x, int z, BaseBiome biome) {
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
FaweChunk<Chunk> result = this.blocks.get(pair);
if (result == null) {
result = this.getChunk(wrap);
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
result = this.getChunk(x >> 4, z >> 4);
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
if (previous != null) {
this.blocks.put(wrap, previous);
this.blocks.put(pair, previous);
result = previous;
}
}
result.setBiome(x, z, biome);
result.setBiome(x & 15, z & 15, biome);
return true;
}
@ -185,28 +107,28 @@ public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
if (this.blocks.size() == 0) {
return null;
}
final Iterator<Entry<ChunkLoc, FaweChunk<Chunk>>> iter = this.blocks.entrySet().iterator();
final FaweChunk<Chunk> toReturn = iter.next().getValue();
Iterator<Entry<Long, FaweChunk<Chunk>>> iter = this.blocks.entrySet().iterator();
FaweChunk<Chunk> toReturn = iter.next().getValue();
if (SetQueue.IMP.isWaiting()) {
return null;
}
iter.remove();
this.execute(toReturn);
return toReturn;
} catch (final Throwable e) {
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
private final ArrayDeque<FaweChunk<Chunk>> toUpdate = new ArrayDeque<>();
private ArrayDeque<FaweChunk<Chunk>> toUpdate = new ArrayDeque<>();
public boolean execute(final FaweChunk<Chunk> fc) {
public boolean execute(FaweChunk<Chunk> fc) {
if (fc == null) {
return false;
}
// Load chunk
final Chunk chunk = fc.getChunk();
Chunk chunk = fc.getChunk();
chunk.load(true);
// Set blocks / entities / biome
if (!this.setComponents(fc)) {
@ -222,17 +144,17 @@ public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
}
@Override
public void setChunk(final FaweChunk<?> chunk) {
this.blocks.put(chunk.getChunkLoc(), (FaweChunk<Chunk>) chunk);
public void setChunk(FaweChunk<?> chunk) {
this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
}
public abstract Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs);
public abstract Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs);
public abstract boolean setComponents(final FaweChunk<Chunk> fc);
public abstract boolean setComponents(FaweChunk<Chunk> fc);
@Override
public abstract FaweChunk<Chunk> getChunk(final ChunkLoc wrap);
public abstract FaweChunk<Chunk> getChunk(int x, int z);
@Override
public abstract boolean fixLighting(final FaweChunk<?> fc, final boolean fixAll);
public abstract boolean fixLighting(FaweChunk<?> fc, boolean fixAll);
}

View File

@ -1,15 +1,13 @@
package com.boydti.fawe.bukkit.v1_8;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.util.FaweQueue;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.sk89q.worldedit.world.biome.BaseBiome;
public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
private char[][] ids;
@ -24,8 +22,8 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*/
protected BukkitChunk_1_8(final ChunkLoc chunk) {
super(chunk);
protected BukkitChunk_1_8(FaweQueue parent, int x, int z) {
super(parent, x, z);
this.ids = new char[16][];
this.count = new short[16];
this.air = new short[16];
@ -35,15 +33,14 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
@Override
public Chunk getChunk() {
if (this.chunk == null) {
final ChunkLoc cl = this.getChunkLoc();
this.chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z);
this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
}
return this.chunk;
}
@Override
public void setChunkLoc(final ChunkLoc loc) {
super.setChunkLoc(loc);
public void setLoc(final FaweQueue parent, int x, int z) {
super.setLoc(parent, x, z);
this.chunk = null;
}

View File

@ -4,7 +4,6 @@ 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;
import com.boydti.fawe.object.IntegerPair;
@ -75,9 +74,8 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
private RefMethod methodGetWorld;
private RefField tileEntityListTick;
private final HashMap<String, FaweGenerator_1_8> worldMap = new HashMap<>();
public BukkitQueue_1_8() {
public BukkitQueue_1_8(String world) {
super(world);
try {
this.methodGetHandlePlayer = this.classCraftPlayer.getMethod("getHandle");
this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle");
@ -99,20 +97,6 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
}
}
public FaweGenerator_1_8 getFaweGenerator(final World world) {
final ChunkGenerator gen = world.getGenerator();
if ((gen != null) && (gen instanceof FaweGenerator_1_8)) {
return (FaweGenerator_1_8) gen;
}
FaweGenerator_1_8 faweGen = this.worldMap.get(world.getName());
if (faweGen != null) {
return faweGen;
}
faweGen = new FaweGenerator_1_8(this, world);
this.worldMap.put(world.getName(), faweGen);
return faweGen;
}
@Override
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
for (final FaweChunk<Chunk> fc : fcs) {
@ -264,6 +248,37 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
return array[j] >> 4;
}
private int lcx = Integer.MIN_VALUE;
private int lcz = Integer.MIN_VALUE;
private int lcy = Integer.MIN_VALUE;
private Object lc;
private char[] ls;
private World bukkitWorld;
@Override
public int getCombinedId4Data(int x, int y, int z) {
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;
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 {
@ -373,8 +388,8 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
final int[][] biomes = fs.getBiomeArray();
if (biomes != null) {
final LocalWorld lw = BukkitUtil.getLocalWorld(world);
final int X = fs.getChunkLoc().x << 4;
final int Z = fs.getChunkLoc().z << 4;
final int X = fs.getX() << 4;
final int Z = fs.getZ() << 4;
final BaseBiome bb = new BaseBiome(0);
int last = 0;
for (int x = 0; x < 16; x++) {
@ -529,8 +544,8 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
}
@Override
public FaweChunk<Chunk> getChunk(final ChunkLoc wrap) {
return new BukkitChunk_1_8(wrap);
public FaweChunk<Chunk> getChunk(int x, int z) {
return new BukkitChunk_1_8(this, x, z);
}
public boolean unloadChunk(final String world, final Chunk chunk) {

View File

@ -1,459 +0,0 @@
package com.boydti.fawe.bukkit.v1_8;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkPopulateEvent;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
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;
private final ChunkGenerator parent;
private final List<BlockPopulator> pops;
private final Object provider;
private short[][] ids;
private byte[][] data;
private Map<?, ?> tiles;
private List<?>[] entities;
private Biome[][] biomes;
private final World world;
private final BukkitQueue_1_8 queue;
private void registerEvents() {
if (this.events) {
return;
}
Bukkit.getPluginManager().registerEvents(this, Fawe.<FaweBukkit> imp());
}
@EventHandler
private void onPopulate(final ChunkPopulateEvent event) {
final World world = event.getWorld();
final ChunkGenerator gen = world.getGenerator();
if (gen instanceof FaweGenerator_1_8) {
final FaweGenerator_1_8 fawe = (FaweGenerator_1_8) gen;
if (fawe.data == null) {
return;
}
fawe.populate(event.getChunk());
this.decouple((FaweGenerator_1_8) gen, world);
}
}
public void setBlock(final short[][] result, final int x, final int y, final int z, final short blkid) {
if (result[FaweCache.CACHE_I[y][x][z]] == null) {
result[FaweCache.CACHE_I[y][x][z]] = new short[4096];
}
result[FaweCache.CACHE_I[y][x][z]][FaweCache.CACHE_J[y][x][z]] = blkid;
}
public void setBlock(final short[][] result, final int x, final int y, final int z, final short[] blkid) {
if (blkid.length == 1) {
this.setBlock(result, x, y, z, blkid[0]);
}
final short id = blkid[FaweCache.RANDOM.random(blkid.length)];
if (result[FaweCache.CACHE_I[y][x][z]] == null) {
result[FaweCache.CACHE_I[y][x][z]] = new short[4096];
}
result[FaweCache.CACHE_I[y][x][z]][FaweCache.CACHE_J[y][x][z]] = id;
}
public void setBlocks(final short[][] ids, final byte[][] data, final int x, final int z) {
this.ids = ids;
this.data = data == null ? new byte[16][] : data;
if (this.parent == null) {
this.inject(this, this.world);
}
this.world.regenerateChunk(x, z);
}
/**
* Regenerate chunk with the provided id / data / block count<br>
* - You can provide null for datas / count but it will be marginally slower
* @param ids
* @param datas
* @param count
* @param chunk
*/
@Deprecated
public void regenerateBlocks(final short[][] ids, byte[][] datas, short[] count, final Chunk chunk) {
if (datas == null) {
datas = new byte[16][];
}
if (count == null) {
count = new short[16];
}
final int x = chunk.getX();
final int z = chunk.getZ();
boolean skip = true;
for (int i = 0; i < 16; i++) {
if (count[i] < 4096) {
skip = false;
break;
}
}
if (!skip) {
try {
chunk.load(true);
this.biomes = new Biome[16][16];
final int X = x << 4;
final int Z = z << 4;
for (int xx = 0; xx < 16; xx++) {
final int xxx = X + x;
for (int zz = 0; zz < 16; zz++) {
final int zzz = Z + zz;
this.biomes[xx][zz] = this.world.getBiome(xxx, zzz);
}
}
final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle");
final Object c = getHandele.invoke(chunk);
final Class<? extends Object> clazz = c.getClass();
final Field sf = clazz.getDeclaredField("sections");
sf.setAccessible(true);
final Field tf = clazz.getDeclaredField("tileEntities");
final Field ef = clazz.getDeclaredField("entitySlices");
final Object[] sections = (Object[]) sf.get(c);
final HashMap<?, ?> tiles = (HashMap<?, ?>) tf.get(c);
final List<?>[] entities = (List<?>[]) ef.get(c);
Method xm = null;
Method ym = null;
Method zm = null;
// Copy entities / blockstates
final Set<Entry<?, ?>> entryset = (Set<Entry<?, ?>>) (Set<?>) tiles.entrySet();
final Iterator<Entry<?, ?>> iter = entryset.iterator();
while (iter.hasNext()) {
final Entry<?, ?> tile = iter.next();
final Object loc = tile.getKey();
if (xm == null) {
final Class<? extends Object> clazz2 = loc.getClass().getSuperclass();
xm = clazz2.getDeclaredMethod("getX");
ym = clazz2.getDeclaredMethod("getY");
zm = clazz2.getDeclaredMethod("getZ");
}
final int lx = (int) xm.invoke(loc) & 15;
final int ly = (int) ym.invoke(loc);
final int lz = (int) zm.invoke(loc) & 15;
final int j = FaweCache.CACHE_I[ly][lx][lz];
final int k = FaweCache.CACHE_J[ly][lx][lz];
if (ids[j] == null) {
continue;
}
if (ids[j][k] != 0) {
iter.remove();
}
}
this.tiles = tiles;
// Trim entities
for (int i = 0; i < 16; i++) {
if ((entities[i] != null) && (count[i] >= 4096)) {
entities[i].clear();
}
}
this.entities = entities;
// Efficiently merge sections
Method getIdArray = null;
for (int j = 0; j < sections.length; j++) {
if (count[j] >= 4096) {
continue;
}
final Object section = sections[j];
if (section == null) {
continue;
}
if (getIdArray == null) {
final Class<? extends Object> clazz2 = section.getClass();
getIdArray = clazz2.getDeclaredMethod("getIdArray");
}
final char[] array = (char[]) getIdArray.invoke(section);
for (int k = 0; k < array.length; k++) {
final int i = array[k];
if (i < 16) {
continue;
}
short[] va = ids[j];
if (va == null) {
va = new short[4096];
ids[j] = va;
}
final short v = va[k];
if (v != 0) {
continue;
}
final short id = FaweCache.CACHE_ID[i];
va[k] = id;
switch (id) {
case 0:
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:
continue;
case 53:
case 67:
case 108:
case 109:
case 114:
case 128:
case 134:
case 135:
case 136:
case 156:
case 163:
case 164:
case 180:
byte db = FaweCache.CACHE_DATA[i];
if (db == 0) {
db = -1;
}
if (datas[j] == null) {
datas[j] = new byte[4096];
}
datas[j][k] = db;
continue;
}
final byte db = FaweCache.CACHE_DATA[i];
if (db == 0) {
continue;
}
if (datas[j] == null) {
datas[j] = new byte[4096];
}
datas[j][k] = db;
}
}
} catch (final Throwable e) {
e.printStackTrace();
return;
}
}
// Execute
this.ids = ids;
this.data = datas;
if (this.parent == null) {
this.inject(this, this.world);
}
this.world.regenerateChunk(x, z);
}
public void inject(final FaweGenerator_1_8 gen, final World world) {
this.queue.setGenerator(world, gen);
this.queue.setPopulator(world, new ArrayList<BlockPopulator>());
this.queue.setProvider(world, null);
}
public void decouple(final FaweGenerator_1_8 gen, final World world) {
gen.data = null;
gen.ids = null;
gen.tiles = null;
gen.entities = null;
gen.biomes = null;
if (gen.parent == null) {
this.queue.setGenerator(world, gen.parent);
this.queue.setPopulator(world, gen.pops);
if (gen.provider != null) {
this.queue.setProvider(world, gen.provider);
}
}
}
public FaweGenerator_1_8(final BukkitQueue_1_8 queue, final World world) {
this.queue = queue;
this.world = world;
this.parent = world.getGenerator();
this.pops = world.getPopulators();
if (this.parent == null) {
this.provider = queue.getProvider(world);
} else {
this.provider = null;
}
this.registerEvents();
}
@Override
public short[][] generateExtBlockSections(final World world, final Random random, final int x, final int z, final BiomeGrid biomes) {
short[][] result;
if (this.ids != null) {
result = this.ids;
if ((biomes != null) && (this.biomes != null)) {
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
biomes.setBiome(i, j, this.biomes[i][j]);
}
}
}
} else if (this.parent != null) {
result = this.parent.generateExtBlockSections(world, random, x, z, biomes);
} else {
result = null;
}
return result;
}
public void populate(final Chunk chunk) {
for (int i = 0; i < this.data.length; i++) {
final byte[] section = this.data[i];
if (section == null) {
continue;
}
for (int j = 0; j < section.length; j++) {
final byte v = section[j];
if (v == 0) {
continue;
}
final int x = FaweCache.CACHE_X[i][j];
final int y = FaweCache.CACHE_Y[i][j];
final int z = FaweCache.CACHE_Z[i][j];
chunk.getBlock(x, y, z).setData(v != -1 ? v : 0, false);
}
}
if ((this.tiles != null) || (this.entities != null)) {
this.queue.setEntitiesAndTiles(chunk, this.entities, this.tiles);
}
final BukkitChunk_1_8 fc = new BukkitChunk_1_8(new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ()));
fc.chunk = chunk;
this.queue.fixLighting(fc, Settings.FIX_ALL_LIGHTING);
}
@Override
public byte[] generate(final World world, final Random random, final int x, final int z) {
if (this.ids == null) {
try {
this.parent.generate(world, random, x, z);
} catch (final Throwable e) {
return null;
}
}
return null;
}
@Override
public byte[][] generateBlockSections(final World world, final Random random, final int x, final int z, final BiomeGrid biomes) {
if ((this.ids == null) && (this.parent != null)) {
return this.parent.generateBlockSections(world, random, x, z, biomes);
}
return null;
}
@Override
public boolean canSpawn(final World world, final int x, final int z) {
if (this.parent != null) {
return this.parent.canSpawn(world, x, z);
}
return true;
}
@Override
public List<BlockPopulator> getDefaultPopulators(final World world) {
if ((this.ids == null) && (this.parent != null)) {
return this.parent.getDefaultPopulators(world);
}
return null;
}
@Override
public Location getFixedSpawnLocation(final World world, final Random random) {
if ((this.ids == null) && (this.parent != null)) {
return this.parent.getFixedSpawnLocation(world, random);
}
return null;
}
}

View File

@ -1,15 +1,13 @@
package com.boydti.fawe.bukkit.v1_9;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.util.FaweQueue;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.sk89q.worldedit.world.biome.BaseBiome;
public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
private int[][] ids;
@ -24,8 +22,8 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*/
protected BukkitChunk_1_9(final ChunkLoc chunk) {
super(chunk);
protected BukkitChunk_1_9(FaweQueue parent, int x, int z) {
super(parent, x, z);
this.ids = new int[16][];
this.count = new short[16];
this.air = new short[16];
@ -35,15 +33,14 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
@Override
public Chunk getChunk() {
if (this.chunk == null) {
final ChunkLoc cl = this.getChunkLoc();
this.chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z);
this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
}
return this.chunk;
}
@Override
public void setChunkLoc(final ChunkLoc loc) {
super.setChunkLoc(loc);
public void setLoc(final FaweQueue parent, int x, int z) {
super.setLoc(parent, x, z);
this.chunk = null;
}

View File

@ -4,7 +4,6 @@ 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;
import com.boydti.fawe.object.IntegerPair;
@ -64,12 +63,15 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
private final RefField fieldWorld;
private final RefMethod methodGetBlocks;
private final RefMethod methodSetType;
private final RefMethod methodGetType;
private final RefMethod methodGetByCombinedId;
private final RefMethod methodGetCombinedId;
private final Object air;
private final RefMethod methodGetWorld;
private final RefField tileEntityListTick;
public BukkitQueue_1_9() throws NoSuchMethodException, RuntimeException {
public BukkitQueue_1_9(String world) throws NoSuchMethodException, RuntimeException {
super(world);
this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle");
this.methodInitLighting = this.classChunk.getMethod("initLighting");
this.classBlockPositionConstructor = this.classBlockPosition.getConstructor(int.class, int.class, int.class);
@ -79,10 +81,12 @@ 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.methodGetType = this.classChunk.getMethod("a", int.class, int.class, 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");
this.methodGetWorld = this.classChunk.getMethod("getWorld");
this.methodGetCombinedId = classBlock.getMethod("getCombinedId", classIBlockData.getRealClass());
}
@Override
@ -92,12 +96,11 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
}
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);
chunk.getWorld().refreshChunk(fc.getX(), fc.getZ());
}
@Override
@ -187,10 +190,10 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
public boolean isSurrounded(final int[][] sections, final int x, final int y, final int z) {
return this.isSolid(this.getId(sections, x, y + 1, z))
&& this.isSolid(this.getId(sections, x + 1, y - 1, z))
&& this.isSolid(this.getId(sections, x - 1, y, z))
&& this.isSolid(this.getId(sections, x, y, z + 1))
&& this.isSolid(this.getId(sections, x, y, z - 1));
&& this.isSolid(this.getId(sections, x + 1, y - 1, z))
&& this.isSolid(this.getId(sections, x - 1, y, z))
&& this.isSolid(this.getId(sections, x, y, z + 1))
&& this.isSolid(this.getId(sections, x, y, z - 1));
}
public boolean isSolid(final int i) {
@ -221,6 +224,35 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
return this.methodGetBlocks.of(obj).call();
}
private int lcx = Integer.MIN_VALUE;
private int lcz = Integer.MIN_VALUE;
private int lcy = Integer.MIN_VALUE;
private RefExecutor lc;
private World bukkitWorld;
@Override
public int getCombinedId4Data(int x, int y, int z) {
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;
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;
@ -302,7 +334,7 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
final int combined = newArray[i];
final int id = combined & 4095;
final int data = combined >> 12;
array[i] = (char) ((id << 4) + data);
array[i] = (char) ((id << 4) + data);
}
section = sections[j] = this.newChunkSection(j << 4, flag, array);
continue;
@ -481,8 +513,8 @@ public class BukkitQueue_1_9 extends BukkitQueue_0 {
}
@Override
public FaweChunk<Chunk> getChunk(final ChunkLoc wrap) {
return new BukkitChunk_1_9(wrap);
public FaweChunk<Chunk> getChunk(int x, int z) {
return new BukkitChunk_1_9(this, x, z);
}
public boolean unloadChunk(final String world, final Chunk chunk) {

View File

@ -11,7 +11,6 @@ import com.boydti.fawe.regions.general.PlotSquaredFeature;
import com.boydti.fawe.util.Lag;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.WEManager;
import com.boydti.fawe.util.WESubscriber;
@ -153,8 +152,7 @@ public class Fawe {
if (Settings.METRICS) {
this.IMP.startMetrics();
}
SetQueue.IMP.queue = this.IMP.getQueue();
// Delete old history
MainUtil.deleteDirectory(new File(IMP.getDirectory(), "history"));

View File

@ -1,5 +1,14 @@
package com.boydti.fawe;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.Tag;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -9,23 +18,10 @@ import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.world.biome.BaseBiome;
/**
* The FaweAPI class offers a few useful functions.<br>
* - This class is not intended to replace the WorldEdit API<br>
@ -68,77 +64,69 @@ public class FaweAPI {
SetQueue.IMP.setBlock(world, x, y, z, id, data);
}
/**
* Set a biome at a location asynchronously
* @param world
* @param x
* @param z
* @param id
* @param data
*/
public static void setBiomeAsync(final String world, final int x, final int z, final BaseBiome biome) {
SetQueue.IMP.setBiome(world, x, z, biome);
// /**
// * Set a biome at a location asynchronously
// * @param world
// * @param x
// * @param z
// * @param id
// * @param data
// */
// public static void setBiomeAsync(final String world, final int x, final int z, final BaseBiome biome) {
// SetQueue.IMP.setBiome(world, x, z, biome);
// }
//
// /**
// * Set a biome at a location asynchronously
// * @param loc
// * @param biome
// */
// public static void setBiomeAsync(final Location loc, final BaseBiome biome) {
// SetQueue.IMP.setBiome(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockZ(), biome);
// }
//
// /**
// * This will return a FaweChunk object that can be modified.<br>
// * - The FaweChunk object can be reused if you want identical changes across chunks<br>
// * - This is additive modification.<br>
// * - First use {@link FaweChunk#fill(int, byte)} (e.g. with air) for absolute modification<br>
// * When ready, use {@link #setChunk(FaweChunk, ChunkLoc)}
// * @return
// */
// public static FaweChunk<?> createChunk() {
// return SetQueue.IMP.queue.getChunk(new ChunkLoc(null, 0, 0));
// }
//
// /**
// * @see #createChunk()
// * @param data
// * @param location
// */
// public static void setChunkAsync(final FaweChunk<?> data, final ChunkLoc location) {
// data.setChunkLoc(location);
// data.addToQueue();
// }
//
// /**
// * @see #createChunk()
// * @param data
// * @param chunk
// */
// public static void setChunkAsync(final FaweChunk<?> data, final Chunk chunk) {
// final ChunkLoc loc = new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
// data.setChunkLoc(loc);
// data.addToQueue();
// }
//
public static void fixLighting(String world, int x, int z, final boolean fixAll) {
FaweQueue queue = SetQueue.IMP.getQueue(world);
queue.fixLighting(queue.getChunk(x, z), fixAll);
}
/**
* Set a biome at a location asynchronously
* @param loc
* @param biome
*/
public static void setBiomeAsync(final Location loc, final BaseBiome biome) {
SetQueue.IMP.setBiome(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockZ(), biome);
}
/**
* This will return a FaweChunk object that can be modified.<br>
* - The FaweChunk object can be reused if you want identical changes across chunks<br>
* - This is additive modification.<br>
* - First use {@link FaweChunk#fill(int, byte)} (e.g. with air) for absolute modification<br>
* When ready, use {@link #setChunk(FaweChunk, ChunkLoc)}
* @return
*/
public static FaweChunk<?> createChunk() {
return SetQueue.IMP.queue.getChunk(new ChunkLoc(null, 0, 0));
}
/**
* @see #createChunk()
* @param data
* @param location
*/
public static void setChunkAsync(final FaweChunk<?> data, final ChunkLoc location) {
data.setChunkLoc(location);
data.addToQueue();
}
/**
* @see #createChunk()
* @param data
* @param chunk
*/
public static void setChunkAsync(final FaweChunk<?> data, final Chunk chunk) {
final ChunkLoc loc = new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
data.setChunkLoc(loc);
data.addToQueue();
}
/**
* Fix the lighting at a chunk location.<br>
* - The fixAll parameter determines if extensive relighting should occur (slow)
* @param loc
*/
public static void fixLighting(final ChunkLoc loc, final boolean fixAll) {
SetQueue.IMP.queue.fixLighting(SetQueue.IMP.queue.getChunk(loc), fixAll);
}
/**
* Fix the lighting at a chunk.<br>
* - The fixAll parameter determines if extensive relighting should occur (slow)
* @param chunk
*/
public static void fixLighting(final Chunk chunk, final boolean fixAll) {
final ChunkLoc loc = new ChunkLoc(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
SetQueue.IMP.queue.fixLighting(SetQueue.IMP.queue.getChunk(loc), fixAll);
FaweQueue queue = SetQueue.IMP.getQueue(chunk.getWorld().getName());
queue.fixLighting(queue.getChunk(chunk.getX(), chunk.getZ()), fixAll);
}
/**

View File

@ -28,7 +28,7 @@ public interface IFawe {
public int[] getVersion();
public FaweQueue getQueue();
public FaweQueue getNewQueue(String world);
public EditSessionWrapper getEditSessionWrapper(final EditSession session);

View File

@ -3,7 +3,6 @@ package com.boydti.fawe.command;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
@ -24,7 +23,7 @@ public class FixLighting extends FaweCommand {
final FaweLocation loc = player.getLocation();
final Region selection = player.getSelection();
if (selection == null) {
FaweAPI.fixLighting(new ChunkLoc(loc.world, loc.x >> 4, loc.z >> 4), Settings.FIX_ALL_LIGHTING);
FaweAPI.fixLighting(loc.world, loc.x >> 4, loc.z >> 4, Settings.FIX_ALL_LIGHTING);
BBC.FIX_LIGHTING_CHUNK.send(player);
return true;
}
@ -42,8 +41,7 @@ public class FixLighting extends FaweCommand {
int count = 0;
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
final ChunkLoc cl = new ChunkLoc(loc.world, x, z);
FaweAPI.fixLighting(cl, Settings.FIX_ALL_LIGHTING);
FaweAPI.fixLighting(loc.world, x, z, Settings.FIX_ALL_LIGHTING);
count++;
}
}

View File

@ -1,56 +0,0 @@
package com.boydti.fawe.object;
public class ChunkLoc {
public final int x;
public final int z;
public final String world;
public ChunkLoc(final String world, final int x, final int z) {
this.world = world;
this.x = x;
this.z = z;
}
@Override
public int hashCode() {
int result;
if (this.x >= 0) {
if (this.z >= 0) {
result = (this.x * this.x) + (3 * this.x) + (2 * this.x * this.z) + this.z + (this.z * this.z);
} else {
final int y1 = -this.z;
result = (this.x * this.x) + (3 * this.x) + (2 * this.x * y1) + y1 + (y1 * y1) + 1;
}
} else {
final int x1 = -this.x;
if (this.z >= 0) {
result = -((x1 * x1) + (3 * x1) + (2 * x1 * this.z) + this.z + (this.z * this.z));
} else {
final int y1 = -this.z;
result = -((x1 * x1) + (3 * x1) + (2 * x1 * y1) + y1 + (y1 * y1) + 1);
}
}
result = (result * 31) + this.world.hashCode();
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final ChunkLoc other = (ChunkLoc) obj;
return ((this.x == other.x) && (this.z == other.z) && (this.world.equals(other.world)));
}
@Override
public String toString() {
return this.world + ":" + this.x + "," + this.z;
}
}

View File

@ -27,6 +27,6 @@ public class EditSessionWrapper {
}
public Extent getHistoryExtent(final Extent parent, FaweChangeSet set, final FawePlayer<?> player) {
return new HistoryExtent(parent, set);
return new HistoryExtent(player.getLocation().world, parent, set);
}
}

View File

@ -1,41 +1,59 @@
package com.boydti.fawe.object;
import java.util.ArrayDeque;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.FaweQueue;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayDeque;
public abstract class FaweChunk<T> {
private ChunkLoc chunk;
private FaweQueue parent;
private int x,z;
private final ArrayDeque<Runnable> tasks = new ArrayDeque<Runnable>();
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*/
public FaweChunk(final ChunkLoc chunk) {
this.chunk = chunk;
public FaweChunk(FaweQueue parent, int x, int z) {
this.parent = parent;
this.x = x;
this.z = z;
}
public void setChunkLoc(final ChunkLoc loc) {
this.chunk = loc;
public void setLoc(FaweQueue parent, int x, int z) {
this.parent = parent;
this.x = x;
this.z = z;
}
public ChunkLoc getChunkLoc() {
return this.chunk;
public FaweQueue getParent() {
return parent;
}
public void addToQueue() {
if (this.chunk == null) {
throw new IllegalArgumentException("Chunk location cannot be null!");
}
SetQueue.IMP.queue.setChunk(this);
public int getX() {
return x;
}
public int getZ() {
return z;
}
public long longHash() {
return (long) x << 32 | z & 0xFFFFFFFFL;
}
@Override
public int hashCode() {
return x << 16 | z & 0xFFFF;
}
public void addToQueue(String world) {
parent.setChunk(this);
}
public void fixLighting() {
SetQueue.IMP.queue.fixLighting(this, Settings.FIX_ALL_LIGHTING);
parent.fixLighting(this, Settings.FIX_ALL_LIGHTING);
}
public void fill(final int id, final byte data) {
@ -67,16 +85,11 @@ public abstract class FaweChunk<T> {
public abstract void setBiome(final int x, final int z, final BaseBiome biome);
@Override
public int hashCode() {
return this.chunk.hashCode();
}
@Override
public boolean equals(final Object obj) {
if ((obj == null) || !(obj instanceof FaweChunk)) {
if ((obj == null) || obj.hashCode() != hashCode() || !(obj instanceof FaweChunk)) {
return false;
}
return this.chunk.equals(((FaweChunk) obj).chunk);
return longHash() != ((FaweChunk) obj).longHash();
}
}

View File

@ -2,6 +2,8 @@ package com.boydti.fawe.object;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
@ -27,6 +29,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class HistoryExtent extends AbstractDelegateExtent {
private final com.boydti.fawe.object.changeset.FaweChangeSet changeSet;
private final FaweQueue queue;
/**
* Create a new instance.
@ -34,33 +37,39 @@ public class HistoryExtent extends AbstractDelegateExtent {
* @param extent the extent
* @param changeSet the change set
*/
public HistoryExtent(final Extent extent, final FaweChangeSet changeSet) {
public HistoryExtent(final String world, final Extent extent, final FaweChangeSet changeSet) {
super(extent);
this.queue = SetQueue.IMP.getQueue(world);
checkNotNull(changeSet);
this.changeSet = changeSet;
}
@Override
public synchronized boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
if (super.setBlock(location, block)) {
BaseBlock previous;
try {
previous = this.getBlock(location);
} catch (final Exception e) {
previous = this.getBlock(location);
}
final int id_p = previous.getId();
final int id_b = block.getId();
if (id_p == id_b) {
if (FaweCache.hasData(id_p)) {
if (previous.getData() == block.getData()) {
return false;
}
} else {
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
int combined = queue.getCombinedId4Data(x, y, z);
int id = (combined >> 4);
if (id == block.getId()) {
if (!FaweCache.hasData(id)) {
return false;
}
int data = id & 0xF;
if (data == block.getData()) {
return false;
}
}
this.changeSet.add(location, previous, block);
if (!FaweCache.hasNBT(id)) {
if (FaweCache.hasNBT(block.getId())) {
this.changeSet.add(x, y, z, combined, block);
} else {
this.changeSet.add(x, y, z, combined, (block.getId() << 4) + block.getData());
}
} else {
this.changeSet.add(location, getBlock(location), block);
}
return true;
}
return false;

View File

@ -32,4 +32,10 @@ public class NullChangeSet implements FaweChangeSet {
@Override
public void add(Vector location, BaseBlock from, BaseBlock to) {}
@Override
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {}
@Override
public void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo) {}
}

View File

@ -1,10 +0,0 @@
package com.boydti.fawe.object;
import java.util.Collection;
public abstract class SendChunk {
public abstract void fixLighting(final Collection<ChunkLoc> locs);
public abstract void update(final Collection<ChunkLoc> locs);
}

View File

@ -138,19 +138,8 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
}
@Override
public void add(Vector location, BaseBlock from, BaseBlock to) {
add(location.getBlockX(), location.getBlockY(), location.getBlockZ(), from, to);
}
public void add(int x, int y, int z, BaseBlock from, BaseBlock to) {
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
try {
int idfrom = from.getId();
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
int idTo = to.getId();
int combinedTo = (FaweCache.hasData(idTo) ? ((idTo << 4) + to.getData()) : (idTo << 4));
CompoundTag nbtTo = FaweCache.hasNBT(idTo) ? to.getNbtData() : null;
OutputStream stream = getBAOS(x, y, z);
//x
stream.write((x - ox) & 0xff);
@ -166,6 +155,41 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
//to
stream.write((combinedTo) & 0xff);
stream.write(((combinedTo) >> 8) & 0xff);
}
catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {
int idTo = to.getId();
int combinedTo = (FaweCache.hasData(idTo) ? ((idTo << 4) + to.getData()) : (idTo << 4));
CompoundTag nbtTo = FaweCache.hasNBT(idTo) ? to.getNbtData() : null;
add(x, y, z, combinedId4DataFrom, combinedTo);
if (nbtTo != null && MainUtil.isValidTag(nbtTo)) {
try {
Map<String, Tag> value = ReflectionUtils.getMap(nbtTo.getValue());
value.put("x", new IntTag(x));
value.put("y", new IntTag(y));
value.put("z", new IntTag(z));
NBTOutputStream nbtos = getNBTTOS(x, y, z);
nbtos.writeNamedTag(osNBTTI.getAndIncrement() + "", nbtTo);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void add(Vector loc, BaseBlock from, BaseBlock to) {
int x = loc.getBlockX();
int y = loc.getBlockY();
int z = loc.getBlockZ();
try {
int idfrom = from.getId();
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
if (nbtFrom != null && MainUtil.isValidTag(nbtFrom)) {
Map<String, Tag> value = ReflectionUtils.getMap(nbtFrom.getValue());
@ -175,15 +199,8 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
NBTOutputStream nbtos = getNBTFOS(x, y, z);
nbtos.writeNamedTag(osNBTFI.getAndIncrement() + "", nbtFrom);
}
add(x, y, z, combinedFrom, to);
if (nbtTo != null && MainUtil.isValidTag(nbtTo)) {
Map<String, Tag> value = ReflectionUtils.getMap(nbtTo.getValue());
value.put("x", new IntTag(x));
value.put("y", new IntTag(y));
value.put("z", new IntTag(z));
NBTOutputStream nbtos = getNBTTOS(x, y, z);
nbtos.writeNamedTag(osNBTTI.getAndIncrement() + "", nbtTo);
}
} catch (Exception e) {
e.printStackTrace();
}
@ -200,12 +217,9 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
public void add(BlockChange change) {
try {
BlockVector loc = change.getPosition();
int x = loc.getBlockX();
int y = loc.getBlockY();
int z = loc.getBlockZ();
BaseBlock from = change.getPrevious();
BaseBlock to = change.getCurrent();
add(x, y, z, from, to);
add(loc, from, to);
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -8,4 +8,8 @@ public interface FaweChangeSet extends ChangeSet {
void flush();
void add(Vector location, BaseBlock from, BaseBlock to);
void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to);
void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo);
}

View File

@ -54,20 +54,10 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
size = new AtomicInteger();
}
@Override
public void add(Vector location, BaseBlock from, BaseBlock to) {
add(location.getBlockX(), location.getBlockY(), location.getBlockZ(), from, to);
}
public void add(int x, int y, int z, BaseBlock from, BaseBlock to) {
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
try {
int idfrom = from.getId();
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
int idTo = to.getId();
int combinedTo = (FaweCache.hasData(idTo) ? ((idTo << 4) + to.getData()) : (idTo << 4));
CompoundTag nbtTo = FaweCache.hasNBT(idTo) ? to.getNbtData() : null;
OutputStream stream = getBAOS(x, y, z);
//x
stream.write((x - ox) & 0xff);
@ -83,7 +73,39 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
//to
stream.write((combinedTo) & 0xff);
stream.write(((combinedTo) >> 8) & 0xff);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {
int idTo = to.getId();
int combinedTo = (FaweCache.hasData(idTo) ? ((idTo << 4) + to.getData()) : (idTo << 4));
CompoundTag nbtTo = FaweCache.hasNBT(idTo) ? to.getNbtData() : null;
add(x, y, z, combinedId4DataFrom, combinedTo);
if (nbtTo != null && MainUtil.isValidTag(nbtTo)) {
Map<String, Tag> value = ReflectionUtils.getMap(nbtTo.getValue());
value.put("x", new IntTag(x));
value.put("y", new IntTag(y));
value.put("z", new IntTag(z));
if (toTags == null) {
toTags = new ArrayDeque<>();
}
toTags.add(nbtTo);
}
}
@Override
public void add(Vector loc, BaseBlock from, BaseBlock to) {
try {
int x = loc.getBlockX();
int y = loc.getBlockY();
int z = loc.getBlockZ();
int idfrom = from.getId();
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
if (nbtFrom != null && MainUtil.isValidTag(nbtFrom)) {
Map<String, Tag> value = ReflectionUtils.getMap(nbtFrom.getValue());
value.put("x", new IntTag(x));
@ -94,17 +116,7 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
}
fromTags.add(nbtFrom);
}
if (nbtTo != null && MainUtil.isValidTag(nbtTo)) {
Map<String, Tag> value = ReflectionUtils.getMap(nbtTo.getValue());
value.put("x", new IntTag(x));
value.put("y", new IntTag(y));
value.put("z", new IntTag(z));
if (toTags == null) {
toTags = new ArrayDeque<>();
}
toTags.add(nbtTo);
}
add(x, y, z, combinedFrom, to);
} catch (Exception e) {
e.printStackTrace();
}
@ -116,12 +128,9 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
if ((arg instanceof BlockChange)) {
BlockChange change = (BlockChange) arg;
BlockVector loc = change.getPosition();
int x = loc.getBlockX();
int y = loc.getBlockY();
int z = loc.getBlockZ();
BaseBlock from = change.getPrevious();
BaseBlock to = change.getCurrent();
add(x, y, z, from, to);
add(loc, from, to);
} else {
if (entities == null) {
entities = new ArrayDeque<>();

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.extent;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.BlockVector;
@ -20,13 +21,13 @@ import java.util.List;
public class FastWorldEditExtent extends AbstractDelegateExtent {
private final String world;
private final Thread thread;
private final FaweQueue queue;
public FastWorldEditExtent(final World world, final Thread thread) {
super(world);
this.thread = thread;
this.world = world.getName();
this.queue = SetQueue.IMP.getQueue(world.getName());
}
@Override
@ -42,7 +43,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
@Override
public BaseBiome getBiome(final Vector2D position) {
if (!SetQueue.IMP.isChunkLoaded(this.world, position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
return EditSession.nullBiome;
}
synchronized (this.thread) {
@ -58,7 +59,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
if ((this.lastBlock != null) && this.lastVector.equals(position.toBlockVector())) {
return this.lastBlock;
}
if (!SetQueue.IMP.isChunkLoaded(this.world, position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
try {
this.lastVector = position.toBlockVector();
return this.lastBlock = super.getBlock(position);
@ -93,7 +94,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
@Override
public boolean setBiome(final Vector2D position, final BaseBiome biome) {
SetQueue.IMP.setBiome(this.world, position.getBlockX(), position.getBlockZ(), biome);
queue.setBiome(position.getBlockX(), position.getBlockZ(), biome);
return true;
}
@ -141,7 +142,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
case 151:
case 178: {
if (block.hasNbtData()) {
SetQueue.IMP.addTask(this.world, x, y, z, new Runnable() {
queue.addTask(x >> 4, z >> 4, new Runnable() {
@Override
public void run() {
try {
@ -153,7 +154,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
});
return true;
}
SetQueue.IMP.setBlock(this.world, x, y, z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
queue.setBlock(x, y, z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
return true;
}
case 0:
@ -222,11 +223,11 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
case 190:
case 191:
case 192: {
SetQueue.IMP.setBlock(this.world, x, y, z, id);
queue.setBlock(x, y, z, id, (byte) 0);
return true;
}
default: {
SetQueue.IMP.setBlock(this.world, x, y, z, id, (byte) block.getData());
queue.setBlock(x, y, z, id, (byte) block.getData());
return true;
}
}

View File

@ -1,13 +1,11 @@
package com.boydti.fawe.object.extent;
import com.boydti.fawe.FaweCache;
import java.util.HashSet;
import java.util.List;
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.util.FaweQueue;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
@ -26,8 +24,11 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.HashSet;
import java.util.List;
public class ProcessedWEExtent extends AbstractDelegateExtent {
private final FaweQueue queue;
private Extent parent;
private boolean BSblocked = false;
@ -38,14 +39,13 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
private int max;
private final FawePlayer<?> user;
private final String world;
private final HashSet<RegionWrapper> mask;
private final Thread thread;
public ProcessedWEExtent(final World world, final Thread thread, final FawePlayer<?> player, final HashSet<RegionWrapper> mask, final int max) {
super(world);
this.user = player;
this.world = world.getName();
this.queue = SetQueue.IMP.getQueue(world.getName());
this.max = max != -1 ? max : Integer.MAX_VALUE;
this.mask = mask;
this.thread = thread;
@ -67,7 +67,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
this.Ecount++;
if (this.Ecount > Settings.MAX_ENTITIES) {
this.Eblocked = true;
MainUtil.sendAdmin(BBC.WORLDEDIT_DANGEROUS_WORLDEDIT.format(this.world + ": " + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ(), this.user));
MainUtil.sendAdmin(BBC.WORLDEDIT_DANGEROUS_WORLDEDIT.format(queue.world + ": " + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ(), this.user));
}
if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) {
TaskManager.IMP.task(new Runnable() {
@ -82,7 +82,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
@Override
public BaseBiome getBiome(final Vector2D position) {
if (!SetQueue.IMP.isChunkLoaded(this.world, position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
return EditSession.nullBiome;
}
synchronized (this.thread) {
@ -98,7 +98,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
if ((this.lastBlock != null) && this.lastVector.equals(position.toBlockVector())) {
return this.lastBlock;
}
if (!SetQueue.IMP.isChunkLoaded(this.world, position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
try {
this.lastVector = position.toBlockVector();
return this.lastBlock = super.getBlock(position);
@ -177,7 +177,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
this.BScount++;
if (this.BScount > Settings.MAX_BLOCKSTATES) {
this.BSblocked = true;
MainUtil.sendAdmin(BBC.WORLDEDIT_DANGEROUS_WORLDEDIT.format(this.world + ": " + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ(), this.user));
MainUtil.sendAdmin(BBC.WORLDEDIT_DANGEROUS_WORLDEDIT.format(queue.world + ": " + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ(), this.user));
}
final int x = location.getBlockX();
final int z = location.getBlockZ();
@ -190,7 +190,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
return false;
}
if (block.hasNbtData()) {
SetQueue.IMP.addTask(this.world, x, location.getBlockY(), z, new Runnable() {
queue.addTask(x >> 4, z >> 4, new Runnable() {
@Override
public void run() {
try {
@ -202,7 +202,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
});
return true;
}
SetQueue.IMP.setBlock(this.world, x, location.getBlockY(), z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
queue.setBlock(x, location.getBlockY(), z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
return true;
}
return false;
@ -298,11 +298,11 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
case 190:
case 191:
case 192: {
SetQueue.IMP.setBlock(this.world, x, y, z, id);
queue.setBlock(x, y, z, id, (byte) 0);
return true;
}
default: {
SetQueue.IMP.setBlock(this.world, x, y, z, id, (byte) block.getData());
queue.setBlock(x, y, z, id, (byte) block.getData());
return true;
}
}
@ -315,7 +315,7 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
@Override
public boolean setBiome(final Vector2D position, final BaseBiome biome) {
if (WEManager.IMP.maskContains(this.mask, position.getBlockX(), position.getBlockZ())) {
SetQueue.IMP.setBiome(this.world, position.getBlockX(), position.getBlockZ(), biome);
queue.setBiome(position.getBlockX(), position.getBlockZ(), biome);
}
return false;
}

View File

@ -2,23 +2,28 @@ package com.boydti.fawe.util;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.ChunkLoc;
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 final String world;
public abstract boolean setBiome(final String world, final int x, final int z, final BaseBiome biome);
public FaweQueue(String world) {
this.world = world;
}
public abstract FaweChunk<?> getChunk(final ChunkLoc wrap);
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);
public abstract FaweChunk<?> getChunk(int x, int z);
public abstract void setChunk(final FaweChunk<?> chunk);
public abstract boolean fixLighting(final FaweChunk<?> chunk, final boolean fixAll);
public abstract boolean isChunkLoaded(final String world, final int x, final int z);
public abstract boolean isChunkLoaded(final int x, final int z);
/**
* Gets the FaweChunk and sets the requested blocks
@ -31,7 +36,7 @@ public abstract class FaweQueue {
// Set memory limited
MemUtil.memoryLimitedTask();
// Clear block placement
SetQueue.IMP.queue.clear();
clear();
Fawe.get().getWorldEdit().clearSessions();
// GC
System.gc();
@ -44,5 +49,7 @@ public abstract class FaweQueue {
*/
protected abstract void clear();
public abstract void addTask(String world, int x, int y, int z, Runnable runnable);
public abstract void addTask(int x, int z, Runnable runnable);
public abstract int getCombinedId4Data(int x, int y, int z);
}

View File

@ -1,11 +1,15 @@
package com.boydti.fawe.util;
import java.util.ArrayDeque;
import java.util.concurrent.atomic.AtomicInteger;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class SetQueue {
@ -14,7 +18,7 @@ public class SetQueue {
*/
public static final SetQueue IMP = new SetQueue();
public FaweQueue queue;
public final Map<String, FaweQueue> queues;
/**
* Track the time in ticks
@ -35,6 +39,7 @@ public class SetQueue {
public SetQueue() {
queues = new ConcurrentHashMap<>();
TaskManager.IMP.repeat(new Runnable() {
@Override
public void run() {
@ -42,7 +47,9 @@ public class SetQueue {
final int mem = MemUtil.calculateMemory();
if (mem != Integer.MAX_VALUE) {
if ((mem <= 1) && Settings.ENABLE_HARD_LIMIT) {
SetQueue.this.queue.saveMemory();
for (FaweQueue queue : getQueues()) {
queue.saveMemory();
}
return;
}
if (SetQueue.this.forceChunkSet()) {
@ -60,7 +67,7 @@ public class SetQueue {
if (SetQueue.this.isWaiting()) {
return;
}
final FaweChunk<?> current = SetQueue.this.queue.next();
final FaweChunk<?> current = next();
if (current == null) {
SetQueue.this.time_waiting.set(Math.max(SetQueue.this.time_waiting.get(), SetQueue.this.time_current.get() - 2));
SetQueue.this.tasks();
@ -72,9 +79,42 @@ public class SetQueue {
}, 1);
}
public List<FaweQueue> getQueues() {
List<FaweQueue> list = new ArrayList<>(queues.size());
try {
for (Map.Entry<String, FaweQueue> entry : queues.entrySet()) {
list.add(entry.getValue());
}
}
catch (Exception e) {
e.printStackTrace();
}
return list;
}
public FaweQueue getQueue(String world) {
FaweQueue queue = queues.get(world);
if (queue != null) {
return queue;
}
queue = Fawe.imp().getNewQueue(world);
queues.put(world, queue);
return queue;
}
public FaweChunk<?> next() {
for (Map.Entry<String, FaweQueue> entry : queues.entrySet()) {
FaweQueue queue = entry.getValue();
final FaweChunk<?> set = queue.next();
if (set != null ) {
return set;
}
}
return null;
}
public boolean forceChunkSet() {
final FaweChunk<?> set = this.queue.next();
return set != null;
return next() != null;
}
public boolean isWaiting() {
@ -125,9 +165,10 @@ public class SetQueue {
* @param data
* @return
*/
@Deprecated
public boolean setBlock(final String world, final int x, final int y, final int z, final short id, final byte data) {
SetQueue.IMP.setWaiting();
return this.queue.setBlock(world, x, y, z, id, data);
return getQueue(world).setBlock(x, y, z, id, data);
}
/**
@ -138,27 +179,28 @@ public class SetQueue {
* @param id
* @return
*/
@Deprecated
public boolean setBlock(final String world, final int x, final int y, final int z, final short id) {
SetQueue.IMP.setWaiting();
return this.queue.setBlock(world, x, y, z, id, (byte) 0);
return getQueue(world).setBlock(x, y, z, id, (byte) 0);
}
/**
* @param world
* @param x
* @param y
* @param z
* @param id
* @param data
* @param biome
* @return
*/
@Deprecated
public boolean setBiome(final String world, final int x, final int z, final BaseBiome biome) {
SetQueue.IMP.setWaiting();
return this.queue.setBiome(world, x, z, biome);
return getQueue(world).setBiome(x, z, biome);
}
@Deprecated
public boolean isChunkLoaded(final String world, final int x, final int z) {
return this.queue.isChunkLoaded(world, x, z);
return getQueue(world).isChunkLoaded(x, z);
}
/**
@ -170,7 +212,8 @@ public class SetQueue {
* @param z
* @param runnable
*/
@Deprecated
public void addTask(String world, int x, int y, int z, Runnable runnable) {
this.queue.addTask(world, x, y, z, runnable);
getQueue(world).addTask(x >> 4, z >> 4, runnable);
}
}

View File

@ -314,7 +314,6 @@ public class EditSession implements Extent {
// Include history, masking and memory checking.
Extent wrapped;
extent = wrapped = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE);
extent = this.reorderExtent = new MultiStageReorder(extent, false);
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
extent = this.changeSetExtent = this.wrapper.getHistoryExtent(extent, this.changeSet, fp);
final Player skp = (Player) actor;
@ -335,7 +334,7 @@ public class EditSession implements Extent {
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY);
extent = new SafeExtentWrapper(fp, extent);
this.bypassReorderHistory = wrapped;
this.bypassHistory = this.reorderExtent;
this.bypassHistory = wrapped;
this.bypassNone = extent;
return;
}

View File

@ -9,62 +9,28 @@
#################################################
Version string 'unspecified' does not match SemVer specification
You should try SemVer : http://semver.org/
Cookie rejected [JSESSIONID="26E6D52C45F2EEB46889F1A779E2FC24", version:0, domain:maven.sk89q.com, path:/artifactory/, expiry:null] Illegal 'path' attribute "/artifactory/". Path of origin: "/repo/org/spongepowered/spongeapi/"
Download http://repo.spongepowered.org/maven/org/spongepowered/spongeapi/4.1.0-SNAPSHOT/spongeapi-4.1.0-20160402.223304-15.jar
:core:compileJava
:bukkit:processResources
:forge:deobfCompileDummyTask
:forge:deobfProvidedDummyTask
:forge:extractDependencyATs SKIPPED
:forge:extractMcpData
:bukkit:processTestResources UP-TO-DATE
warning: [options] bootstrap class path not set in conjunction with -source 1.7
:core:compileJava UP-TO-DATE
:core:processResources UP-TO-DATE
:core:classes UP-TO-DATE
:core:jar UP-TO-DATE
:forge:extractMcpData SKIPPED
:forge:extractMcpMappings SKIPPED
:forge:genSrgs SKIPPED
:forge:getVersionJson
:forge:downloadServer SKIPPED
:forge:splitServerJarNote: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 warning
:core:processResources UP-TO-DATE
:core:classes
:core:jar
:bukkit:compileJava
:core:assemble
:core:compileTestJava UP-TO-DATE
:core:processTestResources UP-TO-DATE
:core:testClasses UP-TO-DATE
:core:test UP-TO-DATE
:core:check UP-TO-DATE
:core:build
warning: [options] bootstrap class path not set in conjunction with -source 1.7
:forge:splitServerJar SKIPPED
:forge:deobfMcMCP SKIPPED
:forge:sourceApiJava UP-TO-DATE
:forge:compileApiJava UP-TO-DATE
:forge:processApiResources UP-TO-DATE
:forge:apiClasses UP-TO-DATE
:forge:sourceMainJava
:forge:compileJavaNote: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 warning
:bukkit:classes
:bukkit:jar SKIPPED
:bukkit:assemble UP-TO-DATE
:bukkit:compileTestJava UP-TO-DATE
:bukkit:testClasses UP-TO-DATE
:bukkit:test UP-TO-DATE
:bukkit:check UP-TO-DATE
:bukkit:shadowJar
:bukkit:build
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'modid()' in type 'Mod': class file for net.minecraftforge.fml.common.Mod not found
:forge:sourceMainJava UP-TO-DATE
:forge:compileJavaC:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'modid()' in type 'Mod': class file for net.minecraftforge.fml.common.Mod not found
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'name()' in type 'Mod'
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'version()' in type 'Mod'
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'acceptableRemoteVersions()' in type 'Mod'
@ -97,6 +63,7 @@ Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
27 warnings
:forge:processResources UP-TO-DATE
:forge:classes
:forge:jar
@ -110,13 +77,12 @@ Note: Recompile with -Xlint:unchecked for details.
:forge:reobfShadowJar
:forge:extractRangemapReplacedMain
C:\Users\Jesse\Desktop\OTHER\GitHub\FastAsyncWorldEdit\forge\build\sources\main\java
:forge:retromapReplacedMain
remapping source...
:forge:sourceJar
:forge:retromapReplacedMain UP-TO-DATE
:forge:sourceJar UP-TO-DATE
:forge:assemble
:forge:check UP-TO-DATE
:forge:build
BUILD SUCCESSFUL
Total time: 1 mins 21.422 secs
Total time: 36.184 secs

View File

@ -112,8 +112,8 @@ public class FaweSponge implements IFawe {
}
@Override
public FaweQueue getQueue() {
return new SpongeQueue_1_8();
public FaweQueue getNewQueue(String world) {
return new SpongeQueue_1_8(world);
}
@Override

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.forge.v0;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.SetQueue;
@ -22,70 +21,70 @@ public abstract class SpongeQueue_0 extends FaweQueue {
/**
* Map of chunks in the queue
*/
private final ConcurrentHashMap<ChunkLoc, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
public SpongeQueue_0(String world) {
super(world);
}
@Override
public boolean isChunkLoaded(String worldName, int x, int z) {
World world = Sponge.getServer().getWorld(worldName).get();
public boolean isChunkLoaded(int x, int z) {
World world = Sponge.getServer().getWorld(this.world).get();
Chunk chunk = world.getChunk(x << 4, 0, z << 4).orElse(null);
return chunk != null && chunk.isLoaded();
}
@Override
public void addTask(String world, int x, int y, int z, Runnable runnable) {
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
FaweChunk<Chunk> result = this.blocks.get(wrap);
public void addTask(int x, int z, Runnable runnable) {
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
FaweChunk<Chunk> result = this.blocks.get(pair);
if (result == null) {
result = this.getChunk(wrap);
result = this.getChunk(x, z);
result.addTask(runnable);
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
final FaweChunk<Chunk> previous = this.blocks.put(pair, result);
if (previous == null) {
return;
}
this.blocks.put(wrap, previous);
this.blocks.put(pair, previous);
result = previous;
}
result.addTask(runnable);
}
@Override
public boolean setBlock(final String world, int x, final int y, int z, final short id, final byte data) {
public boolean setBlock(int x, final int y, int z, final short id, final byte data) {
if ((y > 255) || (y < 0)) {
return false;
}
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
x = x & 15;
z = z & 15;
FaweChunk<Chunk> result = this.blocks.get(wrap);
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
FaweChunk<Chunk> result = this.blocks.get(pair);
if (result == null) {
result = this.getChunk(wrap);
result.setBlock(x, y, z, id, data);
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
result = this.getChunk(x >> 4, z >> 4);
result.setBlock(x & 15, y, z & 15, id, data);
final FaweChunk<Chunk> previous = this.blocks.put(pair, result);
if (previous == null) {
return true;
}
this.blocks.put(wrap, previous);
this.blocks.put(pair, previous);
result = previous;
}
result.setBlock(x, y, z, id, data);
result.setBlock(x & 15, y, z & 15, id, data);
return true;
}
@Override
public boolean setBiome(final String world, int x, int z, final BaseBiome biome) {
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
x = x & 15;
z = z & 15;
FaweChunk<Chunk> result = this.blocks.get(wrap);
public boolean setBiome(int x, int z, final BaseBiome biome) {
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
FaweChunk<Chunk> result = this.blocks.get(pair);
if (result == null) {
result = this.getChunk(wrap);
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
result = this.getChunk(x >> 4, z >> 4);
final FaweChunk<Chunk> previous = this.blocks.put(pair, result);
if (previous != null) {
this.blocks.put(wrap, previous);
this.blocks.put(pair, previous);
result = previous;
}
}
result.setBiome(x, z, biome);
result.setBiome(x & 15, z & 15, biome);
return true;
}
@ -95,7 +94,7 @@ public abstract class SpongeQueue_0 extends FaweQueue {
if (this.blocks.size() == 0) {
return null;
}
final Iterator<Map.Entry<ChunkLoc, FaweChunk<Chunk>>> iter = this.blocks.entrySet().iterator();
final Iterator<Map.Entry<Long, FaweChunk<Chunk>>> iter = this.blocks.entrySet().iterator();
final FaweChunk<Chunk> toReturn = iter.next().getValue();
if (SetQueue.IMP.isWaiting()) {
return null;
@ -133,7 +132,7 @@ public abstract class SpongeQueue_0 extends FaweQueue {
@Override
public void setChunk(final FaweChunk<?> chunk) {
this.blocks.put(chunk.getChunkLoc(), (FaweChunk<Chunk>) chunk);
this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
}
public abstract Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs);
@ -141,7 +140,7 @@ public abstract class SpongeQueue_0 extends FaweQueue {
public abstract boolean setComponents(final FaweChunk<Chunk> fc);
@Override
public abstract FaweChunk<Chunk> getChunk(final ChunkLoc wrap);
public abstract FaweChunk<Chunk> getChunk(int x, int z);
@Override
public abstract boolean fixLighting(final FaweChunk<?> fc, final boolean fixAll);

View File

@ -1,8 +1,8 @@
package com.boydti.fawe.forge.v1_8;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.util.FaweQueue;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Arrays;
import org.spongepowered.api.Sponge;
@ -17,23 +17,29 @@ public class SpongeChunk_1_8 extends FaweChunk<Chunk> {
public int[][] biomes;
public Chunk chunk;
public SpongeChunk_1_8(ChunkLoc chunk) {
super(chunk);
public SpongeChunk_1_8(FaweQueue parent, int x, int z) {
super(parent, x, z);
this.ids = new char[16][];
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
}
@Override
public Chunk getChunk() {
if (this.chunk == null) {
ChunkLoc cl = getChunkLoc();
this.chunk = Sponge.getServer().getWorld(cl.world).get().getChunk(cl.x, 0, cl.z).get();
this.chunk = Sponge.getServer().getWorld(getParent().world).get().getChunk(getX(), 0, getZ()).get();
}
return this.chunk;
}
@Override
public void setLoc(final FaweQueue parent, int x, int z) {
super.setLoc(parent, x, z);
this.chunk = null;
}
/**
* Get the number of block changes in a specified section.
* @param i
@ -211,7 +217,7 @@ public class SpongeChunk_1_8 extends FaweChunk<Chunk> {
@Override
public FaweChunk clone() {
SpongeChunk_1_8 toReturn = new SpongeChunk_1_8(getChunkLoc());
SpongeChunk_1_8 toReturn = new SpongeChunk_1_8(getParent(), getX(), getZ());
toReturn.air = this.air.clone();
toReturn.count = this.count.clone();
toReturn.relight = this.relight.clone();

View File

@ -4,7 +4,6 @@ import com.boydti.fawe.FaweCache;
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.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.util.TaskManager;
@ -31,6 +30,12 @@ import org.spongepowered.api.world.World;
public class SpongeQueue_1_8 extends SpongeQueue_0 {
public World spongeWorld;
public SpongeQueue_1_8(String world) {
super(world);
}
@Override
public Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs) {
if (fcs.isEmpty()) {
@ -75,12 +80,41 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
}
}
private int lcx = Integer.MIN_VALUE;
private int lcz = Integer.MIN_VALUE;
private int lcy = Integer.MIN_VALUE;
private net.minecraft.world.chunk.Chunk lc;
private char[] ls;
@Override
public int getCombinedId4Data(int x, int y, int z) {
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;
Chunk spongeChunk = fc.getChunk();
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeChunk.getWorld();
ChunkLoc wrapper = fc.getChunkLoc();
try {
boolean flag = !nmsWorld.provider.getHasNoSky();
// Sections
@ -181,11 +215,12 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
/**
* This should be overridden by any specialized queues.
* @param wrap
* @param x
* @param z
*/
@Override
public SpongeChunk_1_8 getChunk(ChunkLoc wrap) {
return new SpongeChunk_1_8(wrap);
public SpongeChunk_1_8 getChunk(int x, int z) {
return new SpongeChunk_1_8(this, x, z);
}
@Override
@ -208,10 +243,9 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
}
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
ChunkLoc loc = pc.getChunkLoc();
int X = loc.x << 4;
int Z = loc.z << 4;
int X = pc.getX() << 4;
int Z = pc.getZ() << 4;
for (int j = 0; j < sections.length; j++) {