diff --git a/bukkit/build.gradle b/bukkit/build.gradle deleted file mode 100644 index ab4f8347..00000000 --- a/bukkit/build.gradle +++ /dev/null @@ -1,50 +0,0 @@ -dependencies { - compile project(':core') - compile 'org.bukkit.craftbukkit:CraftBukkit:1.8.8' - compile 'org.bukkit.craftbukkit:CraftBukkit:1.9.2' - compile 'net.milkbowl.vault:VaultAPI:1.5' - compile 'com.massivecraft:factions:2.8.0' - compile 'com.drtshock:factions:1.6.9.5' - compile 'com.factionsone:FactionsOne:1.2.2' - compile 'me.ryanhamshire:GriefPrevention:11.5.2' - compile 'com.massivecraft:mcore:7.0.1' - compile 'net.sacredlabyrinth.Phaed:PreciousStones:10.0.4-SNAPSHOT' - compile 'net.jzx7:regios:5.9.9' - compile 'com.bekvon.bukkit:residence:2.6.6.6' - compile 'com.palmergames.bukkit:towny:0.84.0.9' - compile 'com.worldcretornica:plotme_core:0.16.3' - compile 'junit:junit:4.11' - -} - -sourceCompatibility = 1.7 -targetCompatibility = 1.7 - -processResources { - from('src/main/resources') { - include 'plugin.yml' - expand( - name: project.parent.name, - version: project.parent.version - ) - } -} - -apply plugin: 'com.github.johnrengelman.shadow' -// We only want the shadow jar produced -jar.enabled = false -shadowJar { - dependencies { - include(dependency(':core')) - include(dependency('org.mcstats.bukkit:metrics:R7')) - } - relocate 'org.mcstats', 'com.plotsquared.stats' - archiveName = "${parent.name}-${project.name}.jar" - destinationDir = file '../target' -} -shadowJar.doLast { - task -> - ant.checksum file: task.archivePath -} - -build.dependsOn(shadowJar); \ No newline at end of file diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java deleted file mode 100644 index 43b31c89..00000000 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.boydti.fawe.bukkit.v0; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.util.FaweQueue; -import com.sk89q.worldedit.world.biome.BaseBiome; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingDeque; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.event.Listener; - -/** - * The base object for - */ -public abstract class BukkitQueue_0 extends FaweQueue implements Listener { - - protected World bukkitWorld; - - /** - * Map of chunks in the queue - */ - private ConcurrentHashMap> blocks = new ConcurrentHashMap<>(); - private LinkedBlockingDeque> chunks = new LinkedBlockingDeque<>(); - - public BukkitQueue_0(final String world) { - super(world); - } - - @Override - public boolean isChunkLoaded(int x, int z) { - if (bukkitWorld == null) { - bukkitWorld = Bukkit.getServer().getWorld(world); - } - return bukkitWorld.isChunkLoaded(x, z); -// long id = ((long) x << 32) | (z & 0xFFFFFFFFL); -// HashSet map = this.loaded.get(world); -// if (map != null) { -// return map.contains(id); -// } -// return false; - }; - - @Override - public boolean regenerateChunk(int x, int z) { - if (bukkitWorld == null) { - bukkitWorld = Bukkit.getServer().getWorld(world); - } - return bukkitWorld.regenerateChunk(x, z); - } - - @Override - public void addTask(int x, int z, Runnable runnable) { - long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x, z); - result.addTask(runnable); - FaweChunk previous = this.blocks.put(pair, result); - if (previous == null) { - chunks.add(result); - return; - } - this.blocks.put(pair, previous); - result = previous; - } - result.addTask(runnable); - } - - private FaweChunk lastChunk; - private int lastX = Integer.MIN_VALUE; - private int lastZ = Integer.MIN_VALUE; - - @Override - public boolean setBlock(int x, int y, int z, short id, byte data) { - if ((y > 255) || (y < 0)) { - return false; - } - int cx = x >> 4; - int cz = z >> 4; - if (cx != lastX || cz != lastZ) { - lastX = cx; - lastZ = cz; - long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL; - lastChunk = this.blocks.get(pair); - if (lastChunk == null) { - lastChunk = this.getChunk(x >> 4, z >> 4); - lastChunk.setBlock(x & 15, y, z & 15, id, data); - FaweChunk previous = this.blocks.put(pair, lastChunk); - if (previous == null) { - chunks.add(lastChunk); - return true; - } - this.blocks.put(pair, previous); - lastChunk = previous; - } - } - lastChunk.setBlock(x & 15, y, z & 15, id, data); - return true; - } - - @Override - public boolean setBiome(int x, int z, BaseBiome biome) { - long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x >> 4, z >> 4); - FaweChunk previous = this.blocks.put(pair, result); - if (previous != null) { - this.blocks.put(pair, previous); - result = previous; - } else { - chunks.add(result); - } - } - result.setBiome(x & 15, z & 15, biome); - return true; - } - - @Override - public FaweChunk next() { - lastX = Integer.MIN_VALUE; - lastZ = Integer.MIN_VALUE; - try { - if (this.blocks.size() == 0) { - return null; - } - synchronized (blocks) { - FaweChunk chunk = chunks.poll(); - if (chunk != null) { - blocks.remove(chunk.longHash()); - this.execute(chunk); - return chunk; - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - return null; - } - - @Override - public int size() { - return chunks.size(); - } - - private LinkedBlockingDeque> toUpdate = new LinkedBlockingDeque<>(); - - public boolean execute(FaweChunk fc) { - if (fc == null) { - return false; - } - // Load chunk - Chunk chunk = fc.getChunk(); - chunk.load(true); - // Set blocks / entities / biome - if (!this.setComponents(fc)) { - return false; - } - fc.executeTasks(); - return true; - } - - @Override - public void clear() { - this.blocks.clear(); - this.chunks.clear(); - } - - @Override - public void setChunk(FaweChunk chunk) { - FaweChunk previous = this.blocks.put(chunk.longHash(), (FaweChunk) chunk); - if (previous != null) { - chunks.remove(previous); - } - chunks.add((FaweChunk) chunk); - } - - public abstract Collection> sendChunk(Collection> fcs); - - public abstract boolean setComponents(FaweChunk fc); - - @Override - public abstract FaweChunk getChunk(int x, int z); - - @Override - public abstract boolean fixLighting(FaweChunk fc, boolean fixAll); -} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitEditSessionWrapper_1_8.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitEditSessionWrapper_1_8.java deleted file mode 100644 index 41768306..00000000 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitEditSessionWrapper_1_8.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.boydti.fawe.bukkit.v1_8; - -import com.boydti.fawe.bukkit.v0.BukkitEditSessionWrapper_0; -import com.boydti.fawe.util.ReflectionUtils.RefClass; -import com.boydti.fawe.util.ReflectionUtils.RefField; -import com.boydti.fawe.util.ReflectionUtils.RefMethod; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BlockType; -import org.bukkit.Bukkit; - - -import static com.boydti.fawe.util.ReflectionUtils.getRefClass; - -public class BukkitEditSessionWrapper_1_8 extends BukkitEditSessionWrapper_0 { - - private final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld"); - private final RefClass classChunk = getRefClass("{nms}.Chunk"); - private final RefClass classWorld = getRefClass("{nms}.World"); - - private RefMethod worldGetHandle; - private RefMethod methodGetChunkAt; - private RefField heightMap; - private Object nmsWorld; - - private int lastXMin; - private int lastZMin; - private Object lastChunk; - - public BukkitEditSessionWrapper_1_8(final EditSession session) { - super(session); - try { - this.worldGetHandle = this.classCraftWorld.getMethod("getHandle"); - this.methodGetChunkAt = this.classWorld.getMethod("getChunkAt", int.class, int.class); - this.heightMap = this.classChunk.getField("heightMap"); - this.nmsWorld = this.worldGetHandle.of(Bukkit.getWorld(session.getWorld().getName())).call(); - } catch (final Exception e) { - e.printStackTrace(); - } - } - - @Override - public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) { - final int bx = x >> 4; - final int bz = z >> 4; - int[] heights; - if ((this.lastChunk == null) || (bx != this.lastXMin) || (bz != this.lastZMin)) { - this.lastXMin = bx; - this.lastZMin = bz; - this.lastChunk = this.methodGetChunkAt.of(this.nmsWorld).call(bx, bz); - } - if (this.lastChunk != null) { - heights = (int[]) this.heightMap.of(this.lastChunk).get(); - final int lx = x & 15; - final int lz = z & 15; - final int height = heights[((lz << 4) | lx)]; - if ((height <= maxY) && (height >= minY)) { - final Vector pt = new Vector(x, height, z); - final int id = this.session.getBlockType(pt); - if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, 0) : !BlockType.canPassThrough(id, 0)) { - return height; - } - } - } - for (int y = maxY; y >= minY; --y) { - final Vector pt = new Vector(x, y, z); - final int id = this.session.getBlockType(pt); - int data; - switch (id) { - case 0: { - continue; - } - case 2: - case 4: - case 13: - case 14: - case 15: - case 20: - case 21: - case 22: - case 25: - 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 52: - case 54: - case 55: - case 56: - case 57: - case 58: - case 60: - case 61: - case 62: - 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 84: - case 85: - case 87: - case 88: - case 101: - case 102: - case 103: - 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: - case 170: - case 172: - case 173: - case 174: - case 176: - case 177: - case 181: - case 182: - case 188: - case 189: - case 190: - case 191: - case 192: - return y; - default: - data = 0; - } - if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) { - return y; - } - } - return minY; - } - -} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue_1_8.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue_1_8.java deleted file mode 100644 index f17ae3e2..00000000 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue_1_8.java +++ /dev/null @@ -1,692 +0,0 @@ -package com.boydti.fawe.bukkit.v1_8; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.bukkit.v0.BukkitQueue_All; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.IntegerPair; -import com.boydti.fawe.util.MemUtil; -import com.boydti.fawe.util.ReflectionUtils.RefClass; -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.boydti.fawe.util.TaskManager; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.LocalWorld; -import com.sk89q.worldedit.Vector2D; -import com.sk89q.worldedit.bukkit.BukkitUtil; -import com.sk89q.worldedit.world.biome.BaseBiome; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.World.Environment; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.generator.BlockPopulator; -import org.bukkit.generator.ChunkGenerator; - - -import static com.boydti.fawe.util.ReflectionUtils.getRefClass; - -public class BukkitQueue_1_8 extends BukkitQueue_All { - - private final RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer"); - private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); - private final RefClass classPacket = getRefClass("{nms}.Packet"); - private final RefClass classConnection = getRefClass("{nms}.PlayerConnection"); - private final RefClass classChunk = getRefClass("{nms}.Chunk"); - private final RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer"); - private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); - private final RefClass classWorld = getRefClass("{nms}.World"); - private final RefField mustSave = this.classChunk.getField("mustSave"); - private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition"); - private final RefClass classChunkSection = getRefClass("{nms}.ChunkSection"); - - private RefMethod methodRecalcBlockCounts; - private RefMethod methodGetHandlePlayer; - private RefMethod methodGetHandleChunk; - private RefConstructor MapChunk; - private RefField connection; - private RefMethod send; - private RefMethod methodInitLighting; - private RefConstructor classBlockPositionConstructor; - private RefConstructor classChunkSectionConstructor; - private RefMethod methodX; - private RefMethod methodAreNeighborsLoaded; - private RefField fieldSections; - private RefField fieldWorld; - private RefMethod methodGetIdArray; - private RefMethod methodGetWorld; - private RefField tileEntityListTick; - - public BukkitQueue_1_8(final String world) { - super(world); - try { - this.methodGetHandlePlayer = this.classCraftPlayer.getMethod("getHandle"); - 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.connection = this.classEntityPlayer.getField("playerConnection"); - this.send = this.classConnection.getMethod("sendPacket", this.classPacket.getRealClass()); - this.classBlockPositionConstructor = this.classBlockPosition.getConstructor(int.class, int.class, int.class); - this.methodX = this.classWorld.getMethod("x", this.classBlockPosition.getRealClass()); - this.fieldSections = this.classChunk.getField("sections"); - this.fieldWorld = this.classChunk.getField("world"); - this.methodGetIdArray = this.classChunkSection.getMethod("getIdArray"); - this.methodAreNeighborsLoaded = this.classChunk.getMethod("areNeighborsLoaded", int.class); - this.classChunkSectionConstructor = this.classChunkSection.getConstructor(int.class, boolean.class, char[].class); - this.tileEntityListTick = this.classWorld.getField("tileEntityList"); - this.methodGetWorld = this.classChunk.getMethod("getWorld"); - this.methodRecalcBlockCounts = this.classChunkSection.getMethod("recalcBlockCounts"); - } catch (final NoSuchMethodException e) { - e.printStackTrace(); - } - } - - public Object getCachedChunk(int cx, int cz) { - return methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call(); - } - - public Object getCachedSection(Object chunk, int cy) { - Object storage = ((Object[]) fieldSections.of(chunk).get())[cy]; - if (storage == null) { - return null; - } - return getIdArray(storage); - } - - public int getCombinedId4Data(Object section, int x, int y, int z) { - char[] ls = (char[]) section; - return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0; - } - - @Override - public Collection> sendChunk(final Collection> fcs) { - for (final FaweChunk fc : fcs) { - sendChunk(fc); - } - return new ArrayList<>(); - } - - public void sendChunk(final FaweChunk fc) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING; - TaskManager.IMP.sync(new Runnable() { - @Override - public void run() { - if (!result) { - fixLighting(fc, Settings.FIX_ALL_LIGHTING); - } - Chunk chunk = fc.getChunk(); - World world = chunk.getWorld(); - final int view = Bukkit.getServer().getViewDistance(); - int cx = chunk.getX(); - int cz = chunk.getZ(); - for (final Player player : Bukkit.getOnlinePlayers()) { - if (!player.getWorld().equals(world)) { - continue; - } - final Location loc = player.getLocation(); - final int px = loc.getBlockX() >> 4; - final int pz = loc.getBlockZ() >> 4; - if ((Math.abs(cx - px) > view) || (Math.abs(cz - pz) > view)) { - continue; - } - final Object entity = methodGetHandlePlayer.of(player).call(); - final RefExecutor con = send.of(connection.of(entity).get()); - final Object c = methodGetHandleChunk.of(fc.getChunk()).call(); - Object packet = MapChunk.create(c, false, 65535); - con.call(packet); - } - } - }, false); - } - }, Settings.ASYNC_LIGHTING); - } - - @Override - public boolean fixLighting(final FaweChunk fc, final boolean fixAll) { - try { - final BukkitChunk_1_8 bc = (BukkitChunk_1_8) fc; - final Chunk chunk = bc.getChunk(); - if (!chunk.isLoaded()) { - if (Fawe.get().getMainThread() != Thread.currentThread()) { - return false; - } - chunk.load(false); - } - - // Initialize lighting - final Object c = this.methodGetHandleChunk.of(chunk).call(); - - this.methodInitLighting.of(c).call(); - - if (((bc.getTotalRelight() == 0) && !fixAll)) { - return true; - } - - final Object[] sections = (Object[]) this.fieldSections.of(c).get(); - final Object w = this.fieldWorld.of(c).get(); - - final int X = chunk.getX() << 4; - final int Z = chunk.getZ() << 4; - - final RefExecutor relight = this.methodX.of(w); - for (int j = 0; j < sections.length; j++) { - final Object section = sections[j]; - if (section == null) { - continue; - } - if (((bc.getRelight(j) == 0) && !fixAll) || (bc.getCount(j) == 0) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0))) { - continue; - } - final char[] array = this.getIdArray(section); - if (array == null) { - continue; - } - int l = FaweCache.RANDOM.random(2); - for (int k = 0; k < array.length; k++) { - final int i = array[k]; - if (i < 16) { - continue; - } - final short id = FaweCache.CACHE_ID[i]; - switch (id) { // Lighting - default: - if (!fixAll) { - continue; - } - if ((k & 1) == l) { - l = 1 - l; - continue; - } - case 10: - case 11: - case 39: - case 40: - case 50: - case 51: - case 62: - case 74: - case 76: - case 89: - case 122: - case 124: - case 130: - case 138: - case 169: - final int x = FaweCache.CACHE_X[j][k]; - final int y = FaweCache.CACHE_Y[j][k]; - final int z = FaweCache.CACHE_Z[j][k]; - if (this.isSurrounded(sections, x, y, z)) { - continue; - } - final Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z); - relight.call(pos); - } - } - } - return true; - } catch (final Throwable e) { - if (Thread.currentThread() == Fawe.get().getMainThread()) { - e.printStackTrace(); - } - } - return false; - } - - public boolean isSurrounded(final Object[] 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)); - } - - public boolean isSolid(final int i) { - if (i == 0) { - return false; - } - return Material.getMaterial(i).isOccluding(); - } - - public int getId(final Object[] sections, final int x, final int y, final int z) { - if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) { - return 1; - } - if ((y < 0) || (y > 255)) { - return 1; - } - final int i = FaweCache.CACHE_I[y][x][z]; - final Object section = sections[i]; - if (section == null) { - return 0; - } - final char[] array = this.getIdArray(section); - final int j = FaweCache.CACHE_J[y][x][z]; - return array[j] >> 4; - } - - @Override - public boolean setComponents(final FaweChunk fc) { - try { - final BukkitChunk_1_8 fs = ((BukkitChunk_1_8) fc); - final Chunk chunk = fs.getChunk(); - final World world = chunk.getWorld(); - - final boolean flag = world.getEnvironment() == Environment.NORMAL; - - // Sections - final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle"); - final Object c = getHandele.invoke(chunk); - final Object w = this.methodGetWorld.of(c).call(); - final Class 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 Collection[] entities = (Collection[]) ef.get(c); - - Method xm = null; - Method ym = null; - Method zm = null; - - // Trim tiles - boolean removed = false; - final Set> entryset = (Set>) (Set) tiles.entrySet(); - final Iterator> iter = entryset.iterator(); - while (iter.hasNext()) { - final Entry tile = iter.next(); - final Object pos = tile.getKey(); - if (xm == null) { - final Class clazz2 = pos.getClass().getSuperclass(); - xm = clazz2.getDeclaredMethod("getX"); - ym = clazz2.getDeclaredMethod("getY"); - zm = clazz2.getDeclaredMethod("getZ"); - } - final int lx = (int) xm.invoke(pos) & 15; - final int ly = (int) ym.invoke(pos); - final int lz = (int) zm.invoke(pos) & 15; - final int j = FaweCache.CACHE_I[ly][lx][lz]; - final int k = FaweCache.CACHE_J[ly][lx][lz]; - final char[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - if (array[k] != 0) { - removed = true; - iter.remove(); - } - } - if (removed) { - ((Collection) this.tileEntityListTick.of(w).get()).clear(); - } - - // Trim entities - for (int i = 0; i < 16; i++) { - if ((entities[i] != null) && (fs.getCount(i) >= 4096)) { - entities[i].clear(); - } - } - - // Efficiently merge sections - for (int j = 0; j < sections.length; j++) { - if (fs.getCount(j) == 0) { - continue; - } - final char[] newArray = fs.getIdArray(j); - if (newArray == null) { - continue; - } - Object section = sections[j]; - if ((section == null) || (fs.getCount(j) >= 4096)) { - section = sections[j] = this.newChunkSection(j << 4, flag, newArray); - continue; - } - final char[] currentArray = this.getIdArray(section); - boolean fill = true; - for (int k = 0; k < newArray.length; k++) { - final char n = newArray[k]; - if (n == 0) { - fill = false; - continue; - } - switch (n) { - case 0: - fill = false; - continue; - case 1: - fill = false; - currentArray[k] = 0; - continue; - default: - currentArray[k] = n; - continue; - } - } - if (fill) { - fs.setCount(j, Short.MAX_VALUE); - } - methodRecalcBlockCounts.of(section).call(); - } - - // Biomes - final int[][] biomes = fs.getBiomeArray(); - if (biomes != null) { - final LocalWorld lw = BukkitUtil.getLocalWorld(world); - 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++) { - final int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - final int biome = array[z]; - if (biome == 0) { - continue; - } - if (last != biome) { - last = biome; - bb.setId(biome); - } - lw.setBiome(new Vector2D(X + x, Z + z), bb); - } - } - } - TaskManager.IMP.later(new Runnable() { - @Override - public void run() { - sendChunk(fs); - } - }, 1); - return true; - } catch (final Exception e) { - if (Thread.currentThread() == Fawe.get().getMainThread()) { - e.printStackTrace(); - } - } - return false; - } - - /** - * This method is called when the server is < 1% available memory (i.e. likely to crash)
- * - You can disable this in the conifg
- * - Will try to free up some memory
- * - Clears the queue
- * - Clears worldedit history
- * - Clears entities
- * - Unloads chunks in vacant worlds
- * - Unloads non visible chunks
- */ - @Override - public void saveMemory() { - super.saveMemory(); - // Clear the queue - super.clear(); - ArrayDeque toUnload = new ArrayDeque<>(); - final int distance = Bukkit.getViewDistance() + 2; - HashMap> players = new HashMap<>(); - for (final Player player : Bukkit.getOnlinePlayers()) { - // Clear history - final FawePlayer fp = FawePlayer.wrap(player); - final LocalSession s = fp.getSession(); - if (s != null) { - s.clearHistory(); - s.setClipboard(null); - } - final Location loc = player.getLocation(); - final World worldObj = loc.getWorld(); - final String world = worldObj.getName(); - HashMap map = players.get(world); - if (map == null) { - map = new HashMap<>(); - players.put(world, map); - } - final IntegerPair origin = new IntegerPair(loc.getBlockX() >> 4, loc.getBlockZ() >> 4); - Integer val = map.get(origin); - int check; - if (val != null) { - if (val == distance) { - continue; - } - check = distance - val; - } else { - check = distance; - map.put(origin, distance); - } - for (int x = -distance; x <= distance; x++) { - if ((x >= check) || (-x >= check)) { - continue; - } - for (int z = -distance; z <= distance; z++) { - if ((z >= check) || (-z >= check)) { - continue; - } - final int weight = distance - Math.max(Math.abs(x), Math.abs(z)); - final IntegerPair chunk = new IntegerPair(x + origin.x, z + origin.z); - val = map.get(chunk); - if ((val == null) || (val < weight)) { - map.put(chunk, weight); - } - } - } - } - Fawe.get().getWorldEdit().clearSessions(); - for (final World world : Bukkit.getWorlds()) { - final String name = world.getName(); - final HashMap map = players.get(name); - if ((map == null) || (map.size() == 0)) { - final boolean save = world.isAutoSave(); - world.setAutoSave(false); - for (final Chunk chunk : world.getLoadedChunks()) { - this.unloadChunk(name, chunk); - } - world.setAutoSave(save); - continue; - } - final Chunk[] chunks = world.getLoadedChunks(); - for (final Chunk chunk : chunks) { - final int x = chunk.getX(); - final int z = chunk.getZ(); - if (!map.containsKey(new IntegerPair(x, z))) { - toUnload.add(chunk); - } else if (chunk.getEntities().length > 4096) { - for (final Entity ent : chunk.getEntities()) { - ent.remove(); - } - } - } - } - // GC again - System.gc(); - System.gc(); - // If still critical memory - int free = MemUtil.calculateMemory(); - if (free <= 1) { - for (final Chunk chunk : toUnload) { - this.unloadChunk(chunk.getWorld().getName(), chunk); - } - } else if (free == Integer.MAX_VALUE) { - for (final Chunk chunk : toUnload) { - chunk.unload(true, false); - } - } else { - return; - } - toUnload = null; - players = null; - } - - public Object newChunkSection(final int i, final boolean flag, final char[] ids) { - return this.classChunkSectionConstructor.create(i, flag, ids); - } - - public char[] getIdArray(final Object obj) { - return (char[]) this.methodGetIdArray.of(obj).call(); - } - - @Override - public FaweChunk getChunk(int x, int z) { - return new BukkitChunk_1_8(this, x, z); - } - - public boolean unloadChunk(final String world, final Chunk chunk) { - final Object c = this.methodGetHandleChunk.of(chunk).call(); - this.mustSave.of(c).set(false); - if (chunk.isLoaded()) { - chunk.unload(false, false); - } - return true; - } - - public ChunkGenerator setGenerator(final World world, final ChunkGenerator newGen) { - try { - final ChunkGenerator gen = world.getGenerator(); - final Class clazz = world.getClass(); - final Field generator = clazz.getDeclaredField("generator"); - generator.setAccessible(true); - generator.set(world, newGen); - - final Field wf = clazz.getDeclaredField("world"); - wf.setAccessible(true); - final Object w = wf.get(world); - final Class clazz2 = w.getClass().getSuperclass(); - final Field generator2 = clazz2.getDeclaredField("generator"); - generator2.set(w, newGen); - - return gen; - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } - - public List setPopulator(final World world, final List newPop) { - try { - final List pop = world.getPopulators(); - final Field populators = world.getClass().getDeclaredField("populators"); - populators.setAccessible(true); - populators.set(world, newPop); - return pop; - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } - - public void setEntitiesAndTiles(final Chunk chunk, final List[] entities, final Map tiles) { - try { - final Class clazz = chunk.getClass(); - final Method handle = clazz.getMethod("getHandle"); - final Object c = handle.invoke(chunk); - final Class clazz2 = c.getClass(); - - if (tiles.size() > 0) { - final Field tef = clazz2.getDeclaredField("tileEntities"); - final Map te = (Map) tef.get(c); - final Method put = te.getClass().getMethod("putAll", Map.class); - put.invoke(te, tiles); - } - - final Field esf = clazz2.getDeclaredField("entitySlices"); - esf.setAccessible(true); - esf.set(c, entities); - } catch (final Exception e) { - e.printStackTrace(); - } - } - - public Object getProvider(final World world) { - try { - // Provider 1 - final Class clazz = world.getClass(); - final Field wf = clazz.getDeclaredField("world"); - wf.setAccessible(true); - final Object w = wf.get(world); - final Field provider = w.getClass().getSuperclass().getDeclaredField("chunkProvider"); - provider.setAccessible(true); - // ChunkProviderServer - final Class clazz2 = w.getClass(); - final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); - // Store old provider server - final Object worldProviderServer = wpsf.get(w); - // Store the old provider - final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); - return cp.get(worldProviderServer); - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } - - public Object setProvider(final World world, Object newProvider) { - try { - // Provider 1 - final Class clazz = world.getClass(); - final Field wf = clazz.getDeclaredField("world"); - wf.setAccessible(true); - final Object w = wf.get(world); - // ChunkProviderServer - final Class clazz2 = w.getClass(); - final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); - // Store old provider server - final Object worldProviderServer = wpsf.get(w); - // Store the old provider - final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); - final Object oldProvider = cp.get(worldProviderServer); - // Provider 2 - final Class clazz3 = worldProviderServer.getClass(); - final Field provider2 = clazz3.getDeclaredField("chunkProvider"); - // If the provider needs to be calculated - if (newProvider == null) { - Method k; - try { - k = clazz2.getDeclaredMethod("k"); - } catch (final Throwable e) { - try { - k = clazz2.getDeclaredMethod("j"); - } catch (final Throwable e2) { - e2.printStackTrace(); - return null; - } - } - k.setAccessible(true); - final Object tempProviderServer = k.invoke(w); - newProvider = cp.get(tempProviderServer); - // Restore old provider - wpsf.set(w, worldProviderServer); - } - // Set provider for provider server - provider2.set(worldProviderServer, newProvider); - // Return the previous provider - return oldProvider; - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9.java deleted file mode 100644 index 22ead84c..00000000 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9.java +++ /dev/null @@ -1,658 +0,0 @@ -package com.boydti.fawe.bukkit.v1_9; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.bukkit.v0.BukkitQueue_All; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.IntegerPair; -import com.boydti.fawe.object.PseudoRandom; -import com.boydti.fawe.util.MemUtil; -import com.boydti.fawe.util.ReflectionUtils.RefClass; -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.boydti.fawe.util.TaskManager; -import com.sk89q.worldedit.LocalSession; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.World.Environment; -import org.bukkit.block.Biome; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.generator.BlockPopulator; -import org.bukkit.generator.ChunkGenerator; - - -import static com.boydti.fawe.util.ReflectionUtils.getRefClass; - -public class BukkitQueue_1_9 extends BukkitQueue_All { - - private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); - private final RefClass classChunk = getRefClass("{nms}.Chunk"); - private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); - private final RefClass classWorld = getRefClass("{nms}.World"); - private final RefField mustSave = this.classChunk.getField("mustSave"); - private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition"); - private final RefClass classChunkSection = getRefClass("{nms}.ChunkSection"); - private final RefClass classBlock = getRefClass("{nms}.Block"); - private final RefClass classIBlockData = getRefClass("{nms}.IBlockData"); - private final RefMethod methodGetHandleChunk; - private final RefMethod methodInitLighting; - private final RefConstructor classBlockPositionConstructor; - private final RefConstructor classChunkSectionConstructor; - private final RefMethod methodW; - private final RefField fieldSections; - 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(final 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); - this.methodW = this.classWorld.getMethod("w", this.classBlockPosition.getRealClass()); - this.fieldSections = this.classChunk.getField("sections"); - this.fieldWorld = this.classChunk.getField("world"); - 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()); - } - - public Object getCachedChunk(int cx, int cz) { - return methodGetType.of(methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call()); - } - - public Object getCachedSection(Object chunk, int cy) { - return chunk; - } - - public int getCombinedId4Data(Object section, int x, int y, int z) { - int combined = (int) methodGetCombinedId.call(((RefExecutor) section).call(x & 15, y, z & 15)); - return ((combined & 4095) << 4) + (combined >> 12); - } - - @Override - public Collection> sendChunk(final Collection> fcs) { - for (final FaweChunk fc : fcs) { - sendChunk(fc); - } - return new ArrayList<>(); - } - - public void sendChunk(final FaweChunk fc) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING; - TaskManager.IMP.sync(new Runnable() { - @Override - public void run() { - if (!result) { - fixLighting(fc, Settings.FIX_ALL_LIGHTING); - } - final Chunk chunk = fc.getChunk(); - chunk.getWorld().refreshChunk(fc.getX(), fc.getZ()); - } - }, false); - } - }, Settings.ASYNC_LIGHTING); - } - - @Override - public boolean fixLighting(final FaweChunk pc, final boolean fixAll) { - try { - final BukkitChunk_1_9 bc = (BukkitChunk_1_9) pc; - final Chunk chunk = bc.getChunk(); - if (!chunk.isLoaded()) { - if (Fawe.get().getMainThread() != Thread.currentThread()) { - return false; - } - chunk.load(false); - } - // Initialize lighting - final Object c = this.methodGetHandleChunk.of(chunk).call(); - - this.methodInitLighting.of(c).call(); - - if (((bc.getTotalRelight() == 0) && !fixAll)) { - return true; - } - - final Object[] sections = (Object[]) this.fieldSections.of(c).get(); - final Object w = this.fieldWorld.of(c).get(); - - final int X = chunk.getX() << 4; - final int Z = chunk.getZ() << 4; - - final RefExecutor relight = this.methodW.of(w); - for (int j = 0; j < sections.length; j++) { - final Object section = sections[j]; - if (section == null) { - continue; - } - if (((bc.getRelight(j) == 0) && !fixAll) || (bc.getCount(j) == 0) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0))) { - continue; - } - final int[] array = bc.getIdArray(j); - if (array == null) { - continue; - } - int l = PseudoRandom.random.random(2); - for (int k = 0; k < array.length; k++) { - final int i = array[k]; - if (i < 16) { - continue; - } - final short id = (short) (i & 0xFFF); - switch (id) { // Lighting - default: - if (!fixAll) { - continue; - } - if ((k & 1) == l) { - l = 1 - l; - continue; - } - case 10: - case 11: - case 39: - case 40: - case 50: - case 51: - case 62: - case 74: - case 76: - case 89: - case 122: - case 124: - case 130: - case 138: - case 169: - final int x = FaweCache.CACHE_X[j][k]; - final int y = FaweCache.CACHE_Y[j][k]; - final int z = FaweCache.CACHE_Z[j][k]; - if (this.isSurrounded(bc.getIdArrays(), x, y, z)) { - continue; - } - final Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z); - relight.call(pos); - } - } - } - return true; - } catch (final Throwable e) { - if (Thread.currentThread() == Fawe.get().getMainThread()) { - e.printStackTrace(); - } - } - return false; - } - - 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)); - } - - public boolean isSolid(final int i) { - if (i != 0) { - final Material material = Material.getMaterial(i); - return (material != null) && Material.getMaterial(i).isOccluding(); - } - return false; - } - - public int getId(final int[][] sections, final int x, final int y, final int z) { - if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) { - return 1; - } - if ((y < 0) || (y > 255)) { - return 1; - } - final int i = FaweCache.CACHE_I[y][x][z]; - final int[] section = sections[i]; - if (section == null) { - return 0; - } - final int j = FaweCache.CACHE_J[y][x][z]; - return section[j]; - } - - public Object getBlocks(final Object obj) { - return this.methodGetBlocks.of(obj).call(); - } - - @Override - public boolean setComponents(final FaweChunk pc) { - final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc; - final Chunk chunk = pc.getChunk(); - final World world = chunk.getWorld(); - chunk.load(true); - try { - final boolean flag = world.getEnvironment() == Environment.NORMAL; - - // Sections - final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle"); - final Object c = getHandele.invoke(chunk); - final Object w = this.methodGetWorld.of(c).call(); - final Class 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 Collection[] entities = (Collection[]) ef.get(c); - - Method xm = null; - Method ym = null; - Method zm = null; - - // Trim tiles - boolean removed = false; - final Set> entryset = (Set>) (Set) tiles.entrySet(); - final Iterator> iter = entryset.iterator(); - while (iter.hasNext()) { - final Entry tile = iter.next(); - final Object pos = tile.getKey(); - if (xm == null) { - final Class clazz2 = pos.getClass().getSuperclass(); - xm = clazz2.getDeclaredMethod("getX"); - ym = clazz2.getDeclaredMethod("getY"); - zm = clazz2.getDeclaredMethod("getZ"); - } - final int lx = (int) xm.invoke(pos) & 15; - final int ly = (int) ym.invoke(pos); - final int lz = (int) zm.invoke(pos) & 15; - final int j = FaweCache.CACHE_I[ly][lx][lz]; - final int k = FaweCache.CACHE_J[ly][lx][lz]; - final int[] array = fs.getIdArray(j); - if (array == null) { - continue; - } - if (array[k] != 0) { - removed = true; - iter.remove(); - } - } - if (removed) { - ((Collection) this.tileEntityListTick.of(w).get()).clear(); - } - - // Trim entities - for (int i = 0; i < 16; i++) { - if ((entities[i] != null) && (fs.getCount(i) >= 4096)) { - entities[i].clear(); - } - } - - // Efficiently merge sections - for (int j = 0; j < sections.length; j++) { - if (fs.getCount(j) == 0) { - continue; - } - final int[] newArray = fs.getIdArray(j); - if (newArray == null) { - continue; - } - Object section = sections[j]; - if ((section == null) || (fs.getCount(j) >= 4096)) { - final char[] array = new char[4096]; - for (int i = 0; i < newArray.length; i++) { - final int combined = newArray[i]; - final int id = combined & 4095; - final int data = combined >> 12; - array[i] = (char) ((id << 4) + data); - } - section = sections[j] = this.newChunkSection(j << 4, flag, array); - continue; - } - this.getBlocks(section); - final RefExecutor setType = this.methodSetType.of(section); - boolean fill = true; - for (int k = 0; k < newArray.length; k++) { - final int n = newArray[k]; - switch (n) { - case 0: - fill = false; - continue; - case -1: { - fill = false; - final int x = FaweCache.CACHE_X[j][k]; - final int y = FaweCache.CACHE_Y[j][k]; - final int z = FaweCache.CACHE_Z[j][k]; - setType.call(x, y & 15, z, this.air); - continue; - } - default: { - final int x = FaweCache.CACHE_X[j][k]; - final int y = FaweCache.CACHE_Y[j][k]; - final int z = FaweCache.CACHE_Z[j][k]; - final Object iblock = this.methodGetByCombinedId.call(n); - setType.call(x, y & 15, z, iblock); - continue; - } - } - } - if (fill) { - fs.setCount(j, Short.MAX_VALUE); - } - } - // Clear - } catch (IllegalAccessException | IllegalArgumentException | NoSuchMethodException | SecurityException | InvocationTargetException | NoSuchFieldException e) { - e.printStackTrace(); - } - final int[][] biomes = fs.biomes; - final Biome[] values = Biome.values(); - if (biomes != null) { - for (int x = 0; x < 16; x++) { - final int[] array = biomes[x]; - if (array == null) { - continue; - } - for (int z = 0; z < 16; z++) { - final int biome = array[z]; - if (biome == 0) { - continue; - } - chunk.getBlock(x, 0, z).setBiome(values[biome]); - } - } - } - TaskManager.IMP.later(new Runnable() { - @Override - public void run() { - sendChunk(fs); - } - }, 1); - return true; - } - - /** - * This method is called when the server is < 1% available memory (i.e. likely to crash)
- * - You can disable this in the conifg
- * - Will try to free up some memory
- * - Clears the queue
- * - Clears worldedit history
- * - Clears entities
- * - Unloads chunks in vacant worlds
- * - Unloads non visible chunks
- */ - @Override - public void saveMemory() { - super.saveMemory(); - // Clear the queue - super.clear(); - ArrayDeque toUnload = new ArrayDeque<>(); - final int distance = Bukkit.getViewDistance() + 2; - HashMap> players = new HashMap<>(); - for (final Player player : Bukkit.getOnlinePlayers()) { - // Clear history - final FawePlayer fp = FawePlayer.wrap(player); - final LocalSession s = fp.getSession(); - if (s != null) { - s.clearHistory(); - s.setClipboard(null); - } - final Location loc = player.getLocation(); - final World worldObj = loc.getWorld(); - final String world = worldObj.getName(); - HashMap map = players.get(world); - if (map == null) { - map = new HashMap<>(); - players.put(world, map); - } - final IntegerPair origin = new IntegerPair(loc.getBlockX() >> 4, loc.getBlockZ() >> 4); - Integer val = map.get(origin); - int check; - if (val != null) { - if (val == distance) { - continue; - } - check = distance - val; - } else { - check = distance; - map.put(origin, distance); - } - for (int x = -distance; x <= distance; x++) { - if ((x >= check) || (-x >= check)) { - continue; - } - for (int z = -distance; z <= distance; z++) { - if ((z >= check) || (-z >= check)) { - continue; - } - final int weight = distance - Math.max(Math.abs(x), Math.abs(z)); - final IntegerPair chunk = new IntegerPair(x + origin.x, z + origin.z); - val = map.get(chunk); - if ((val == null) || (val < weight)) { - map.put(chunk, weight); - } - } - } - } - Fawe.get().getWorldEdit().clearSessions(); - for (final World world : Bukkit.getWorlds()) { - final String name = world.getName(); - final HashMap map = players.get(name); - if ((map == null) || (map.size() == 0)) { - final boolean save = world.isAutoSave(); - world.setAutoSave(false); - for (final Chunk chunk : world.getLoadedChunks()) { - this.unloadChunk(name, chunk); - } - world.setAutoSave(save); - continue; - } - final Chunk[] chunks = world.getLoadedChunks(); - for (final Chunk chunk : chunks) { - final int x = chunk.getX(); - final int z = chunk.getZ(); - if (!map.containsKey(new IntegerPair(x, z))) { - toUnload.add(chunk); - } else if (chunk.getEntities().length > 4096) { - for (final Entity ent : chunk.getEntities()) { - ent.remove(); - } - } - } - } - // GC again - System.gc(); - System.gc(); - // If still critical memory - int free = MemUtil.calculateMemory(); - if (free <= 1) { - for (final Chunk chunk : toUnload) { - this.unloadChunk(chunk.getWorld().getName(), chunk); - } - } else if (free == Integer.MAX_VALUE) { - for (final Chunk chunk : toUnload) { - chunk.unload(true, false); - } - } else { - return; - } - toUnload = null; - players = null; - } - - public Object newChunkSection(final int i, final boolean flag, final char[] ids) { - return this.classChunkSectionConstructor.create(i, flag, ids); - } - - @Override - public FaweChunk getChunk(int x, int z) { - return new BukkitChunk_1_9(this, x, z); - } - - public boolean unloadChunk(final String world, final Chunk chunk) { - final Object c = this.methodGetHandleChunk.of(chunk).call(); - this.mustSave.of(c).set(false); - if (chunk.isLoaded()) { - chunk.unload(false, false); - } - return true; - } - - public ChunkGenerator setGenerator(final World world, final ChunkGenerator newGen) { - try { - final ChunkGenerator gen = world.getGenerator(); - final Class clazz = world.getClass(); - final Field generator = clazz.getDeclaredField("generator"); - generator.setAccessible(true); - generator.set(world, newGen); - - final Field wf = clazz.getDeclaredField("world"); - wf.setAccessible(true); - final Object w = wf.get(world); - final Class clazz2 = w.getClass().getSuperclass(); - final Field generator2 = clazz2.getDeclaredField("generator"); - generator2.set(w, newGen); - - return gen; - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } - - public List setPopulator(final World world, final List newPop) { - try { - final List pop = world.getPopulators(); - final Field populators = world.getClass().getDeclaredField("populators"); - populators.setAccessible(true); - populators.set(world, newPop); - return pop; - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } - - public void setEntitiesAndTiles(final Chunk chunk, final List[] entities, final Map tiles) { - try { - final Class clazz = chunk.getClass(); - final Method handle = clazz.getMethod("getHandle"); - final Object c = handle.invoke(chunk); - final Class clazz2 = c.getClass(); - - if (tiles.size() > 0) { - final Field tef = clazz2.getDeclaredField("tileEntities"); - final Map te = (Map) tef.get(c); - final Method put = te.getClass().getMethod("putAll", Map.class); - put.invoke(te, tiles); - } - - final Field esf = clazz2.getDeclaredField("entitySlices"); - esf.setAccessible(true); - esf.set(c, entities); - } catch (final Exception e) { - e.printStackTrace(); - } - } - - public Object getProvider(final World world) { - try { - // Provider 1 - final Class clazz = world.getClass(); - final Field wf = clazz.getDeclaredField("world"); - wf.setAccessible(true); - final Object w = wf.get(world); - final Field provider = w.getClass().getSuperclass().getDeclaredField("chunkProvider"); - provider.setAccessible(true); - // ChunkProviderServer - final Class clazz2 = w.getClass(); - final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); - // Store old provider server - final Object worldProviderServer = wpsf.get(w); - // Store the old provider - final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); - return cp.get(worldProviderServer); - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } - - public Object setProvider(final World world, Object newProvider) { - try { - // Provider 1 - final Class clazz = world.getClass(); - final Field wf = clazz.getDeclaredField("world"); - wf.setAccessible(true); - final Object w = wf.get(world); - // ChunkProviderServer - final Class clazz2 = w.getClass(); - final Field wpsf = clazz2.getDeclaredField("chunkProviderServer"); - // Store old provider server - final Object worldProviderServer = wpsf.get(w); - // Store the old provider - final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider"); - final Object oldProvider = cp.get(worldProviderServer); - // Provider 2 - final Class clazz3 = worldProviderServer.getClass(); - final Field provider2 = clazz3.getDeclaredField("chunkProvider"); - // If the provider needs to be calculated - if (newProvider == null) { - Method k; - try { - k = clazz2.getDeclaredMethod("k"); - } catch (final Throwable e) { - try { - k = clazz2.getDeclaredMethod("j"); - } catch (final Throwable e2) { - e2.printStackTrace(); - return null; - } - } - k.setAccessible(true); - final Object tempProviderServer = k.invoke(w); - newProvider = cp.get(tempProviderServer); - // Restore old provider - wpsf.set(w, worldProviderServer); - } - // Set provider for provider server - provider2.set(worldProviderServer, newProvider); - // Return the previous provider - return oldProvider; - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } -} diff --git a/bukkit0/build.gradle b/bukkit0/build.gradle new file mode 100644 index 00000000..40ad1695 --- /dev/null +++ b/bukkit0/build.gradle @@ -0,0 +1,25 @@ +dependencies { + compile project(':core') + compile 'net.milkbowl.vault:VaultAPI:1.5' + compile 'com.massivecraft:factions:2.8.0' + compile 'com.drtshock:factions:1.6.9.5' + compile 'com.factionsone:FactionsOne:1.2.2' + compile 'me.ryanhamshire:GriefPrevention:11.5.2' + compile 'com.massivecraft:mcore:7.0.1' + compile 'net.sacredlabyrinth.Phaed:PreciousStones:10.0.4-SNAPSHOT' + compile 'net.jzx7:regios:5.9.9' + compile 'com.bekvon.bukkit:residence:2.6.6.6' + compile 'com.palmergames.bukkit:towny:0.84.0.9' + compile 'com.worldcretornica:plotme_core:0.16.3' + compile 'junit:junit:4.11' +} + +processResources { + from('src/main/resources') { + include 'plugin.yml' + expand( + name: project.parent.name, + version: project.parent.version + ) + } +} \ No newline at end of file diff --git a/bukkit0/build/libs/bukkit-all.jar b/bukkit0/build/libs/bukkit-all.jar new file mode 100644 index 00000000..f87c0cd5 Binary files /dev/null and b/bukkit0/build/libs/bukkit-all.jar differ diff --git a/bukkit0/build/libs/bukkit-all.jar.MD5 b/bukkit0/build/libs/bukkit-all.jar.MD5 new file mode 100644 index 00000000..306da7ab --- /dev/null +++ b/bukkit0/build/libs/bukkit-all.jar.MD5 @@ -0,0 +1 @@ +b88df720766580832fc345218f204c5f diff --git a/bukkit0/build/libs/bukkit.jar b/bukkit0/build/libs/bukkit.jar new file mode 100644 index 00000000..105d349f Binary files /dev/null and b/bukkit0/build/libs/bukkit.jar differ diff --git a/bukkit0/build/libs/bukkit0.jar b/bukkit0/build/libs/bukkit0.jar new file mode 100644 index 00000000..06f13a1e Binary files /dev/null and b/bukkit0/build/libs/bukkit0.jar differ diff --git a/bukkit/build/resources/main/config.yml b/bukkit0/build/resources/main/config.yml similarity index 100% rename from bukkit/build/resources/main/config.yml rename to bukkit0/build/resources/main/config.yml diff --git a/bukkit/build/resources/main/plugin.yml b/bukkit0/build/resources/main/plugin.yml similarity index 100% rename from bukkit/build/resources/main/plugin.yml rename to bukkit0/build/resources/main/plugin.yml diff --git a/bukkit/build/tmp/shadowJar/MANIFEST.MF b/bukkit0/build/tmp/jar/MANIFEST.MF similarity index 100% rename from bukkit/build/tmp/shadowJar/MANIFEST.MF rename to bukkit0/build/tmp/jar/MANIFEST.MF diff --git a/bukkit0/build/tmp/shadowJar/MANIFEST.MF b/bukkit0/build/tmp/shadowJar/MANIFEST.MF new file mode 100644 index 00000000..59499bce --- /dev/null +++ b/bukkit0/build/tmp/shadowJar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitCommand.java diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java new file mode 100644 index 00000000..0184c40d --- /dev/null +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java @@ -0,0 +1,18 @@ +package com.boydti.fawe.bukkit; + +import com.boydti.fawe.object.EditSessionWrapper; +import com.boydti.fawe.util.FaweQueue; +import com.sk89q.worldedit.EditSession; +import org.bukkit.plugin.java.JavaPlugin; + +public abstract class BukkitMain extends JavaPlugin { + + @Override + public void onEnable() { + new FaweBukkit(this); + } + + public abstract FaweQueue getQueue(String world); + + public abstract EditSessionWrapper getEditSessionWrapper(EditSession session); +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java similarity index 91% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java index 5740a2fe..f0a964fd 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java @@ -37,14 +37,14 @@ public class BukkitPlayer extends FawePlayer { * - The `/wea` command will give/remove the required bypass permission */ if (Fawe. imp().getVault() == null || Fawe. imp().getVault().permission == null) { - this.parent.addAttachment(Fawe. imp()).setPermission("fawe.bypass", flag); + this.parent.addAttachment(Fawe. imp().getPlugin()).setPermission("fawe.bypass", flag); } else if (flag) { if (!Fawe. imp().getVault().permission.playerAdd(this.parent, perm)) { - this.parent.addAttachment(Fawe. imp()).setPermission("fawe.bypass", flag); + this.parent.addAttachment(Fawe. imp().getPlugin()).setPermission("fawe.bypass", flag); } } else { if (!Fawe. imp().getVault().permission.playerRemove(this.parent, perm)) { - this.parent.addAttachment(Fawe. imp()).setPermission("fawe.bypass", flag); + this.parent.addAttachment(Fawe. imp().getPlugin()).setPermission("fawe.bypass", flag); } } } diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java similarity index 90% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index c0b13b1d..d203fd43 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -13,10 +13,7 @@ import com.boydti.fawe.bukkit.regions.ResidenceFeature; import com.boydti.fawe.bukkit.regions.TownyFeature; import com.boydti.fawe.bukkit.regions.Worldguard; import com.boydti.fawe.bukkit.v0.BukkitQueue_All; -import com.boydti.fawe.bukkit.v1_8.BukkitEditSessionWrapper_1_8; -import com.boydti.fawe.bukkit.v1_8.BukkitQueue_1_8; -import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9; -import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1; +import com.boydti.fawe.bukkit.v0.ChunkListener; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.EditSessionWrapper; import com.boydti.fawe.object.FaweCommand; @@ -43,10 +40,10 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; -public class FaweBukkit extends JavaPlugin implements IFawe, Listener { +public class FaweBukkit implements IFawe, Listener { + private final BukkitMain plugin; private VaultUtil vault; private WorldEditPlugin worldedit; @@ -61,10 +58,10 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { return this.worldedit; } - @Override - public void onEnable() { + public FaweBukkit(BukkitMain plugin) { + this.plugin = plugin; try { - Bukkit.getPluginManager().registerEvents(this, this); + Bukkit.getPluginManager().registerEvents(this, plugin); Fawe.set(this); if (Bukkit.getVersion().contains("git-Spigot") && FaweAPI.checkVersion(this.getVersion(), 1, 7, 10)) { debug("====== USE PAPER SPIGOT ======"); @@ -76,23 +73,29 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { } catch (final Throwable e) { e.printStackTrace(); - this.getServer().shutdown(); + Bukkit.getServer().shutdown(); } + TaskManager.IMP.task(new Runnable() { + @Override + public void run() { + new ChunkListener(); + } + }); } @Override public void debug(final String s) { - this.getLogger().info(ChatColor.translateAlternateColorCodes('&', s)); + Bukkit.getLogger().info(ChatColor.translateAlternateColorCodes('&', s)); } @Override public File getDirectory() { - return this.getDataFolder(); + return plugin.getDataFolder(); } @Override public void setupCommand(final String label, final FaweCommand cmd) { - this.getCommand(label).setExecutor(new BukkitCommand(cmd)); + plugin.getCommand(label).setExecutor(new BukkitCommand(cmd)); } @Override @@ -115,7 +118,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { @Override public void startMetrics() { - Metrics metrics = new Metrics(this); + Metrics metrics = new Metrics(plugin); metrics.start(); debug("&6Metrics enabled."); } @@ -131,7 +134,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { */ @Override public void setupWEListener() { - this.getServer().getPluginManager().registerEvents(new WEListener(), this); + Bukkit.getServer().getPluginManager().registerEvents(new WEListener(), plugin); } /** @@ -152,7 +155,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { */ @Override public TaskManager getTaskManager() { - return new BukkitTaskMan(this); + return new BukkitTaskMan(plugin); } private int[] version; @@ -188,7 +191,7 @@ 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
*/ @Override - public FaweQueue getNewQueue(String world) { + public FaweQueue getNewQueue(String world, boolean dontCareIfFast) { try { Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField(); fieldDirtyCount.setAccessible(true); @@ -200,19 +203,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { } } catch (Throwable ignore) {} try { - if (FaweAPI.checkVersion(this.getVersion(), 1, 9, 0)) { - try { - return new BukkitQueue_1_9_R1(world); - } catch (Throwable e) { - e.printStackTrace(); - } - try { - return new BukkitQueue_1_9(world); - } catch (final Throwable e) { - e.printStackTrace(); - } - } - return new BukkitQueue_1_8(world); + return plugin.getQueue(world); } catch (Throwable ignore) {} if (hasNMS) { debug("====== NO NMS BLOCK PLACER FOUND ======"); @@ -226,6 +217,10 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { return new BukkitQueue_All(world); } + public BukkitMain getPlugin() { + return plugin; + } + @Override public String getWorldName(World world) { return world.getName(); @@ -236,7 +231,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener { */ @Override public EditSessionWrapper getEditSessionWrapper(final EditSession session) { - return new BukkitEditSessionWrapper_1_8(session); + return plugin.getEditSessionWrapper(session); } /** diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/Metrics.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/Metrics.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/Metrics.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/Metrics.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/VaultUtil.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/VaultUtil.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/VaultUtil.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/VaultUtil.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/WEListener.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/WEListener.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/WEListener.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/WEListener.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java similarity index 99% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java index b7cd86bb..ae803b46 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingExtent.java @@ -95,8 +95,6 @@ public class LoggingExtent extends AbstractDelegateExtent { case 57: case 58: case 60: - case 61: - case 62: case 7: case 8: case 9: diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMask.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMask.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMask.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMask.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/BukkitMaskManager.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/FactionsFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsOneFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/FactionsOneFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsOneFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/FactionsOneFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/FactionsUUIDFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/GriefPreventionFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/PlotMeFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/PreciousStonesFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/ResidenceFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/TownyFeature.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/regions/Worldguard.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java similarity index 100% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java similarity index 56% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java rename to bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java index 4b067b9e..366d76da 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java @@ -1,14 +1,9 @@ package com.boydti.fawe.bukkit.v0; -import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.bukkit.v1_8.BukkitChunk_1_8; -import com.boydti.fawe.config.Settings; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.IntegerPair; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.exception.FaweException; -import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.bukkit.BukkitUtil; @@ -16,52 +11,53 @@ import com.sk89q.worldedit.world.biome.BaseBiome; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.Collection; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.event.EventHandler; -import org.bukkit.event.block.BlockPhysicsEvent; -import org.bukkit.event.entity.ItemSpawnEvent; -import org.bukkit.plugin.Plugin; -import org.spigotmc.AsyncCatcher; -public class BukkitQueue_All extends BukkitQueue_0 { +public abstract class BukkitQueue_0 extends NMSMappedFaweQueue { - public BukkitQueue_All(final String world) { + public BukkitQueue_0(final String world) { super(world); - if (getClass() == BukkitQueue_All.class) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - Bukkit.getPluginManager().registerEvents(BukkitQueue_All.this, (Plugin) Fawe.imp()); - } - }); - } } - - private boolean physicsFreeze = false; - - @EventHandler - public void onPhysics(BlockPhysicsEvent event) { - if (physicsFreeze) { - event.setCancelled(true); - } + @Override + public World getWorld(String world) { + return Bukkit.getWorld(world); } - @EventHandler - public void onItemSpawn(ItemSpawnEvent event) { - if (physicsFreeze) { - event.setCancelled(true); - } + @Override + public boolean isChunkLoaded(World world, int x, int z) { + return world.isChunkLoaded(x, z); + } + + @Override + public void refreshChunk(World world, CHUNK chunk) { + return; + } + + @Override + public boolean regenerateChunk(World world, int x, int z) { + return world.regenerateChunk(x, z); + } + + @Override + public boolean fixLighting(FaweChunk fc, boolean fixAll) { + // Not implemented + return true; + } + + @Override + public boolean loadChunk(World impWorld, int x, int z, boolean generate) { + return impWorld.loadChunk(x, z, generate); } private volatile boolean timingsEnabled; @Override public void startSet(boolean parallel) { + ChunkListener.physicsFreeze = true; if (parallel) { try { Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled"); @@ -80,6 +76,7 @@ public class BukkitQueue_All extends BukkitQueue_0 { @Override public void endSet(boolean parallel) { + ChunkListener.physicsFreeze = false; if (parallel) { try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled); } catch (Throwable ignore) {ignore.printStackTrace();} @@ -88,15 +85,9 @@ public class BukkitQueue_All extends BukkitQueue_0 { } @Override - public Collection> sendChunk(Collection> fcs) { - return new ArrayList<>(); - } - - @Override - public boolean setComponents(FaweChunk fc) { + public boolean setComponents(FaweChunk fc) { try { - startSet(); - final BukkitChunk_1_8 fs = ((BukkitChunk_1_8) fc); + final CharFaweChunk fs = ((CharFaweChunk) fc); final Chunk chunk = fs.getChunk(); chunk.load(true); final World world = chunk.getWorld(); @@ -191,115 +182,20 @@ public class BukkitQueue_All extends BukkitQueue_0 { } } } - endSet(); return true; } catch (final Throwable e) { e.printStackTrace(); } - endSet(); return false; } - public void startSet() { - physicsFreeze = true; - try { - // Need to temporarily disable the async catcher since it can't discern safe/unsafe async calls - // The main thread will be locked until it is enabled again (if anything fails it will be enabled again) - AsyncCatcher.enabled = false; - } catch (Throwable ignore) {} - } - - public void endSet() { - physicsFreeze = false; - try { - AsyncCatcher.enabled = true; - } catch (Throwable ignore) {} - } - @Override - public FaweChunk getChunk(int x, int z) { - return new BukkitChunk_1_8(this, x, z); - } - - @Override - public boolean fixLighting(FaweChunk fc, boolean fixAll) { - return true; - } - - public int lastChunkX = Integer.MIN_VALUE; - public int lastChunkZ = Integer.MIN_VALUE; - public int lastChunkY = Integer.MIN_VALUE; - - private Object lastChunk; - private Object lastSection; - - public Object getCachedChunk(int cx, int cz) { - return bukkitWorld.getChunkAt(cx, cz); - } - - public Object getCachedSection(Object chunk, int cy) { - return lastChunk; - } - - public int getCombinedId4Data(Object section, int x, int y, int z) { - Block block = ((Chunk) lastChunk).getBlock(x & 15, y, z & 15); - int combined = block.getTypeId() << 4; - if (FaweCache.hasData(combined)) { - combined += block.getData(); - } - return combined; - } - - private final RunnableVal loadChunk = new RunnableVal() { - @Override - public void run(IntegerPair coord) { - bukkitWorld.loadChunk(coord.x, coord.z, true); - } - }; - - long average = 0; - - @Override - public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { - if (y < 0 || y > 255) { - return 0; - } - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - if (bukkitWorld == null) { - bukkitWorld = Bukkit.getServer().getWorld(world); + public FaweChunk getChunk(final int x, final int z) { + return new CharFaweChunk(this, x, z) { + @Override + public Chunk getNewChunk() { + return getWorld().getChunkAt(x, z); } - lastChunkX = cx; - lastChunkZ = cz; - if (!bukkitWorld.isChunkLoaded(cx, cz)) { - long start = System.currentTimeMillis(); - boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); - if (sync) { - bukkitWorld.loadChunk(cx, cz, true); - } else if (Settings.CHUNK_WAIT > 0) { - loadChunk.value = new IntegerPair(cx, cz); - TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT); - if (!bukkitWorld.isChunkLoaded(cx, cz)) { - throw new FaweException.FaweChunkLoadException(); - } - } else { - return 0; - } - } - lastChunk = getCachedChunk(cx, cz); - lastSection = getCachedSection(lastChunk, cy); - } else if (cy != lastChunkY) { - if (lastChunk == null) { - return 0; - } - lastSection = getCachedSection(lastChunk, cy); - } - - if (lastSection == null) { - return 0; - } - return getCombinedId4Data(lastSection, x, y, z); + }; } } diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java new file mode 100644 index 00000000..5f300e8a --- /dev/null +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java @@ -0,0 +1,26 @@ +package com.boydti.fawe.bukkit.v0; + +import com.boydti.fawe.FaweCache; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.block.Block; + +public class BukkitQueue_All extends BukkitQueue_0 { + public BukkitQueue_All(String world) { + super(world); + } + + public int getCombinedId4Data(Chunk section, int x, int y, int z) { + Block block = ((Chunk) section).getBlock(x & 15, y, z & 15); + int combined = block.getTypeId() << 4; + if (FaweCache.hasData(combined)) { + combined += block.getData(); + } + return combined; + } + + @Override + public Chunk getCachedChunk(World impWorld, int cx, int cz) { + return impWorld.getChunkAt(cx, cz); + } +} diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java new file mode 100644 index 00000000..a2b4eca0 --- /dev/null +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java @@ -0,0 +1,48 @@ +package com.boydti.fawe.bukkit.v0; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.bukkit.FaweBukkit; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.util.TaskManager; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.entity.ItemSpawnEvent; + +public class ChunkListener implements Listener { + public ChunkListener() { + Bukkit.getPluginManager().registerEvents(ChunkListener.this, Fawe.imp().getPlugin()); + TaskManager.IMP.repeat(new Runnable() { + @Override + public void run() { + physicsFreeze = false; + physicsLimit = Settings.PHYSICS_PER_TICK; + itemLimit = Settings.ITEMS_PER_TICK; + } + }, 1); + } + + private int physicsLimit = Settings.PHYSICS_PER_TICK; + private int itemLimit = Settings.ITEMS_PER_TICK; + public static boolean physicsFreeze = false; + + @EventHandler(priority = EventPriority.LOWEST) + public void onPhysics(BlockPhysicsEvent event) { + if (physicsFreeze) { + event.setCancelled(true); + } else if (--physicsLimit < 0) { + physicsFreeze = true; + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onItemSpawn(ItemSpawnEvent event) { + if (physicsFreeze) { + event.setCancelled(true); + } else if (--itemLimit < 0) { + physicsFreeze = true; + } + } +} diff --git a/bukkit/src/main/resources/config.yml b/bukkit0/src/main/resources/config.yml similarity index 100% rename from bukkit/src/main/resources/config.yml rename to bukkit0/src/main/resources/config.yml diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit0/src/main/resources/plugin.yml similarity index 100% rename from bukkit/src/main/resources/plugin.yml rename to bukkit0/src/main/resources/plugin.yml diff --git a/bukkit18/build.gradle b/bukkit18/build.gradle new file mode 100644 index 00000000..b42b8cf6 --- /dev/null +++ b/bukkit18/build.gradle @@ -0,0 +1,21 @@ +dependencies { + compile project(':bukkit0') + compile 'org.bukkit.craftbukkit:CraftBukkit:1.8.8' +} + +apply plugin: 'com.github.johnrengelman.shadow' +// We only want the shadow jar produced +jar.enabled = false +shadowJar { + dependencies { + include(dependency(':bukkit0')) + } + archiveName = "${parent.name}-${project.name}.jar" + destinationDir = file '../target' +} +shadowJar.doLast { + task -> + ant.checksum file: task.archivePath +} + +build.dependsOn(shadowJar); \ No newline at end of file diff --git a/bukkit18/build/resources/main/plugin.yml b/bukkit18/build/resources/main/plugin.yml new file mode 100644 index 00000000..da7fe10a --- /dev/null +++ b/bukkit18/build/resources/main/plugin.yml @@ -0,0 +1,43 @@ +name: FastAsyncWorldEdit +main: com.boydti.fawe.bukkit.v1_8.BukkitMain_1_8 +version: 3.4.2 +description: Fast Async WorldEdit plugin +authors: [Empire92] +loadbefore: [WorldEdit] +load: STARTUP +database: false +#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] +commands: + wea: + description: (FAWE) Bypass WorldEdit processing and area restrictions + aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere] + usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass" + fixlighting: + description: (FAWE) Fix the lighting in your current chunk + aliases: [/fixlighting] + stream: + description: (FAWE) Stream a schematic into the world + aliases: [/stream] + fawe: + description: (FAWE) Reload the plugin + aliases: [/fawe,/fawereload] + wrg: + description: (FAWE) Select your current WorldEdit Region. + aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region] + frb: + description: (FAWE) Rollback an edit + aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb] + fcancel: + description: (FAWE) Cancel your edit + aliases: [fawecancel,/fcancel,/cancel,/fawecancel] +permissions: + fawe.bypass: + default: false + fawe.admin: + default: false + fawe.stream: + default: false + fawe.fixlighting: + default: false + fawe.reload: + default: false diff --git a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java new file mode 100644 index 00000000..409cd0be --- /dev/null +++ b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java @@ -0,0 +1,24 @@ +package com.boydti.fawe.bukkit.v1_8; + +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.util.FaweQueue; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; + +public class BukkitChunk_1_8 extends CharFaweChunk { + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param parent + * @param x + * @param z + */ + public BukkitChunk_1_8(FaweQueue parent, int x, int z) { + super(parent, x, z); + } + + @Override + public Chunk getNewChunk() { + return Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ()); + } +} diff --git a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitMain_1_8.java b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitMain_1_8.java new file mode 100644 index 00000000..034ad279 --- /dev/null +++ b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitMain_1_8.java @@ -0,0 +1,18 @@ +package com.boydti.fawe.bukkit.v1_8; + +import com.boydti.fawe.bukkit.BukkitMain; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.object.EditSessionWrapper; +import com.sk89q.worldedit.EditSession; + +public class BukkitMain_1_8 extends BukkitMain { + @Override + public BukkitQueue_0 getQueue(String world) { + return new BukkitQueue18R3(world); + } + + @Override + public EditSessionWrapper getEditSessionWrapper(EditSession session) { + return new EditSessionWrapper(session); + } +} diff --git a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java new file mode 100644 index 00000000..ed43b78f --- /dev/null +++ b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java @@ -0,0 +1,327 @@ +package com.boydti.fawe.bukkit.v1_8; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.BukkitPlayer; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.FaweLocation; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.PseudoRandom; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.ChunkCoordIntPair; +import net.minecraft.server.v1_8_R3.ChunkSection; +import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk; +import net.minecraft.server.v1_8_R3.PlayerConnection; +import net.minecraft.server.v1_8_R3.TileEntity; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_8_R3.CraftChunk; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; + +public class BukkitQueue18R3 extends BukkitQueue_0 { + + public BukkitQueue18R3(final String world) { + super(world); + } + + @Override + public boolean isChunkLoaded(int x, int z) { + return getWorld().isChunkLoaded(x, z); + } + + public World getWorld(String world) { + return Bukkit.getWorld(world); + } + + @Override + public boolean regenerateChunk(World world, int x, int z) { + return world.regenerateChunk(x, z); + } + + @Override + public boolean loadChunk(World world, int x, int z, boolean generate) { + return getCachedChunk(world, x, z) != null; + } + + @Override + public ChunkSection[] getCachedChunk(World world, int x, int z) { + Chunk chunk = world.getChunkAt(x, z); + if (chunk == null) { + return null; + } + if (!chunk.isLoaded()) { + chunk.load(true); + } + return ((CraftChunk) chunk).getHandle().getSections(); + } + + @Override + public int getCombinedId4Data(char[] ls, int x, int y, int z) { + return ls[FaweCache.CACHE_J[y][x & 15][z & 15]]; + } + + @Override + public boolean isChunkLoaded(World world, int x, int z) { + return world.isChunkLoaded(x, z); + } + + @Override + public boolean setComponents(FaweChunk fc) { + CharFaweChunk fs = (CharFaweChunk) fc; + CraftChunk chunk = (CraftChunk) fs.getChunk(); + net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle(); + net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld(); + try { + final boolean flag = getWorld().getEnvironment() == World.Environment.NORMAL; + // Sections + ChunkSection[] sections = nmsChunk.getSections(); + Map tiles = nmsChunk.getTileEntities(); + Collection[] entities = nmsChunk.getEntitySlices(); + // Trim tiles + Set> entryset = tiles.entrySet(); + Iterator> iterator = entryset.iterator(); + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + BlockPosition pos = tile.getKey(); + int lx = pos.getX() & 15; + int ly = pos.getY(); + int lz = pos.getZ() & 15; + int j = FaweCache.CACHE_I[ly][lx][lz]; + int k = FaweCache.CACHE_J[ly][lx][lz]; + char[] array = fs.getIdArray(j); + if (array == null) { + continue; + } + if (array[k] != 0) { + iterator.remove(); + } + } + // Trim entities + for (int i = 0; i < 16; i++) { + if ((entities[i] != null) && (fs.getCount(i) >= 4096)) { + entities[i].clear(); + } + } + // Efficiently merge sections + for (int j = 0; j < sections.length; j++) { + if (fs.getCount(j) == 0) { + continue; + } + char[] newArray = fs.getIdArray(j); + if (newArray == null) { + continue; + } + ChunkSection section = sections[j]; + if ((section == null) || (fs.getCount(j) >= 4096)) { + section = new ChunkSection(j << 4, flag, newArray); + sections[j] = section; + continue; + } + char[] currentArray = section.getIdArray(); + boolean fill = true; + int solid = 0; + for (int k = 0; k < newArray.length; k++) { + char n = newArray[k]; + switch (n) { + case 0: + fill = false; + continue; + case 1: + fill = false; + if (currentArray[k] > 1) { + solid++; + } + currentArray[k] = 0; + continue; + default: + solid++; + currentArray[k] = n; + continue; + } + } + setCount(0, solid, section); + if (fill) { + fs.setCount(j, Short.MAX_VALUE); + } + } +// // Clear + } catch (Throwable e) { + e.printStackTrace(); + } + int[][] biomes = fs.biomes; + if (biomes != null) { + for (int x = 0; x < 16; x++) { + int[] array = biomes[x]; + if (array == null) { + continue; + } + for (int z = 0; z < 16; z++) { + int biome = array[z]; + if (biome == 0) { + continue; + } + nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; + } + } + } + sendChunk(fc); + return true; + } + + public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { + Class clazz = section.getClass(); + Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount"); + Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount"); + fieldTickingBlockCount.setAccessible(true); + fieldNonEmptyBlockCount.setAccessible(true); + fieldTickingBlockCount.set(section, tickingBlockCount); + fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); + } + + @Override + public void refreshChunk(World world, Chunk chunk) { + if (!chunk.isLoaded()) { + return; + } + net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + ChunkCoordIntPair pos = nmsChunk.j(); + int cx = pos.x; + int cz = pos.z; + int view = Bukkit.getViewDistance(); + for (FawePlayer fp : Fawe.get().getCachedPlayers()) { + BukkitPlayer bukkitPlayer = (BukkitPlayer) fp; + if (!bukkitPlayer.getWorld().equals(world)) { + continue; + } + net.minecraft.server.v1_8_R3.EntityPlayer nmsPlayer = ((CraftPlayer) bukkitPlayer.parent).getHandle(); + FaweLocation loc = fp.getLocation(); + int px = loc.x >> 4; + int pz = loc.z >> 4; + int dx = Math.abs(cx - (loc.x >> 4)); + int dz = Math.abs(cz - (loc.z >> 4)); + if ((dx > view) || (dz > view)) { + continue; + } + PlayerConnection con = nmsPlayer.playerConnection; + con.sendPacket(new PacketPlayOutMapChunk(nmsChunk, false, 65535)); + } + } + + @Override + public boolean fixLighting(FaweChunk chunk, boolean fixAll) { + try { + CharFaweChunk fc = (CharFaweChunk) chunk; + CraftChunk craftChunk = (CraftChunk) fc.getChunk(); + net.minecraft.server.v1_8_R3.Chunk nmsChunk = craftChunk.getHandle(); + if (!craftChunk.isLoaded()) { + return false; + } + nmsChunk.initLighting(); + if (fc.getTotalRelight() == 0 && !fixAll) { + return true; + } + ChunkSection[] sections = nmsChunk.getSections(); + net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld(); + + int X = fc.getX() << 4; + int Z = fc.getZ() << 4; + + BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); + for (int j = 0; j < sections.length; j++) { + ChunkSection section = sections[j]; + if (section == null) { + continue; + } + if ((fc.getRelight(j) == 0 && !fixAll) || fc.getCount(j) == 0 || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) { + continue; + } + char[] array = section.getIdArray(); + int l = PseudoRandom.random.random(2); + for (int k = 0; k < array.length; k++) { + int i = array[k]; + if (i < 16) { + continue; + } + short id = (short) (i >> 4); + switch (id) { // Lighting + default: + if (!fixAll) { + continue; + } + if ((k & 1) == l) { + l = 1 - l; + continue; + } + case 10: + case 11: + case 39: + case 40: + case 50: + case 51: + case 62: + case 74: + case 76: + case 89: + case 122: + case 124: + case 130: + case 138: + case 169: + int x = FaweCache.CACHE_X[j][k]; + int y = FaweCache.CACHE_Y[j][k]; + int z = FaweCache.CACHE_Z[j][k]; + if (isSurrounded(sections, x, y, z)) { + continue; + } + pos.c(X + x, y, Z + z); + nmsWorld.x(pos); + } + } + } + return true; + } catch (Throwable e) { + if (Thread.currentThread() == Fawe.get().getMainThread()) { + e.printStackTrace(); + } + } + return false; + } + + public boolean isSurrounded(ChunkSection[] sections, int x, int y, int z) { + return isSolid(getId(sections, x, y + 1, z)) + && isSolid(getId(sections, x + 1, y - 1, z)) + && isSolid(getId(sections, x - 1, y, z)) + && isSolid(getId(sections, x, y, z + 1)) + && isSolid(getId(sections, x, y, z - 1)); + } + + public boolean isSolid(int i) { + return Material.getMaterial(i).isOccluding(); + } + + public int getId(ChunkSection[] sections, int x, int y, int z) { + if (x < 0 || x > 15 || z < 0 || z > 15) { + return 1; + } + if (y < 0 || y > 255) { + return 1; + } + int i = FaweCache.CACHE_I[y][x][z]; + ChunkSection section = sections[i]; + if (section == null) { + return 0; + } + char[] array = section.getIdArray(); + int j = FaweCache.CACHE_J[y][x][z]; + return array[j] >> 4; + } +} diff --git a/bukkit18/src/main/resources/plugin.yml b/bukkit18/src/main/resources/plugin.yml new file mode 100644 index 00000000..da7fe10a --- /dev/null +++ b/bukkit18/src/main/resources/plugin.yml @@ -0,0 +1,43 @@ +name: FastAsyncWorldEdit +main: com.boydti.fawe.bukkit.v1_8.BukkitMain_1_8 +version: 3.4.2 +description: Fast Async WorldEdit plugin +authors: [Empire92] +loadbefore: [WorldEdit] +load: STARTUP +database: false +#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] +commands: + wea: + description: (FAWE) Bypass WorldEdit processing and area restrictions + aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere] + usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass" + fixlighting: + description: (FAWE) Fix the lighting in your current chunk + aliases: [/fixlighting] + stream: + description: (FAWE) Stream a schematic into the world + aliases: [/stream] + fawe: + description: (FAWE) Reload the plugin + aliases: [/fawe,/fawereload] + wrg: + description: (FAWE) Select your current WorldEdit Region. + aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region] + frb: + description: (FAWE) Rollback an edit + aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb] + fcancel: + description: (FAWE) Cancel your edit + aliases: [fawecancel,/fcancel,/cancel,/fawecancel] +permissions: + fawe.bypass: + default: false + fawe.admin: + default: false + fawe.stream: + default: false + fawe.fixlighting: + default: false + fawe.reload: + default: false diff --git a/bukkit19/build.gradle b/bukkit19/build.gradle new file mode 100644 index 00000000..e91426b5 --- /dev/null +++ b/bukkit19/build.gradle @@ -0,0 +1,22 @@ +dependencies { + compile project(':bukkit0') + compile 'org.bukkit.craftbukkit:CraftBukkit:1.9.2' +} + +apply plugin: 'com.github.johnrengelman.shadow' +// We only want the shadow jar produced +jar.enabled = false +shadowJar { + dependencies { + include(dependency(':bukkit0')) + include(dependency(':core')) + } + archiveName = "${parent.name}-${project.name}.jar" + destinationDir = file '../target' +} +shadowJar.doLast { + task -> + ant.checksum file: task.archivePath +} + +build.dependsOn(shadowJar); \ No newline at end of file diff --git a/bukkit19/build/libs/bukkit19-all.jar b/bukkit19/build/libs/bukkit19-all.jar new file mode 100644 index 00000000..53907e29 Binary files /dev/null and b/bukkit19/build/libs/bukkit19-all.jar differ diff --git a/bukkit19/build/libs/bukkit19-all.jar.MD5 b/bukkit19/build/libs/bukkit19-all.jar.MD5 new file mode 100644 index 00000000..75a52873 --- /dev/null +++ b/bukkit19/build/libs/bukkit19-all.jar.MD5 @@ -0,0 +1 @@ +0b4c7b4aeeea42cb68e5ccfcc8c82b14 diff --git a/bukkit19/build/resources/main/plugin.yml b/bukkit19/build/resources/main/plugin.yml new file mode 100644 index 00000000..f7d53e1c --- /dev/null +++ b/bukkit19/build/resources/main/plugin.yml @@ -0,0 +1,43 @@ +name: FastAsyncWorldEdit +main: com.boydti.fawe.bukkit.v1_9.BukkitMain_1_9 +version: 3.4.2 +description: Fast Async WorldEdit plugin +authors: [Empire92] +loadbefore: [WorldEdit] +load: STARTUP +database: false +#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] +commands: + wea: + description: (FAWE) Bypass WorldEdit processing and area restrictions + aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere] + usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass" + fixlighting: + description: (FAWE) Fix the lighting in your current chunk + aliases: [/fixlighting] + stream: + description: (FAWE) Stream a schematic into the world + aliases: [/stream] + fawe: + description: (FAWE) Reload the plugin + aliases: [/fawe,/fawereload] + wrg: + description: (FAWE) Select your current WorldEdit Region. + aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region] + frb: + description: (FAWE) Rollback an edit + aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb] + fcancel: + description: (FAWE) Cancel your edit + aliases: [fawecancel,/fcancel,/cancel,/fawecancel] +permissions: + fawe.bypass: + default: false + fawe.admin: + default: false + fawe.stream: + default: false + fawe.fixlighting: + default: false + fawe.reload: + default: false diff --git a/bukkit19/build/tmp/shadowJar/MANIFEST.MF b/bukkit19/build/tmp/shadowJar/MANIFEST.MF new file mode 100644 index 00000000..59499bce --- /dev/null +++ b/bukkit19/build/tmp/shadowJar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java new file mode 100644 index 00000000..06bbaf77 --- /dev/null +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java @@ -0,0 +1,114 @@ +package com.boydti.fawe.bukkit.v1_9; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.util.FaweQueue; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import net.minecraft.server.v1_9_R1.Block; +import net.minecraft.server.v1_9_R1.DataBits; +import net.minecraft.server.v1_9_R1.DataPalette; +import net.minecraft.server.v1_9_R1.DataPaletteBlock; +import net.minecraft.server.v1_9_R1.DataPaletteGlobal; +import net.minecraft.server.v1_9_R1.IBlockData; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; + +public class BukkitChunk_1_9 extends CharFaweChunk { + + public DataPaletteBlock[] sectionPalettes; + + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param parent + * @param x + * @param z + */ + public BukkitChunk_1_9(FaweQueue parent, int x, int z) { + super(parent, x, z); + } + + @Override + public Chunk getNewChunk() { + return Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ()); + } + + @Override + public CharFaweChunk copy(boolean shallow) { + BukkitChunk_1_9 value = (BukkitChunk_1_9) super.copy(shallow); + if (sectionPalettes != null) { + value.sectionPalettes = new DataPaletteBlock[16]; + try { + Field fieldBits = DataPaletteBlock.class.getDeclaredField("b"); + fieldBits.setAccessible(true); + Field fieldPalette = DataPaletteBlock.class.getDeclaredField("c"); + fieldPalette.setAccessible(true); + Field fieldSize = DataPaletteBlock.class.getDeclaredField("e"); + fieldSize.setAccessible(true); + for (int i = 0; i < sectionPalettes.length; i++) { + DataPaletteBlock current = sectionPalettes[i]; + if (current == null) { + continue; + } + DataPaletteBlock paletteBlock = new DataPaletteBlock(); + // Clone palette + DataPalette currentPalette = (DataPalette) fieldPalette.get(paletteBlock); + if (!(currentPalette instanceof DataPaletteGlobal)) { + try { + Method resize = DataPaletteBlock.class.getDeclaredMethod("b", int.class); + resize.setAccessible(true); + resize.invoke(paletteBlock, 128); + } catch (Throwable e) { + e.printStackTrace(); + } + } + currentPalette = (DataPalette) fieldPalette.get(paletteBlock); + fieldPalette.set(paletteBlock, currentPalette); + // Clone size + fieldSize.set(paletteBlock, fieldSize.get(current)); + // Clone pallete + DataBits currentBits = (DataBits) fieldBits.get(current); + DataBits newBits = new DataBits(1, 0); + for (Field field : DataBits.class.getDeclaredFields()) { + field.setAccessible(true); + field.set(newBits, field.get(currentBits)); + } + fieldBits.set(paletteBlock, newBits); + value.sectionPalettes[i] = paletteBlock; + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + return value; + } + + public void optimize() { + if (sectionPalettes != null) { + return; + } + char[][] arrays = getIdArrays(); + IBlockData lastBlock = null; + char lastChar = Character.MAX_VALUE; + for (int layer = 0; layer < 16; layer++) { + if (getCount(layer) > 0) { + if (sectionPalettes == null) { + sectionPalettes = new DataPaletteBlock[16]; + } + DataPaletteBlock palette = sectionPalettes[layer] = new DataPaletteBlock(); + char[] blocks = getIdArray(layer); + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + char combinedId = blocks[FaweCache.CACHE_J[y][x][z]]; + if (combinedId > 1) { + palette.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF)); + } + } + } + } + } + } + } +} diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitMain_1_9.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitMain_1_9.java new file mode 100644 index 00000000..81e07910 --- /dev/null +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitMain_1_9.java @@ -0,0 +1,18 @@ +package com.boydti.fawe.bukkit.v1_9; + +import com.boydti.fawe.bukkit.BukkitMain; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.object.EditSessionWrapper; +import com.sk89q.worldedit.EditSession; + +public class BukkitMain_1_9 extends BukkitMain { + @Override + public BukkitQueue_0 getQueue(String world) { + return new BukkitQueue_1_9_R1(world); + } + + @Override + public EditSessionWrapper getEditSessionWrapper(EditSession session) { + return new EditSessionWrapper(session); + } +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java similarity index 76% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java rename to bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java index 1988b3c8..565a0900 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java @@ -2,20 +2,17 @@ package com.boydti.fawe.bukkit.v1_9; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.bukkit.v0.BukkitQueue_All; -import com.boydti.fawe.bukkit.v1_8.BukkitChunk_1_8; -import com.boydti.fawe.config.Settings; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.util.MemUtil; -import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.LocalSession; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayDeque; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; @@ -24,6 +21,7 @@ import java.util.Map; import java.util.Map.Entry; import net.minecraft.server.v1_9_R1.Block; import net.minecraft.server.v1_9_R1.BlockPosition; +import net.minecraft.server.v1_9_R1.Blocks; import net.minecraft.server.v1_9_R1.ChunkSection; import net.minecraft.server.v1_9_R1.DataBits; import net.minecraft.server.v1_9_R1.DataPalette; @@ -43,25 +41,26 @@ import org.bukkit.entity.Player; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; -public class BukkitQueue_1_9_R1 extends BukkitQueue_All { +public class BukkitQueue_1_9_R1 extends BukkitQueue_0 { - public BukkitQueue_1_9_R1(final String world) throws NoSuchMethodException, RuntimeException { + public BukkitQueue_1_9_R1(final String world) { super(world); } - public Object getCachedChunk(int cx, int cz) { - CraftChunk chunk = (CraftChunk) bukkitWorld.getChunkAt(cx, cz); + @Override + public ChunkSection[] getCachedChunk(World world, int cx, int cz) { + CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz); return chunk.getHandle().getSections(); } - public Object getCachedSection(Object chunk, int cy) { - ChunkSection[] chunkSections = (ChunkSection[]) chunk; + @Override + public DataPaletteBlock getCachedSection(ChunkSection[] chunkSections, int cy) { ChunkSection nibble = chunkSections[cy]; return nibble != null ? nibble.getBlocks() : null; } - public int getCombinedId4Data(Object section, int x, int y, int z) { - DataPaletteBlock lastSection = (DataPaletteBlock) section; + @Override + public int getCombinedId4Data(DataPaletteBlock lastSection, int x, int y, int z) { IBlockData ibd = lastSection.a(x & 15, y & 15, z & 15); Block block = ibd.getBlock(); int id = Block.getId(block); @@ -73,37 +72,15 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All { } @Override - public Collection> sendChunk(final Collection> fcs) { - for (final FaweChunk fc : fcs) { - sendChunk(fc); - } - return new ArrayList<>(); - } - - public void sendChunk(final FaweChunk fc) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING; - TaskManager.IMP.sync(new Runnable() { - @Override - public void run() { - if (!result) { - fixLighting(fc, Settings.FIX_ALL_LIGHTING); - } - final Chunk chunk = fc.getChunk(); - chunk.getWorld().refreshChunk(fc.getX(), fc.getZ()); - } - }, false); - } - }, Settings.ASYNC_LIGHTING); + public void refreshChunk(World world, Chunk fc) { + world.refreshChunk(fc.getX(), fc.getZ()); } @Override - public boolean fixLighting(final FaweChunk pc, final boolean fixAll) { + public boolean fixLighting(final FaweChunk pc, final boolean fixAll) { try { - final BukkitChunk_1_8 bc = (BukkitChunk_1_8) pc; - final Chunk chunk = bc.getChunk(); + final CharFaweChunk bc = (CharFaweChunk) pc; + final Chunk chunk = (Chunk) bc.getChunk(); if (!chunk.isLoaded()) { if (Fawe.get().getMainThread() != Thread.currentThread()) { return false; @@ -232,10 +209,16 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All { fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); } + public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException { + Field fieldSection = ChunkSection.class.getDeclaredField("blockIds"); + fieldSection.setAccessible(true); + fieldSection.set(section, palette); + } + @Override - public boolean setComponents(final FaweChunk pc) { - final BukkitChunk_1_8 fs = (BukkitChunk_1_8) pc; - final Chunk chunk = pc.getChunk(); + public boolean setComponents(final FaweChunk pc) { + final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc; + final Chunk chunk = (Chunk) fs.getChunk(); final World world = chunk.getWorld(); chunk.load(true); try { @@ -286,10 +269,10 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All { entities[i].clear(); } } - // Efficiently merge sections for (int j = 0; j < sections.length; j++) { - if (fs.getCount(j) == 0) { + int count = fs.getCount(j); + if (count == 0) { continue; } final char[] array = fs.getIdArray(j); @@ -298,7 +281,23 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All { } ChunkSection section = sections[j]; if (section == null) { - sections[j] = new ChunkSection(j << 4, flag, array); + if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { + section = sections[j] = new ChunkSection(j << 4, flag); + setPalette(section, fs.sectionPalettes[j]); + setCount(0, count - fs.getAir(j), section); + continue; + } else { + sections[j] = new ChunkSection(j << 4, flag, array); + } + continue; + } else if (count >= 4096) { + if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) { + setPalette(section, fs.sectionPalettes[j]); + setCount(0, count - fs.getAir(j), section); + continue; + } else { + sections[j] = new ChunkSection(j << 4, flag, array); + } continue; } DataPaletteBlock nibble = section.getBlocks(); @@ -309,95 +308,25 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All { Field fieldPalette = nibble.getClass().getDeclaredField("c"); fieldPalette.setAccessible(true); DataPalette palette = (DataPalette) fieldPalette.get(nibble); - - if (fs.getCount(j) >= 4096) { - int tickingBlockCount = 0; - int nonEmptyBlockCount = fs.getCount(j) - fs.getAir(j); - setCount(tickingBlockCount, nonEmptyBlockCount, section); - int lastId = -1; - int lastBit = -1; - for (int i = 0; i < array.length; i++) { - int value = array[i]; - if (value != lastId) { - lastId = value; - int id = lastId >> 4; - int data = lastId & 0xF; - IBlockData ibd = Block.getById(id).fromLegacyData(data); - lastBit = palette.a(ibd); - palette = (DataPalette) fieldPalette.get(nibble); - bits = (DataBits) fieldBits.get(nibble); - } - bits.a(i, lastBit); - } - continue; - } - boolean fill = true; int nonEmptyBlockCount = 0; - int lastId = -1; - int lastBit = -1; - for (int k = 0; k < array.length; k++) { - final char combined = array[k]; - switch (combined) { - case 0: - int existingBit = bits.a(k); - if (existingBit != lastBit) { - palette = (DataPalette) fieldPalette.get(nibble); - bits = (DataBits) fieldBits.get(nibble); - lastBit = existingBit; - IBlockData ibd = palette.a(existingBit); - if (ibd == null) { - fill = false; + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + char combinedId = array[FaweCache.CACHE_J[y][x][z]]; + switch (combinedId) { + case 0: continue; - } - Block block = ibd.getBlock(); - int id = Block.getId(block); - if (FaweCache.hasData(id)) { - lastId = (id << 4) + block.toLegacyData(ibd); - } else { - lastId = id << 4; - } + case 1: + // TODO check existing + nibble.setBlock(x, y, z, Blocks.AIR.getBlockData()); + continue; + default: + nonEmptyBlockCount++; + nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF)); } - if (lastId != 0) { - nonEmptyBlockCount++; - } else { - fill = false; - } - continue; - case 1: { - fill = false; - int value = 0; - if (value != lastId) { - lastId = value; - int id = lastId >> 4; - int data = lastId & 0xF; - IBlockData ibd = Block.getById(id).fromLegacyData(data); - lastBit = palette.a(ibd); - palette = (DataPalette) fieldPalette.get(nibble); - bits = (DataBits) fieldBits.get(nibble); - } - bits.a(k, lastBit); - continue; - } - default: { - nonEmptyBlockCount++; - int value = combined; - if (value != lastId) { - lastId = value; - int id = lastId >> 4; - int data = lastId & 0xF; - IBlockData ibd = Block.getById(id).fromLegacyData(data); - lastBit = palette.a(ibd); - palette = (DataPalette) fieldPalette.get(nibble); - bits = (DataBits) fieldBits.get(nibble); - } - bits.a(k, lastBit); - continue; } } } - if (fill) { - fs.setCount(j, Short.MAX_VALUE); - } setCount(0, nonEmptyBlockCount, section); } // Clear @@ -534,11 +463,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All { players = null; } - @Override - public FaweChunk getChunk(int x, int z) { - return new BukkitChunk_1_8(this, x, z); - } - public boolean unloadChunk(final String world, final Chunk chunk) { net.minecraft.server.v1_9_R1.Chunk c = ((CraftChunk) chunk).getHandle(); c.mustSave = false; @@ -674,4 +598,9 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All { } return null; } + + @Override + public FaweChunk getChunk(int x, int z) { + return new BukkitChunk_1_9(this, x, z); + } } diff --git a/bukkit19/src/main/resources/plugin.yml b/bukkit19/src/main/resources/plugin.yml new file mode 100644 index 00000000..f7d53e1c --- /dev/null +++ b/bukkit19/src/main/resources/plugin.yml @@ -0,0 +1,43 @@ +name: FastAsyncWorldEdit +main: com.boydti.fawe.bukkit.v1_9.BukkitMain_1_9 +version: 3.4.2 +description: Fast Async WorldEdit plugin +authors: [Empire92] +loadbefore: [WorldEdit] +load: STARTUP +database: false +#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] +commands: + wea: + description: (FAWE) Bypass WorldEdit processing and area restrictions + aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere] + usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass" + fixlighting: + description: (FAWE) Fix the lighting in your current chunk + aliases: [/fixlighting] + stream: + description: (FAWE) Stream a schematic into the world + aliases: [/stream] + fawe: + description: (FAWE) Reload the plugin + aliases: [/fawe,/fawereload] + wrg: + description: (FAWE) Select your current WorldEdit Region. + aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region] + frb: + description: (FAWE) Rollback an edit + aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb] + fcancel: + description: (FAWE) Cancel your edit + aliases: [fawecancel,/fcancel,/cancel,/fawecancel] +permissions: + fawe.bypass: + default: false + fawe.admin: + default: false + fawe.stream: + default: false + fawe.fixlighting: + default: false + fawe.reload: + default: false diff --git a/core/src/main/java/com/boydti/fawe/FaweAPI.java b/core/src/main/java/com/boydti/fawe/FaweAPI.java index ba676685..95ca3f78 100644 --- a/core/src/main/java/com/boydti/fawe/FaweAPI.java +++ b/core/src/main/java/com/boydti/fawe/FaweAPI.java @@ -84,7 +84,7 @@ public class FaweAPI { * @return */ public FaweQueue createQueue(String worldName, boolean autoqueue) { - return SetQueue.IMP.getNewQueue(worldName, autoqueue); + return SetQueue.IMP.getNewQueue(worldName, true, autoqueue); } public static World getWorld(String worldName) { @@ -295,7 +295,7 @@ public class FaweAPI { * @param fixAll */ public static void fixLighting(String world, int x, int z, final boolean fixAll) { - FaweQueue queue = SetQueue.IMP.getNewQueue(world, false); + FaweQueue queue = SetQueue.IMP.getNewQueue(world, true, false); queue.fixLighting(queue.getChunk(x, z), fixAll); } @@ -305,7 +305,7 @@ public class FaweAPI { * @param fixAll */ public static void fixLighting(final Chunk chunk, final boolean fixAll) { - FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName(), false); + FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName(), true, false); queue.fixLighting(queue.getChunk(chunk.getX(), chunk.getZ()), fixAll); } @@ -388,7 +388,7 @@ public class FaweAPI { tagMap = null; tag = null; - FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world, true); + FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world, true, true); for (int y = 0; y < height; y++) { final int yy = y_offset + y; diff --git a/core/src/main/java/com/boydti/fawe/FaweCache.java b/core/src/main/java/com/boydti/fawe/FaweCache.java index b97f99ad..6bb970ad 100644 --- a/core/src/main/java/com/boydti/fawe/FaweCache.java +++ b/core/src/main/java/com/boydti/fawe/FaweCache.java @@ -5,7 +5,13 @@ import com.sk89q.worldedit.CuboidClipboard; import com.sk89q.worldedit.blocks.BaseBlock; public class FaweCache { + /** + * y | x | z + */ public final static short[][][] CACHE_I = new short[256][16][16]; + /** + * y | x | z + */ public final static short[][][] CACHE_J = new short[256][16][16]; public final static byte[][] CACHE_X = new byte[16][4096]; @@ -105,13 +111,10 @@ public class FaweCache { case 49: case 51: case 52: - case 54: case 56: case 57: case 58: case 60: - case 61: - case 62: case 7: case 8: case 9: diff --git a/core/src/main/java/com/boydti/fawe/IFawe.java b/core/src/main/java/com/boydti/fawe/IFawe.java index 2baa9c48..36ca0004 100644 --- a/core/src/main/java/com/boydti/fawe/IFawe.java +++ b/core/src/main/java/com/boydti/fawe/IFawe.java @@ -29,7 +29,7 @@ public interface IFawe { public int[] getVersion(); - public FaweQueue getNewQueue(String world); + public FaweQueue getNewQueue(String world, boolean fast); public String getWorldName(World world); diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java index 39425d0a..9e6ead21 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -22,7 +22,6 @@ public class Settings { public static boolean ENABLE_HARD_LIMIT = true; public static boolean STORE_HISTORY_ON_DISK = false; public static boolean STORE_CLIPBOARD_ON_DISK = false; - public static int DELETE_HISTORY_AFTER_DAYS = 7; public static int DELETE_CLIPBOARD_AFTER_DAYS = 1; public static int COMPRESSION_LEVEL = 0; @@ -39,6 +38,8 @@ public class Settings { public static int UNSAFE_PARALLEL_THREADS = 1; public static boolean FIX_ALL_LIGHTING = true; public static boolean ASYNC_LIGHTING = true; + public static int PHYSICS_PER_TICK = 1337; + public static int ITEMS_PER_TICK = 1337; public static HashMap limits; @@ -103,6 +104,9 @@ public class Settings { options.put("extent.debug", EXTENT_DEBUG); options.put("metrics", METRICS); + options.put("tick-limiter.physics", PHYSICS_PER_TICK); + options.put("tick-limiter.items", ITEMS_PER_TICK); + // Default limit FaweLimit defaultLimit = new FaweLimit(); if (!config.contains("limits.default")) { @@ -141,6 +145,9 @@ public class Settings { EXTENT_DEBUG = config.getBoolean("extent.debug"); STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk"); DELETE_CLIPBOARD_AFTER_DAYS = config.getInt("clipboard.delete-after-days"); + PHYSICS_PER_TICK = config.getInt("tick-limiter.physics"); + ITEMS_PER_TICK = config.getInt("tick-limiter.items"); + if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) { LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE; } diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java similarity index 88% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java rename to core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java index 34de9504..8cc8b363 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitChunk_1_8.java +++ b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.v1_8; +package com.boydti.fawe.example; import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.FaweChunk; @@ -6,24 +6,25 @@ import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.MainUtil; import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.Arrays; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -public class BukkitChunk_1_8 extends FaweChunk { +public abstract class CharFaweChunk extends FaweChunk { - private char[][] ids; + public char[][] ids; + public short[] count; + public short[] air; + public short[] relight; + public int[][] biomes; - private short[] count; - private short[] air; - private short[] relight; - private int[][] biomes; - - public Chunk chunk; + public T chunk; /** * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param parent + * @param x + * @param z */ - public BukkitChunk_1_8(FaweQueue parent, int x, int z) { + public CharFaweChunk(FaweQueue parent, int x, int z) { super(parent, x, z); this.ids = new char[16][]; this.count = new short[16]; @@ -32,13 +33,15 @@ public class BukkitChunk_1_8 extends FaweChunk { } @Override - public Chunk getChunk() { + public T getChunk() { if (this.chunk == null) { - this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ()); + this.chunk = getNewChunk(); } return this.chunk; } + public abstract T getNewChunk(); + @Override public void setLoc(final FaweQueue parent, int x, int z) { super.setLoc(parent, x, z); @@ -199,15 +202,17 @@ public class BukkitChunk_1_8 extends FaweChunk { case 130: case 76: case 62: + case 50: this.relight[i]++; case 54: case 146: case 61: case 65: case 68: - if (data < 2) { - data = 2; - } +// if (data < 2) { +// data = 2; +// } + default: vs[j] = (char) ((id << 4) + data); return; @@ -227,8 +232,8 @@ public class BukkitChunk_1_8 extends FaweChunk { } @Override - public FaweChunk copy(boolean shallow) { - BukkitChunk_1_8 copy = new BukkitChunk_1_8(getParent(), getX(), getZ()); + public CharFaweChunk copy(boolean shallow) { + CharFaweChunk copy = (CharFaweChunk) getParent().getChunk(getX(), getZ()); if (shallow) { copy.ids = ids; copy.air = air; diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java b/core/src/main/java/com/boydti/fawe/example/IntFaweChunk.java similarity index 90% rename from bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java rename to core/src/main/java/com/boydti/fawe/example/IntFaweChunk.java index 96dec352..de24290f 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java +++ b/core/src/main/java/com/boydti/fawe/example/IntFaweChunk.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.v1_9; +package com.boydti.fawe.example; import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.FaweChunk; @@ -6,24 +6,26 @@ import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.MainUtil; import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.Arrays; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -public class BukkitChunk_1_9 extends FaweChunk { +public abstract class IntFaweChunk extends FaweChunk { private int[][] ids; private short[] count; private short[] air; private short[] relight; - public int[][] biomes; + private int[][] biomes; - public Chunk chunk; + private T chunk; /** * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param parent + * @param x + * @param z */ - protected BukkitChunk_1_9(FaweQueue parent, int x, int z) { + public IntFaweChunk(FaweQueue parent, int x, int z) { super(parent, x, z); this.ids = new int[16][]; this.count = new short[16]; @@ -32,13 +34,15 @@ public class BukkitChunk_1_9 extends FaweChunk { } @Override - public Chunk getChunk() { + public T getChunk() { if (this.chunk == null) { - this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ()); + this.chunk = getNewChunk(); } return this.chunk; } + public abstract T getNewChunk(); + @Override public void setLoc(final FaweQueue parent, int x, int z) { super.setLoc(parent, x, z); @@ -197,6 +201,7 @@ public class BukkitChunk_1_9 extends FaweChunk { vs[j] = (id); return; case 130: + case 50: case 76: case 62: this.relight[i]++; @@ -205,9 +210,9 @@ public class BukkitChunk_1_9 extends FaweChunk { case 61: case 65: case 68: - if (data < 2) { - data = 2; - } +// if (data < 2) { +// data = 2; +// } default: vs[j] = id + (data << 12); return; @@ -227,8 +232,8 @@ public class BukkitChunk_1_9 extends FaweChunk { } @Override - public FaweChunk copy(boolean shallow) { - BukkitChunk_1_9 copy = new BukkitChunk_1_9(getParent(), getX(), getZ()); + public IntFaweChunk copy(boolean shallow) { + IntFaweChunk copy = (IntFaweChunk) getParent().getChunk(getX(), getZ()); if (shallow) { copy.ids = ids; copy.air = air; diff --git a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java new file mode 100644 index 00000000..ba52081f --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java @@ -0,0 +1,283 @@ +package com.boydti.fawe.example; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.IntegerPair; +import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.object.exception.FaweException; +import com.boydti.fawe.util.FaweQueue; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.world.biome.BaseBiome; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingDeque; + +public abstract class MappedFaweQueue extends FaweQueue { + + private WORLD impWorld; + + /** + * Map of chunks in the queue + */ + private ConcurrentHashMap blocks = new ConcurrentHashMap<>(); + private LinkedBlockingDeque chunks = new LinkedBlockingDeque<>(); + + @Override + public void optimize() { + ArrayList threads = new ArrayList(); + for (final FaweChunk chunk : chunks) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + chunk.optimize(); + } + }); + threads.add(thread); + thread.start(); + } + for (Thread thread : threads) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public MappedFaweQueue(final String world) { + super(world); + } + + public abstract WORLD getWorld(String world); + + public abstract boolean isChunkLoaded(WORLD world, int x, int z); + + public abstract boolean regenerateChunk(WORLD world, int x, int z); + + public abstract void sendChunk(FaweChunk chunk); + + public abstract boolean setComponents(FaweChunk fc); + + @Override + public abstract FaweChunk getChunk(int x, int z); + + @Override + public abstract boolean fixLighting(FaweChunk fc, boolean fixAll); + + public abstract boolean loadChunk(WORLD world, int x, int z, boolean generate); + + public abstract CHUNK getCachedChunk(WORLD world, int cx, int cz); + + @Override + public boolean isChunkLoaded(int x, int z) { + return isChunkLoaded(getWorld(), x, z); + }; + + public WORLD getWorld() { + if (impWorld != null) { + return impWorld; + } + return impWorld = getWorld(world); + } + + @Override + public boolean regenerateChunk(int x, int z) { + return regenerateChunk(getWorld(), x, z); + } + + @Override + public void addTask(int x, int z, Runnable runnable) { + long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL; + FaweChunk result = this.blocks.get(pair); + if (result == null) { + result = this.getChunk(x, z); + result.addTask(runnable); + FaweChunk previous = this.blocks.put(pair, result); + if (previous == null) { + chunks.add(result); + return; + } + this.blocks.put(pair, previous); + result = previous; + } + result.addTask(runnable); + } + + private FaweChunk lastWrappedChunk; + private int lastX = Integer.MIN_VALUE; + private int lastZ = Integer.MIN_VALUE; + + @Override + public boolean setBlock(int x, int y, int z, short id, byte data) { + if ((y > 255) || (y < 0)) { + return false; + } + int cx = x >> 4; + int cz = z >> 4; + if (cx != lastX || cz != lastZ) { + lastX = cx; + lastZ = cz; + long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL; + lastWrappedChunk = this.blocks.get(pair); + if (lastWrappedChunk == null) { + lastWrappedChunk = this.getChunk(x >> 4, z >> 4); + lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data); + FaweChunk previous = this.blocks.put(pair, lastWrappedChunk); + if (previous == null) { + chunks.add(lastWrappedChunk); + return true; + } + this.blocks.put(pair, previous); + lastWrappedChunk = previous; + } + } + lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data); + return true; + } + + @Override + public boolean setBiome(int x, int z, BaseBiome biome) { + long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL; + FaweChunk result = this.blocks.get(pair); + if (result == null) { + result = this.getChunk(x >> 4, z >> 4); + FaweChunk previous = this.blocks.put(pair, result); + if (previous != null) { + this.blocks.put(pair, previous); + result = previous; + } else { + chunks.add(result); + } + } + result.setBiome(x & 15, z & 15, biome); + return true; + } + + @Override + public FaweChunk next() { + lastX = Integer.MIN_VALUE; + lastZ = Integer.MIN_VALUE; + try { + if (this.blocks.size() == 0) { + return null; + } + synchronized (blocks) { + FaweChunk chunk = chunks.poll(); + if (chunk != null) { + blocks.remove(chunk.longHash()); + this.execute(chunk); + return chunk; + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + @Override + public int size() { + return chunks.size(); + } + + private LinkedBlockingDeque toUpdate = new LinkedBlockingDeque<>(); + + public boolean execute(FaweChunk fc) { + if (fc == null) { + return false; + } + // Set blocks / entities / biome + if (!this.setComponents(fc)) { + return false; + } + fc.executeTasks(); + return true; + } + + @Override + public void clear() { + this.blocks.clear(); + this.chunks.clear(); + } + + @Override + public void setChunk(FaweChunk chunk) { + FaweChunk previous = this.blocks.put(chunk.longHash(), (FaweChunk) chunk); + if (previous != null) { + chunks.remove(previous); + } + chunks.add((FaweChunk) chunk); + } + + public Collection sendChunk(Collection fcs) { + for (final FaweChunk fc : fcs) { + sendChunk(fc); + } + return new ArrayList<>(); + } + + public int lastChunkX = Integer.MIN_VALUE; + public int lastChunkZ = Integer.MIN_VALUE; + public int lastChunkY = Integer.MIN_VALUE; + + private CHUNK lastChunk; + private SECTION lastSection; + + public SECTION getCachedSection(CHUNK chunk, int cy) { + return (SECTION) lastChunk; + } + + public abstract int getCombinedId4Data(SECTION section, int x, int y, int z); + + private final RunnableVal loadChunk = new RunnableVal() { + @Override + public void run(IntegerPair coord) { + loadChunk(getWorld(), coord.x, coord.z, true); + } + }; + + long average = 0; + + @Override + public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { + if (y < 0 || y > 255) { + return 0; + } + int cx = x >> 4; + int cz = z >> 4; + int cy = y >> 4; + if (cx != lastChunkX || cz != lastChunkZ) { + lastChunkX = cx; + lastChunkZ = cz; + if (!isChunkLoaded(cx, cz)) { + long start = System.currentTimeMillis(); + boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); + if (sync) { + loadChunk(getWorld(), cx, cz, true); + } else if (Settings.CHUNK_WAIT > 0) { + loadChunk.value = new IntegerPair(cx, cz); + TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT); + if (!isChunkLoaded(cx, cz)) { + throw new FaweException.FaweChunkLoadException(); + } + } else { + return 0; + } + } + lastChunk = getCachedChunk(getWorld(), cx, cz); + lastSection = getCachedSection(lastChunk, cy); + } else if (cy != lastChunkY) { + if (lastChunk == null) { + return 0; + } + lastSection = getCachedSection(lastChunk, cy); + } + + if (lastSection == null) { + return 0; + } + return getCombinedId4Data(lastSection, x, y, z); + } +} diff --git a/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java new file mode 100644 index 00000000..143f75be --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java @@ -0,0 +1,39 @@ +package com.boydti.fawe.example; + +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.util.TaskManager; + +public abstract class NMSMappedFaweQueue extends MappedFaweQueue { + public NMSMappedFaweQueue(String world) { + super(world); + } + + @Override + public void sendChunk(final FaweChunk fc) { + TaskManager.IMP.taskSyncSoon(new Runnable() { + @Override + public void run() { + final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING; + TaskManager.IMP.taskSyncNow(new Runnable() { + @Override + public void run() { + if (!result) { + fixLighting(fc, Settings.FIX_ALL_LIGHTING); + } + CHUNK chunk = (CHUNK) fc.getChunk(); + refreshChunk(getWorld(), chunk); + } + }, false); + } + }, Settings.ASYNC_LIGHTING); + } + + public abstract void refreshChunk(WORLD world, CHUNK chunk); + + @Override + public abstract boolean setComponents(FaweChunk fc); + + @Override + public abstract boolean fixLighting(FaweChunk fc, boolean fixAll); +} diff --git a/core/src/main/java/com/boydti/fawe/object/EditSessionWrapper.java b/core/src/main/java/com/boydti/fawe/object/EditSessionWrapper.java index 20fbdcce..a8eeb095 100644 --- a/core/src/main/java/com/boydti/fawe/object/EditSessionWrapper.java +++ b/core/src/main/java/com/boydti/fawe/object/EditSessionWrapper.java @@ -4,6 +4,7 @@ import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.util.FaweQueue; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.extent.Extent; @@ -16,10 +17,99 @@ public class EditSessionWrapper { } public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) { + Vector pt = new Vector(x, 0, z); for (int y = maxY; y >= minY; --y) { - final Vector pt = new Vector(x, y, z); - final int id = this.session.getBlockType(pt); - final int data = this.session.getBlockData(pt); + BaseBlock block = session.getLazyBlock(x, y, z); + final int id = block.getId(); + int data; + switch (id) { + case 0: { + continue; + } + case 2: + case 4: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 25: + 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 52: + case 54: + case 55: + case 56: + case 57: + case 58: + case 60: + case 61: + case 62: + 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 84: + case 85: + case 87: + case 88: + case 101: + case 102: + case 103: + 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: + case 170: + case 172: + case 173: + case 174: + case 176: + case 177: + case 181: + case 182: + case 188: + case 189: + case 190: + case 191: + case 192: + return y; + default: + data = 0; + } if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) { return y; } diff --git a/core/src/main/java/com/boydti/fawe/object/FaweChunk.java b/core/src/main/java/com/boydti/fawe/object/FaweChunk.java index 388a2aec..893a8347 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweChunk.java @@ -105,6 +105,8 @@ public abstract class FaweChunk { public abstract void setBiome(final int x, final int z, final BaseBiome biome); + public void optimize() {} + @Override public boolean equals(final Object obj) { if ((obj == null) || obj.hashCode() != hashCode() || !(obj instanceof FaweChunk)) { diff --git a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java index eeae96be..bd3b7a09 100644 --- a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java +++ b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java @@ -172,7 +172,7 @@ public abstract class FawePlayer { DiskStorageHistory set = new DiskStorageHistory(world, uuid, index); EditSession edit = set.toEditSession(getPlayer()); if (world.equals(getWorld())) { - session.remember(edit, 0); + session.remember(edit, false); } else { return; } @@ -184,7 +184,7 @@ public abstract class FawePlayer { } /** - * Get the player's limit + * Get the player's limit * @return */ public FaweLimit getLimit() { diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java index 785a2b32..bba91908 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/FaweClipboard.java @@ -26,6 +26,11 @@ public abstract class FaweClipboard { public void setOrigin(Vector offset) {} // Do nothing + /** + * The locations provided are relative to the clipboard min + * @param task + * @param air + */ public abstract void forEach(final RunnableVal2 task, boolean air); /** diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java index e7ddf321..9c0ddaba 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java @@ -24,6 +24,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard { // x,z,y+15>>4 | y&15 private final byte[][] ids; + private final byte[] heights; private byte[][] datas; private final HashMap nbtMap; private final HashSet entities; @@ -33,6 +34,10 @@ public class MemoryOptimizedClipboard extends FaweClipboard { this.height = height; this.length = length; this.area = width * length; + heights = new byte[(height + 15) >> 4]; + for (int y = 0; y < ((height + 15) >> 4); y++) { + heights[y] = (byte) Math.min(16, height - (y << 4)); + } ids = new byte[width * length * ((height + 15) >> 4)][]; nbtMap = new HashMap<>(); entities = new HashSet<>(); @@ -186,7 +191,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard { int y2 = y & 0xF; byte[] idArray = ids[i]; if (idArray == null) { - idArray = new byte[16]; + idArray = new byte[heights[ylast >> 4]]; ids[i] = idArray; } idArray[y2] = (byte) id; @@ -200,7 +205,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard { } byte[] dataArray = datas[i]; if (dataArray == null) { - dataArray = datas[i] = new byte[16]; + dataArray = datas[i] = new byte[heights[ylast >> 4]]; } dataArray[y2] = (byte) data; } @@ -275,7 +280,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard { int y2 = y & 0xF; byte[] idArray = ids[i]; if (idArray == null) { - idArray = new byte[16]; + idArray = new byte[heights[ylast >> 4]]; ids[i] = idArray; } idArray[y2] = (byte) id; @@ -286,7 +291,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard { int y2 = y & 0xF; byte[] idArray = ids[i]; if (idArray == null) { - idArray = new byte[16]; + idArray = new byte[heights[ylast >> 4]]; ids[i] = idArray; } idArray[y2] = (byte) id; @@ -299,7 +304,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard { } byte[] dataArray = datas[i]; if (dataArray == null) { - dataArray = datas[i] = new byte[16]; + dataArray = datas[i] = new byte[heights[ylast >> 4]]; } dataArray[y2] = (byte) data; return true; diff --git a/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java index cff305c3..77acb5cf 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java @@ -29,12 +29,14 @@ public class FastWorldEditExtent extends FaweExtent { @Override public Entity createEntity(final Location location, final BaseEntity entity) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - FastWorldEditExtent.super.createEntity(location, entity); - } - }); + if (entity != null) { + TaskManager.IMP.task(new Runnable() { + @Override + public void run() { + FastWorldEditExtent.super.createEntity(location, entity); + } + }); + } return null; } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java index 5b71555e..65a068d9 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java @@ -47,7 +47,7 @@ public class ProcessedWEExtent extends FaweExtent { @Override public Entity createEntity(final Location location, final BaseEntity entity) { - if (limit.MAX_ENTITIES-- < 0) { + if (limit.MAX_ENTITIES-- < 0 || entity == null) { return null; } if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) { @@ -227,13 +227,10 @@ public class ProcessedWEExtent extends FaweExtent { case 49: case 51: case 52: - case 54: case 56: case 57: case 58: case 60: - case 61: - case 62: case 7: case 8: case 9: diff --git a/core/src/main/java/com/boydti/fawe/object/io/FastByteArrayOutputStream.java b/core/src/main/java/com/boydti/fawe/object/io/FastByteArrayOutputStream.java new file mode 100644 index 00000000..c162a728 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/io/FastByteArrayOutputStream.java @@ -0,0 +1,275 @@ +package com.boydti.fawe.object.io; + +/* + * #%L + * ch-commons-util + * %% + * Copyright (C) 2012 Cloudhopper by Twitter + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.io.Writer; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * Originally found here: http://www.java2s.com/Code/Java/File-Input-Output/AspeedyimplementationofByteArrayOutputStream.htm + * + * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it + * does not copy buffers when it's expanded. There's also no copying of the internal buffer + * if it's contents is extracted with the writeTo(stream) method. + * + * @author Rickard berg + * @author Brat Baker (Atlassian) + * @author Alexey + * @version $Date: 2008-01-19 10:09:56 +0800 (Sat, 19 Jan 2008) $ $Id: FastByteArrayOutputStream.java 3000 2008-01-19 02:09:56Z tm_jee $ + */ +public class FastByteArrayOutputStream extends OutputStream { + + // Static -------------------------------------------------------- + private static final int DEFAULT_BLOCK_SIZE = 16384; + private LinkedList buffers; + // Attributes ---------------------------------------------------- + // internal buffer + private byte[] buffer; + // is the stream closed? + private boolean closed; + private int blockSize; + private int index; + private int size; + + // Constructors -------------------------------------------------- + public FastByteArrayOutputStream() { + this(DEFAULT_BLOCK_SIZE); + } + + public FastByteArrayOutputStream(int aSize) { + blockSize = aSize; + buffer = new byte[blockSize]; + } + + public int getSize() { + return size + index; + } + + @Override + public void close() { + closed = true; + } + + public byte[] toByteArray() { + byte[] data = new byte[getSize()]; + + // Check if we have a list of buffers + int pos = 0; + + if (buffers != null) { + Iterator iter = buffers.iterator(); + + while (iter.hasNext()) { + byte[] bytes = (byte[])iter.next(); + System.arraycopy(bytes, 0, data, pos, blockSize); + pos += blockSize; + } + } + + // write the internal buffer directly + System.arraycopy(buffer, 0, data, pos, index); + + return data; + } + + @Override + public String toString() { + return new String(toByteArray()); + } + + // OutputStream overrides ---------------------------------------- + public void write(int datum) throws IOException { + if (closed) { + throw new IOException("Stream closed"); + } else { + if (index == blockSize) { + addBuffer(); + } + + // store the byte + buffer[index++] = (byte) datum; + } + } + + @Override + public void write(byte[] data, int offset, int length) throws IOException { + if (data == null) { + throw new NullPointerException(); + } else if ((offset < 0) || ((offset + length) > data.length) || (length < 0)) { + throw new IndexOutOfBoundsException(); + } else if (closed) { + throw new IOException("Stream closed"); + } else { + if ((index + length) > blockSize) { + int copyLength; + + do { + if (index == blockSize) { + addBuffer(); + } + + copyLength = blockSize - index; + + if (length < copyLength) { + copyLength = length; + } + + System.arraycopy(data, offset, buffer, index, copyLength); + offset += copyLength; + index += copyLength; + length -= copyLength; + } while (length > 0); + } else { + // Copy in the subarray + System.arraycopy(data, offset, buffer, index, length); + index += length; + } + } + } + + // Public + public void writeTo(OutputStream out) throws IOException { + // Check if we have a list of buffers + if (buffers != null) { + Iterator iter = buffers.iterator(); + + while (iter.hasNext()) { + byte[] bytes = (byte[]) iter.next(); + out.write(bytes, 0, blockSize); + } + } + + // write the internal buffer directly + out.write(buffer, 0, index); + } + + public void writeTo(RandomAccessFile out) throws IOException { + // Check if we have a list of buffers + if (buffers != null) { + Iterator iter = buffers.iterator(); + + while (iter.hasNext()) { + byte[] bytes = (byte[]) iter.next(); + out.write(bytes, 0, blockSize); + } + } + + // write the internal buffer directly + out.write(buffer, 0, index); + } + + public void writeTo(Writer out, String encoding) throws IOException { + /* + There is design tradeoff between being fast, correct and using too much memory when decoding bytes to strings. + + The rules are thus : + + 1. if there is only one buffer then its a simple String conversion + + REASON : Fast!!! + + 2. uses full buffer allocation annd System.arrayCopy() to smooosh together the bytes + and then use String conversion + + REASON : Fast at the expense of a known amount of memory (eg the used memory * 2) + */ + if (buffers != null) { + // RULE 2 : a balance between using some memory and speed + writeToViaSmoosh(out, encoding); + } else { + // RULE 1 : fastest! + writeToViaString(out, encoding); + } + } + + /** + * This can ONLY be called if there is only a single buffer to write, instead + * use {@link #writeTo(java.io.Writer, String)}, which auto detects if + * {@link #writeToViaString(java.io.Writer, String)} is to be used or + * {@link #writeToViaSmoosh(java.io.Writer, String)}. + * + * @param out the JspWriter + * @param encoding the encoding + * @throws IOException + */ + void writeToViaString(Writer out, String encoding) throws IOException { + byte[] bufferToWrite = buffer; // this is always the last buffer to write + int bufferToWriteLen = index; // index points to our place in the last buffer + writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen); + } + + /** + * This is recommended to be used where there's more than 1 buffer to write, instead + * use {@link #writeTo(java.io.Writer, String)} which auto detects if + * {@link #writeToViaString(java.io.Writer, String)} is to be used or + * {@link #writeToViaSmoosh(java.io.Writer, String)}. + * + * @param out + * @param encoding + * @throws IOException + */ + void writeToViaSmoosh(Writer out, String encoding) throws IOException { + byte[] bufferToWrite = toByteArray(); + int bufferToWriteLen = bufferToWrite.length; + writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen); + } + + /** + * Write bufferToWriteLen of bytes from bufferToWrite to + * out encoding it at the same time. + * + * @param out + * @param encoding + * @param bufferToWrite + * @param bufferToWriteLen + * @throws IOException + */ + private void writeToImpl(Writer out, String encoding, byte[] bufferToWrite, int bufferToWriteLen) + throws IOException { + String writeStr; + if (encoding != null) { + writeStr = new String(bufferToWrite, 0, bufferToWriteLen, encoding); + } else { + writeStr = new String(bufferToWrite, 0, bufferToWriteLen); + } + out.write(writeStr); + } + + /** + * Create a new buffer and store the + * current one in linked list + */ + protected void addBuffer() { + if (buffers == null) { + buffers = new LinkedList(); + } + + buffers.addLast(buffer); + + buffer = new byte[blockSize]; + size += index; + index = 0; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/util/FaweQueue.java b/core/src/main/java/com/boydti/fawe/util/FaweQueue.java index 5398ef06..0fbb189a 100644 --- a/core/src/main/java/com/boydti/fawe/util/FaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/FaweQueue.java @@ -34,6 +34,8 @@ public abstract class FaweQueue { return sessions == null ? new HashSet() : new HashSet<>(sessions); } + public void optimize() {} + 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); diff --git a/core/src/main/java/com/boydti/fawe/util/SetQueue.java b/core/src/main/java/com/boydti/fawe/util/SetQueue.java index c2645767..d0d78563 100644 --- a/core/src/main/java/com/boydti/fawe/util/SetQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/SetQueue.java @@ -108,6 +108,7 @@ public class SetQueue { public void enqueue(FaweQueue queue) { inactiveQueues.remove(queue); if (queue.size() > 0 && !activeQueues.contains(queue)) { + queue.optimize(); activeQueues.add(queue); } } @@ -132,8 +133,8 @@ public class SetQueue { return new ArrayList<>(inactiveQueues); } - public FaweQueue getNewQueue(String world, boolean autoqueue) { - FaweQueue queue = Fawe.imp().getNewQueue(world); + public FaweQueue getNewQueue(String world, boolean fast, boolean autoqueue) { + FaweQueue queue = Fawe.imp().getNewQueue(world, fast); if (autoqueue) { inactiveQueues.add(queue); } @@ -155,18 +156,15 @@ public class SetQueue { if (Settings.QUEUE_MAX_WAIT >= 0) { long now = System.currentTimeMillis(); if (lastSuccess != 0) { - long diff = now - lastSuccess; - if (diff > Settings.QUEUE_MAX_WAIT) { - for (FaweQueue queue : tmp) { - if (queue != null && queue.size() > 0) { - queue.modified = now; - return queue; - } else if (now - queue.modified > Settings.QUEUE_DISCARD_AFTER) { - inactiveQueues.remove(queue); - } + for (FaweQueue queue : tmp) { + if (queue != null && queue.size() > 0 && now - queue.modified > Settings.QUEUE_MAX_WAIT) { + queue.modified = now; + return queue; + } else if (now - queue.modified > Settings.QUEUE_DISCARD_AFTER) { + inactiveQueues.remove(queue); } - return null; } + return null; } } if (Settings.QUEUE_SIZE != -1) { diff --git a/core/src/main/java/com/boydti/fawe/util/TaskManager.java b/core/src/main/java/com/boydti/fawe/util/TaskManager.java index 060fe2d8..c8bf590c 100644 --- a/core/src/main/java/com/boydti/fawe/util/TaskManager.java +++ b/core/src/main/java/com/boydti/fawe/util/TaskManager.java @@ -39,12 +39,12 @@ public abstract class TaskManager { public abstract void task(final Runnable r); /** - * Run a task on either the main thread or asynchronously + * Run a task on the current thread or asynchronously * - If it's already the main thread, it will jst call run() * @param r * @param async */ - public void task(final Runnable r, boolean async) { + public void taskNow(final Runnable r, boolean async) { if (async) { async(r); } else { @@ -52,7 +52,12 @@ public abstract class TaskManager { } } - public void sync(final Runnable r, boolean async) { + /** + * Run a task as soon as possible on the main thread, or now async + * @param r + * @param async + */ + public void taskSyncNow(final Runnable r, boolean async) { if (async) { async(r); } else if (r != null && Thread.currentThread() == Fawe.get().getMainThread()){ @@ -62,6 +67,19 @@ public abstract class TaskManager { } } + /** + * Run a task on the main thread at the next tick or now async + * @param r + * @param async + */ + public void taskSyncSoon(final Runnable r, boolean async) { + if (async) { + async(r); + } else { + task(r); + } + } + /** * Run a task later on the main thread diff --git a/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java b/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java index 500ebaea..21de3e2d 100644 --- a/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java +++ b/core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java @@ -2,6 +2,7 @@ package com.boydti.fawe.wrappers; import com.boydti.fawe.Fawe; import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSessionFactory; @@ -170,7 +171,7 @@ public class PlayerWrapper implements Player { } @Override - public void floatAt(int x, int y, int z, boolean alwaysGlass) { + public void floatAt(final int x, final int y, final int z, final boolean alwaysGlass) { EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory(); EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this); try { @@ -182,7 +183,12 @@ public class PlayerWrapper implements Player { } catch (MaxChangedBlocksException e) { e.printStackTrace(); } - setPosition(new Vector(x + 0.5, y, z + 0.5)); + SetQueue.IMP.addTask(new Runnable() { + @Override + public void run() { + setPosition(new Vector(x + 0.5, y, z + 0.5)); + } + }); } @Override diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index ce026546..8dbc2952 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -234,8 +234,6 @@ public class EditSession implements Extent { this.wrapper = Fawe.imp().getEditSessionWrapper(this); return; } - this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true); - queue.addEditSession(this); // Set the world of the event to the actual world (workaround for CoreProtect) try { Class eventClass = event.getClass(); @@ -262,6 +260,8 @@ public class EditSession implements Extent { this.bypassHistory = extent; this.bypassNone = extent; this.changeSet = new NullChangeSet(); + this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true); + queue.addEditSession(this); return; } this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor); @@ -270,6 +270,8 @@ public class EditSession implements Extent { final LocalSession session = fp.getSession(); this.fastmode = session.hasFastMode(); if (fp.hasWorldEditBypass()) { + this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true); + queue.addEditSession(this); // Bypass skips processing and area restrictions extent = (this.faweExtent = new FastWorldEditExtent(world, queue)); if (this.hasFastMode()) { @@ -283,6 +285,8 @@ public class EditSession implements Extent { return; } } else { + this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), false, true); + queue.addEditSession(this); this.limit = fp.getLimit(); final HashSet mask = WEManager.IMP.getMask(fp); if (mask.size() == 0) { @@ -1533,21 +1537,31 @@ public class EditSession implements Extent { public int fixLiquid(final Vector origin, final double radius, final int moving, final int stationary) throws MaxChangedBlocksException { checkNotNull(origin); checkArgument(radius >= 0, "radius >= 0 required"); + // Our origins can only be liquids - final BlockMask liquidMask = new BlockMask(EditSession.this, new BaseBlock(moving, -1), new BaseBlock(stationary, -1)); + BlockMask liquidMask = new BlockMask( + this, + new BaseBlock(moving, -1), + new BaseBlock(stationary, -1)); // But we will also visit air blocks - final MaskIntersection blockMask = new MaskUnion(liquidMask, new BlockMask(EditSession.this, new BaseBlock(BlockID.AIR))); + MaskIntersection blockMask = + new MaskUnion(liquidMask, + new BlockMask( + this, + new BaseBlock(BlockID.AIR))); // There are boundaries that the routine needs to stay in - final MaskIntersection mask = new MaskIntersection(new BoundedHeightMask(0, Math.min(origin.getBlockY(), EditSession.this.getWorld().getMaxY())), new RegionMask(new EllipsoidRegion( - null, origin, new Vector(radius, radius, radius))), blockMask); + MaskIntersection mask = new MaskIntersection( + new BoundedHeightMask(0, Math.min(origin.getBlockY(), getWorld().getMaxY())), + new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))), + blockMask); - final BlockReplace replace = new BlockReplace(EditSession.this, new BlockPattern(new BaseBlock(stationary))); - final NonRisingVisitor visitor = new NonRisingVisitor(mask, replace); + BlockReplace replace = new BlockReplace(this, new BlockPattern(new BaseBlock(stationary))); + NonRisingVisitor visitor = new NonRisingVisitor(mask, replace); // Around the origin in a 3x3 block - for (final BlockVector position : CuboidRegion.fromCenter(origin, 1)) { + for (BlockVector position : CuboidRegion.fromCenter(origin, 1)) { if (liquidMask.test(position)) { visitor.visit(position); } @@ -1559,7 +1573,7 @@ public class EditSession implements Extent { EditSession.this.flushQueue(); } }, true); - return this.changes = visitor.getAffected(); + return visitor.getAffected(); } /** diff --git a/core/src/main/java/com/sk89q/worldedit/LocalSession.java b/core/src/main/java/com/sk89q/worldedit/LocalSession.java index eea0eaf9..dd0c2fd9 100644 --- a/core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -52,8 +52,10 @@ import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.snapshot.Snapshot; import java.util.Calendar; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.TimeZone; import java.util.concurrent.atomic.AtomicBoolean; @@ -76,7 +78,7 @@ public class LocalSession { // Session related private transient RegionSelector selector = new CuboidRegionSelector(); private transient boolean placeAtPos1 = false; - private transient LinkedList history = new LinkedList(); + private transient List history = Collections.synchronizedList(new LinkedList()); private transient int historyPointer = 0; private transient ClipboardHolder clipboard; private transient boolean toolControl = true; @@ -194,10 +196,10 @@ public class LocalSession { * @param editSession the edit session */ public void remember(EditSession editSession) { - remember(editSession, history.size()); + remember(editSession, true); } - public void remember(EditSession editSession, int index) { + public void remember(EditSession editSession, boolean append) { // Enqueue it if (editSession.getQueue() != null) { FaweQueue queue = editSession.getQueue(); @@ -217,7 +219,11 @@ public class LocalSession { if (set instanceof FaweChangeSet) { ((FaweChangeSet) set).flush(); } - history.add(Math.max(0, Math.min(index, history.size())), editSession); + if (append) { + history.add(editSession); + } else { + history.add(0, editSession); + } while (history.size() > MAX_HISTORY_SIZE) { history.remove(0); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 6089baa4..9f5fd4b6 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -46,12 +46,11 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.math.transform.AffineTransform; -import com.sk89q.worldedit.math.transform.Transform; -import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.parametric.Optional; import java.util.Iterator; @@ -97,17 +96,18 @@ public class ClipboardCommands { @Selection final Region region, @Switch('e') boolean copyEntities, @Switch('m') Mask mask) throws WorldEditException { - Vector origin = region.getMinimumPoint(); + final Vector origin = region.getMinimumPoint(); final int mx = origin.getBlockX(); final int my = origin.getBlockY(); final int mz = origin.getBlockZ(); LazyClipboard lazyClipboard = new LazyClipboard() { @Override public BaseBlock getBlock(int x, int y, int z) { - int xx = mx + x; - int yy = my + y; - int zz = mz + z; - return editSession.getLazyBlock(xx, yy, zz); + return editSession.getLazyBlock(mx + x, my + y, mz + z); + } + + public BaseBlock getBlockAbs(int x, int y, int z) { + return editSession.getLazyBlock(x, y, z); } @Override @@ -120,10 +120,13 @@ public class ClipboardCommands { Iterator iter = region.iterator(); while (iter.hasNext()) { BlockVector pos = iter.next(); - BaseBlock block = getBlock((int) pos.x, (int) pos.y, (int) pos.z); + BaseBlock block = getBlockAbs((int) pos.x, (int) pos.y, (int) pos.z); if (!air && block == EditSession.nullBlock) { continue; } + pos.x -= mx; + pos.y -= my; + pos.z -= mz; task.run(pos, block); } } @@ -269,29 +272,24 @@ public class ClipboardCommands { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); Region region = clipboard.getRegion().clone(); - Vector origin = clipboard.getOrigin(); - final Transform transform = holder.getTransform(); - // Optimize for CuboidRegion - if (region instanceof CuboidRegion) { - CuboidRegion cuboid = (CuboidRegion) region; - Vector min = cuboid.getMinimumPoint(); - origin = origin.subtract(cuboid.getMinimumPoint()); - cuboid.setPos2(cuboid.getMaximumPoint().subtract(min)); - cuboid.setPos1(new Vector(0, 0, 0)); - } - Vector to = atOrigin ? origin : session.getPlacementPosition(player); - final int tx = to.getBlockX() - origin.getBlockX(); - final int ty = to.getBlockY() - origin.getBlockY(); - final int tz = to.getBlockZ() - origin.getBlockZ(); + + + final Vector bot = clipboard.getMinimumPoint(); + final Vector origin = clipboard.getOrigin(); + final Vector to = atOrigin ? origin : session.getPlacementPosition(player); // Optimize for BlockArrayClipboard if (clipboard instanceof BlockArrayClipboard) { + // To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min) + final int relx = to.getBlockX() + bot.getBlockX() - origin.getBlockX(); + final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY(); + final int relz = to.getBlockZ() + bot.getBlockZ() - origin.getBlockZ(); BlockArrayClipboard bac = (BlockArrayClipboard) clipboard; bac.IMP.forEach(new RunnableVal2() { @Override public void run(Vector pos, BaseBlock block) { - pos.x += tx; - pos.y += ty; - pos.z += tz; + pos.x += relx; + pos.y += rely; + pos.z += relz; try { editSession.setBlock(pos, block); } catch (MaxChangedBlocksException e) { @@ -300,7 +298,10 @@ public class ClipboardCommands { } }, !ignoreAirBlocks); } else { - // Generic optimization for unknown region type + // To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin) + final int relx = to.getBlockX() - origin.getBlockX(); + final int rely = to.getBlockY() - origin.getBlockY(); + final int relz = to.getBlockZ() - origin.getBlockZ(); Iterator iter = region.iterator(); while (iter.hasNext()) { BlockVector loc = iter.next(); @@ -308,15 +309,21 @@ public class ClipboardCommands { if (block == EditSession.nullBlock && ignoreAirBlocks) { continue; } - loc.x += tx; - loc.y += ty; - loc.z += tz; - editSession.setBlock(transform.apply(loc), block); + loc.x += relx; + loc.y += rely; + loc.z += relz; + editSession.setBlock(loc, block); } } + // Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin) + final int entityOffsetX = to.getBlockX() - origin.getBlockX(); + final int entityOffsetY = to.getBlockY() - origin.getBlockY(); + final int entityOffsetZ = to.getBlockZ() - origin.getBlockZ(); // entities for (Entity entity : clipboard.getEntities()) { - editSession.createEntity(entity.getLocation(), entity.getState()); + Location pos = entity.getLocation(); + Location newPos = new Location(pos.getExtent(), pos.getX() + entityOffsetX, pos.getY() + entityOffsetY, pos.getZ() + entityOffsetZ, pos.getYaw(), pos.getPitch()); + editSession.createEntity(newPos, entity.getState()); } if (selectPasted) { Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint())); diff --git a/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java b/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java index c838ae11..ee6430ed 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java +++ b/core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java @@ -122,6 +122,7 @@ public class SelectionCommand extends SimpleCommand { final byte data = (byte) block.getData(); final FaweChunk fc = queue.getChunk(0, 0); fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data); + fc.optimize(); int bcx = (current.minX) >> 4; int bcz = (current.minZ) >> 4; diff --git a/core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java b/core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java new file mode 100644 index 00000000..a036c9ad --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java @@ -0,0 +1,108 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.function.operation; + +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.history.UndoContext; +import com.sk89q.worldedit.history.change.Change; +import com.sk89q.worldedit.history.changeset.ChangeSet; +import java.util.Iterator; +import java.util.List; + + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Performs an undo or redo from a given {@link ChangeSet}. + */ +public class ChangeSetExecutor implements Operation { + + public enum Type {UNDO, REDO} + + private final Iterator iterator; + private final Type type; + private final UndoContext context; + + /** + * Create a new instance. + * + * @param changeSet the change set + * @param type type of change + * @param context the undo context + */ + private ChangeSetExecutor(ChangeSet changeSet, Type type, UndoContext context) { + checkNotNull(changeSet); + checkNotNull(type); + checkNotNull(context); + this.type = type; + this.context = context; + if (type == Type.UNDO) { + iterator = changeSet.backwardIterator(); + } else { + iterator = changeSet.forwardIterator(); + } + } + + @Override + public Operation resume(RunContext run) throws WorldEditException { + int size = 0; + if (type == Type.UNDO) { + while (iterator.hasNext()) { + iterator.next().undo(context); + } + } else { + while (iterator.hasNext()) { + iterator.next().redo(context); + } + } + return null; + } + + @Override + public void cancel() { + } + + @Override + public void addStatusMessages(List messages) { + } + + /** + * Create a new undo operation. + * + * @param changeSet the change set + * @param context an undo context + * @return an operation + */ + public static ChangeSetExecutor createUndo(ChangeSet changeSet, UndoContext context) { + return new ChangeSetExecutor(changeSet, Type.UNDO, context); + } + + /** + * Create a new redo operation. + * + * @param changeSet the change set + * @param context an undo context + * @return an operation + */ + public static ChangeSetExecutor createRedo(ChangeSet changeSet, UndoContext context) { + return new ChangeSetExecutor(changeSet, Type.REDO, context); + } + +} diff --git a/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java b/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java index 9a070b7a..65f2ab8e 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java +++ b/core/src/main/java/com/sk89q/worldedit/function/operation/Operations.java @@ -53,13 +53,7 @@ public final class Operations { * @throws MaxChangedBlocksException thrown when too many blocks have been changed */ public static void completeLegacy(Operation operation) throws MaxChangedBlocksException { - try { - while (true) { - operation = operation.resume(context); - } - } catch (final WorldEditException e) { - e.printStackTrace(); - } catch (NullPointerException ignore) {} + completeBlindly(operation); } /** diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java b/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java index a7f109d6..0cba816d 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java @@ -113,7 +113,7 @@ public class FaweForge implements IFawe { } @Override - public FaweQueue getNewQueue(String world) { + public FaweQueue getNewQueue(String world, boolean dontCareIfFast) { return new ForgeQueue_All(world); } diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java index 6fe9e831..36098fa4 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java @@ -197,15 +197,16 @@ public class ForgeChunk_All extends FaweChunk { case 130: case 76: case 62: + case 50: this.relight[i]++; case 54: case 146: case 61: case 65: case 68: - if (data < 2) { - data = 2; - } +// if (data < 2) { +// data = 2; +// } default: vs[j] = (byte) id; NibbleArray dataArray = datas[i]; diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 2775c775..140a964e 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -2,24 +2,18 @@ package com.boydti.fawe.forge.v0; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.config.Settings; +import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.forge.ForgePlayer; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.exception.FaweException; -import com.boydti.fawe.util.FaweQueue; -import com.boydti.fawe.util.TaskManager; -import com.sk89q.worldedit.world.biome.BaseBiome; import java.lang.reflect.Field; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingDeque; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.NetHandlerPlayServer; @@ -38,39 +32,55 @@ import net.minecraft.world.chunk.NibbleArray; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.gen.ChunkProviderServer; -public class ForgeQueue_All extends FaweQueue { - - private World forgeWorld; - - private ConcurrentHashMap> blocks = new ConcurrentHashMap<>(); - private LinkedBlockingDeque> chunks = new LinkedBlockingDeque<>(); +public class ForgeQueue_All extends NMSMappedFaweQueue { public ForgeQueue_All(final String world) { super(world); } @Override - public boolean isChunkLoaded(int x, int z) { - return getWorld().getChunkProvider().chunkExists(x, z); + public boolean loadChunk(World world, int x, int z, boolean generate) { + return getCachedChunk(world, x, z) != null; } - public World getWorld() { - if (forgeWorld != null) { - return forgeWorld; + @Override + public Chunk getCachedChunk(World world, int cx, int cz) { + Chunk chunk = world.getChunkProvider().provideChunk(cx, cz); + if (chunk != null && !chunk.isChunkLoaded) { + chunk.onChunkLoad(); } + return chunk; + } + + @Override + public int getCombinedId4Data(ExtendedBlockStorage ls, int x, int y, int z) { + byte[] ids = ls.getBlockLSBArray(); + NibbleArray datasNibble = ls.getBlockMSBArray(); + int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15]; + int combined = (ids[i] << 4) + (datasNibble == null ? 0 : datasNibble.get(x & 15, y & 15, z & 15)); + return combined; + } + + @Override + public boolean isChunkLoaded(World world, int x, int z) { + return world.getChunkProvider().chunkExists(x, z); + } + + @Override + public World getWorld(String world) { WorldServer[] worlds = MinecraftServer.getServer().worldServers; for (WorldServer ws : worlds) { if (ws.provider.getDimensionName().equals(world)) { - return forgeWorld = ws; + return ws; } } return null; } @Override - public boolean regenerateChunk(int x, int z) { + public boolean regenerateChunk(World world, int x, int z) { try { - IChunkProvider provider = getWorld().getChunkProvider(); + IChunkProvider provider = world.getChunkProvider(); if (!(provider instanceof ChunkProviderServer)) { return false; } @@ -88,7 +98,7 @@ public class ForgeQueue_All extends FaweQueue { u = ChunkProviderServer.class.getDeclaredField("chunksToUnload"); } u.setAccessible(true); - Set unloadQueue = (Set) u.get(chunkServer); + Set unloadQueue = (Set) u.get(chunkServer); Field m; try { m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap @@ -104,7 +114,7 @@ public class ForgeQueue_All extends FaweQueue { lc = ChunkProviderServer.class.getDeclaredField("loadedChunks"); } lc.setAccessible(true); - @SuppressWarnings("unchecked") List loaded = (List) lc.get(chunkServer); + @SuppressWarnings("unchecked") List loaded = (List) lc.get(chunkServer); Field p; try { p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider @@ -134,30 +144,6 @@ public class ForgeQueue_All extends FaweQueue { return true; } - @Override - public void addTask(int x, int z, Runnable runnable) { - long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x, z); - result.addTask(runnable); - FaweChunk previous = this.blocks.put(pair, result); - if (previous == null) { - chunks.add(result); - return; - } - this.blocks.put(pair, previous); - result = previous; - } - result.addTask(runnable); - } - - 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 ExtendedBlockStorage ls; - private final RunnableVal loadChunk = new RunnableVal() { @Override public void run(IntegerPair loc) { @@ -170,215 +156,39 @@ public class ForgeQueue_All extends FaweQueue { }; @Override - public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { - if (y < 0 || y > 255) { - return 0; - } - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lcx || cz != lcz) { - World world = getWorld(); - lcx = cx; - lcz = cz; - IChunkProvider provider = world.getChunkProvider(); - Chunk chunk; - if (!provider.chunkExists(cx, cz)) { - boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); - if (sync) { - chunk = provider.provideChunk(cx, cz); - } else if (Settings.CHUNK_WAIT > 0) { - loadChunk.value = new IntegerPair(cx, cz); - TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT); - if (!provider.chunkExists(cx, cz)) { - throw new FaweException.FaweChunkLoadException(); - } - chunk = provider.provideChunk(cx, cz); - } else { - return 0; - } - } else { - chunk = provider.provideChunk(cx, cz); - } - lc = chunk; - ls = lc.getBlockStorageArray()[cy]; - } else if (cy != lcy) { - if (lc == null) { - return 0; - } - ls = lc.getBlockStorageArray()[cy]; - } - if (ls == null) { - ls = null; - return 0; - } - byte[] ids = ls.getBlockLSBArray(); - NibbleArray datasNibble = ls.getBlockMSBArray(); - int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15]; - int combined = (ids[i] << 4) + (datasNibble == null ? 0 : datasNibble.get(x & 15, y & 15, z & 15)); - return combined; - } - - private FaweChunk lastChunk; - private int lastX = Integer.MIN_VALUE; - private int lastZ = Integer.MIN_VALUE; - - @Override - public boolean setBlock(int x, int y, int z, short id, byte data) { - if ((y > 255) || (y < 0)) { - return false; - } - int cx = x >> 4; - int cz = z >> 4; - if (cx != lastX || cz != lastZ) { - lastX = cx; - lastZ = cz; - long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL; - lastChunk = this.blocks.get(pair); - if (lastChunk == null) { - lastChunk = this.getChunk(x >> 4, z >> 4); - lastChunk.setBlock(x & 15, y, z & 15, id, data); - FaweChunk previous = this.blocks.put(pair, lastChunk); - if (previous == null) { - chunks.add(lastChunk); - return true; - } - this.blocks.put(pair, previous); - lastChunk = previous; - } - } - lastChunk.setBlock(x & 15, y, z & 15, id, data); - return true; - } - - @Override - public boolean setBiome(int x, int z, BaseBiome biome) { - long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x >> 4, z >> 4); - FaweChunk previous = this.blocks.put(pair, result); - if (previous != null) { - this.blocks.put(pair, previous); - result = previous; - } else { - chunks.add(result); - } - } - result.setBiome(x & 15, z & 15, biome); - return true; - } - - @Override - public FaweChunk next() { - lastX = Integer.MIN_VALUE; - lastZ = Integer.MIN_VALUE; - try { - if (this.blocks.size() == 0) { - return null; - } - synchronized (blocks) { - FaweChunk chunk = chunks.poll(); - if (chunk != null) { - blocks.remove(chunk.longHash()); - this.execute(chunk); - return chunk; - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - return null; - } - - @Override - public int size() { - return chunks.size(); - } - - private LinkedBlockingDeque> toUpdate = new LinkedBlockingDeque<>(); - - public boolean execute(FaweChunk fc) { - if (fc == null) { - return false; - } - // Load chunk - Chunk chunk = fc.getChunk(); + public void refreshChunk(World world, Chunk chunk) { if (!chunk.isChunkLoaded) { - chunk.onChunkLoad(); + return; } - // Set blocks / entities / biome - if (!this.setComponents(fc)) { - return false; - } - fc.executeTasks(); - return true; - } - - @Override - public void clear() { - this.blocks.clear(); - this.chunks.clear(); - } - - @Override - public void setChunk(FaweChunk chunk) { - FaweChunk previous = this.blocks.put(chunk.longHash(), (FaweChunk) chunk); - if (previous != null) { - chunks.remove(previous); - } - chunks.add((FaweChunk) chunk); - } - - public void sendChunk(final FaweChunk fc) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING; - TaskManager.IMP.sync(new Runnable() { - @Override - public void run() { - if (!result) { - fixLighting(fc, Settings.FIX_ALL_LIGHTING); - } - Chunk chunk = fc.getChunk(); - if (!chunk.isChunkLoaded) { - return; - } - World world = chunk.worldObj; - ChunkCoordIntPair pos = chunk.getChunkCoordIntPair(); - int cx = pos.chunkXPos; - int cz = pos.chunkZPos; - for (FawePlayer fp : Fawe.get().getCachedPlayers()) { - ForgePlayer forgePlayer = (ForgePlayer) fp; - EntityPlayerMP player = forgePlayer.parent; - if (!player.worldObj.equals(world)) { - continue; - } - int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance(); - EntityPlayerMP nmsPlayer = (EntityPlayerMP) player; - ChunkCoordinates loc = player.getPlayerCoordinates(); - int px = loc.posX >> 4; - int pz = loc.posZ >> 4; - int dx = Math.abs(cx - (loc.posX >> 4)); - int dz = Math.abs(cz - (loc.posZ >> 4)); - if ((dx > view) || (dz > view)) { - continue; - } - NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler; - con.sendPacket(new S21PacketChunkData(chunk, false, 65535)); - // Try sending true, 0 first - // Try bulk chunk packet - } - } - }, false); + ChunkCoordIntPair pos = chunk.getChunkCoordIntPair(); + int cx = pos.chunkXPos; + int cz = pos.chunkZPos; + for (FawePlayer fp : Fawe.get().getCachedPlayers()) { + ForgePlayer forgePlayer = (ForgePlayer) fp; + EntityPlayerMP player = forgePlayer.parent; + if (!player.worldObj.equals(world)) { + continue; } - }, Settings.ASYNC_LIGHTING); + int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance(); + EntityPlayerMP nmsPlayer = (EntityPlayerMP) player; + ChunkCoordinates loc = player.getPlayerCoordinates(); + int px = loc.posX >> 4; + int pz = loc.posZ >> 4; + int dx = Math.abs(cx - (loc.posX >> 4)); + int dz = Math.abs(cz - (loc.posZ >> 4)); + if ((dx > view) || (dz > view)) { + continue; + } + NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler; + con.sendPacket(new S21PacketChunkData(chunk, false, 65535)); + // Try sending true, 0 first + // Try bulk chunk packet + } } - public boolean setComponents(FaweChunk fc) { + public boolean setComponents(FaweChunk fc) { ForgeChunk_All fs = (ForgeChunk_All) fc; - Chunk forgeChunk = fc.getChunk(); + Chunk forgeChunk = fs.getChunk(); net.minecraft.world.World nmsWorld = forgeChunk.worldObj; try { boolean flag = !nmsWorld.provider.hasNoSky; @@ -485,12 +295,12 @@ public class ForgeQueue_All extends FaweQueue { } @Override - public FaweChunk getChunk(int x, int z) { + public FaweChunk getChunk(int x, int z) { return new ForgeChunk_All(this, x, z); } @Override - public boolean fixLighting(FaweChunk chunk, boolean fixAll) { + public boolean fixLighting(FaweChunk chunk, boolean fixAll) { try { ForgeChunk_All fc = (ForgeChunk_All) chunk; Chunk forgeChunk = fc.getChunk(); diff --git a/forge189/src/main/java/com/boydti/fawe/forge/FaweForge.java b/forge189/src/main/java/com/boydti/fawe/forge/FaweForge.java index 8da67b62..03287153 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/FaweForge.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/FaweForge.java @@ -114,7 +114,7 @@ public class FaweForge implements IFawe { } @Override - public FaweQueue getNewQueue(String world) { + public FaweQueue getNewQueue(String world, boolean dontCareIfFast) { return new ForgeQueue_All(world); } diff --git a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java index 94c210f7..b9b0a64a 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeChunk_All.java @@ -1,256 +1,25 @@ package com.boydti.fawe.forge.v0; -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.util.FaweQueue; -import com.boydti.fawe.util.MainUtil; -import com.sk89q.worldedit.world.biome.BaseBiome; -import java.util.Arrays; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -public class ForgeChunk_All extends FaweChunk { - - public char[][] ids; - public short[] count; - public short[] air; - public short[] relight; - public byte[][] biomes; - public Chunk chunk; - +public class ForgeChunk_All extends CharFaweChunk { + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param parent + * @param x + * @param z + */ public ForgeChunk_All(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) { - World world = ((ForgeQueue_All) getParent()).getWorld(); - this.chunk = world.getChunkProvider().provideChunk(getX(), getZ()); - } - 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 - * @return - */ - public int getCount(int i) { - return this.count[i]; - } - - public int getAir(int i) { - return this.air[i]; - } - - public void setCount(int i, short value) { - this.count[i] = value; - } - - /** - * Get the number of block changes in a specified section. - * @param i - * @return - */ - public int getRelight(int i) { - return this.relight[i]; - } - - public int getTotalCount() { - int total = 0; - for (int i = 0; i < 16; i++) { - total += this.count[i]; - } - return total; - } - - public int getTotalRelight() { - if (getTotalCount() == 0) { - Arrays.fill(this.count, (short) 1); - Arrays.fill(this.relight, Short.MAX_VALUE); - return Short.MAX_VALUE; - } - int total = 0; - for (int i = 0; i < 16; i++) { - total += this.relight[i]; - } - return total; - } - - /** - * Get the raw data for a section. - * @param i - * @return - */ - public char[] getIdArray(int i) { - return this.ids[i]; - } - - @Override - public void setBlock(int x, int y, int z, int id, byte data) { - int i = FaweCache.CACHE_I[y][x][z]; - int j = FaweCache.CACHE_J[y][x][z]; - char[] vs = this.ids[i]; - if (vs == null) { - vs = this.ids[i] = new char[4096]; - this.count[i]++; - } else if (vs[j] == 0) { - this.count[i]++; - } - switch (id) { - case 0: - this.air[i]++; - vs[j] = (char) 1; - return; - case 10: - case 11: - case 39: - case 40: - case 51: - case 74: - case 89: - case 122: - case 124: - case 138: - case 169: - this.relight[i]++; - case 2: - case 4: - case 13: - case 14: - case 15: - case 20: - case 21: - case 22: - case 30: - case 32: - case 37: - case 41: - case 42: - case 45: - case 46: - case 47: - case 48: - case 49: - case 55: - case 56: - case 57: - case 58: - case 60: - case 7: - case 8: - case 9: - case 73: - 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 129: - case 133: - case 165: - case 166: - case 170: - case 172: - case 173: - case 174: - case 181: - case 182: - case 188: - case 189: - case 190: - case 191: - case 192: - vs[j] = (char) (id << 4); - return; - case 130: - case 76: - case 62: - this.relight[i]++; - case 54: - case 146: - case 61: - case 65: - case 68: - if (data < 2) { - data = 2; - } - default: - vs[j] = (char) ((id << 4) + data); - return; - } - } - - @Override - public void setBiome(int x, int z, BaseBiome biome) { - if (this.biomes == null) { - this.biomes = new byte[16][]; - } - byte[] index = this.biomes[x]; - if (index == null) { - index = this.biomes[x] = new byte[16]; - } - index[z] = (byte) biome.getId(); - } - - @Override - public FaweChunk clone() { - ForgeChunk_All toReturn = new ForgeChunk_All(getParent(), getX(), getZ()); - toReturn.air = this.air.clone(); - toReturn.count = this.count.clone(); - toReturn.relight = this.relight.clone(); - toReturn.ids = new char[this.ids.length][]; - for (int i = 0; i < this.ids.length; i++) { - char[] matrix = this.ids[i]; - if (matrix != null) { - toReturn.ids[i] = new char[matrix.length]; - System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length); - } - } - return toReturn; - } - - @Override - public FaweChunk copy(boolean shallow) { - ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ()); - if (shallow) { - copy.ids = ids; - copy.air = air; - copy.biomes = biomes; - copy.chunk = chunk; - copy.count = count; - copy.relight = relight; - } else { - copy.ids = (char[][]) MainUtil.copyNd(ids); - copy.air = air.clone(); - copy.biomes = biomes.clone(); - copy.chunk = chunk; - copy.count = count.clone(); - copy.relight = relight.clone(); - } - return copy; + public Chunk getNewChunk() { + World world = ((ForgeQueue_All) getParent()).getWorld(); + return world.getChunkProvider().provideChunk(getX(), getZ()); } } diff --git a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index e9f68388..7c59c9b1 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -2,23 +2,15 @@ package com.boydti.fawe.forge.v0; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.config.Settings; +import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.forge.ForgePlayer; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.PseudoRandom; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.exception.FaweException; -import com.boydti.fawe.util.FaweQueue; -import com.boydti.fawe.util.TaskManager; -import com.sk89q.worldedit.world.biome.BaseBiome; import java.lang.reflect.Field; import java.util.Iterator; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingDeque; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; @@ -36,12 +28,7 @@ import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.gen.ChunkProviderServer; -public class ForgeQueue_All extends FaweQueue { - - private World forgeWorld; - - private ConcurrentHashMap> blocks = new ConcurrentHashMap<>(); - private LinkedBlockingDeque> chunks = new LinkedBlockingDeque<>(); +public class ForgeQueue_All extends NMSMappedFaweQueue { public ForgeQueue_All(final String world) { super(world); @@ -52,22 +39,19 @@ public class ForgeQueue_All extends FaweQueue { return getWorld().getChunkProvider().chunkExists(x, z); } - public World getWorld() { - if (forgeWorld != null) { - return forgeWorld; - } + public World getWorld(String world) { WorldServer[] worlds = MinecraftServer.getServer().worldServers; for (WorldServer ws : worlds) { if (ws.provider.getDimensionName().equals(world)) { - return forgeWorld = ws; + return ws; } } return null; } @Override - public boolean regenerateChunk(int x, int z) { - IChunkProvider provider = getWorld().getChunkProvider(); + public boolean regenerateChunk(World world, int x, int z) { + IChunkProvider provider = world.getChunkProvider(); if (!(provider instanceof ChunkProviderServer)) { return false; } @@ -100,240 +84,33 @@ public class ForgeQueue_All extends FaweQueue { } @Override - public void addTask(int x, int z, Runnable runnable) { - long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x, z); - result.addTask(runnable); - FaweChunk previous = this.blocks.put(pair, result); - if (previous == null) { - chunks.add(result); - return; - } - this.blocks.put(pair, previous); - result = previous; - } - result.addTask(runnable); + public boolean loadChunk(World world, int x, int z, boolean generate) { + return getCachedChunk(world, x, z) != null; } - 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; - - private final RunnableVal loadChunk = new RunnableVal() { - @Override - public void run(IntegerPair loc) { - getWorld().getChunkProvider().provideChunk(loc.x, loc.z); + @Override + public Chunk getCachedChunk(World world, int x, int z) { + Chunk chunk = world.getChunkProvider().provideChunk(x, z); + if (chunk != null && !chunk.isLoaded()) { + chunk.onChunkLoad(); } - }; + return chunk; + } @Override - public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { - if (y < 0 || y > 255) { - return 0; - } - int cx = x >> 4; - int cz = z >> 4; - int cy = y >> 4; - if (cx != lcx || cz != lcz) { - World world = getWorld(); - lcx = cx; - lcz = cz; - IChunkProvider provider = world.getChunkProvider(); - Chunk chunk; - if (!provider.chunkExists(lcx, lcz)) { - boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); - if (sync) { - chunk = provider.provideChunk(cx, cz); - } else if (Settings.CHUNK_WAIT > 0) { - loadChunk.value = new IntegerPair(cx, cz); - TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT); - if (!provider.chunkExists(cx, cz)) { - throw new FaweException.FaweChunkLoadException(); - } - chunk = provider.provideChunk(cx, cz); - } else { - return 0; - } - } else { - chunk = provider.provideChunk(cx, cz); - } - lc = chunk; - } else if (cy == lcy) { - return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0; - } - ExtendedBlockStorage storage = lc.getBlockStorageArray()[cy]; - if (storage == null) { - ls = null; - return 0; - } - ls = storage.getData(); + public int getCombinedId4Data(char[] ls, int x, int y, int z) { return ls[FaweCache.CACHE_J[y][x & 15][z & 15]]; } - private FaweChunk lastChunk; - private int lastX = Integer.MIN_VALUE; - private int lastZ = Integer.MIN_VALUE; - @Override - public boolean setBlock(int x, int y, int z, short id, byte data) { - if ((y > 255) || (y < 0)) { - return false; - } - int cx = x >> 4; - int cz = z >> 4; - if (cx != lastX || cz != lastZ) { - lastX = cx; - lastZ = cz; - long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL; - lastChunk = this.blocks.get(pair); - if (lastChunk == null) { - lastChunk = this.getChunk(x >> 4, z >> 4); - lastChunk.setBlock(x & 15, y, z & 15, id, data); - FaweChunk previous = this.blocks.put(pair, lastChunk); - if (previous == null) { - chunks.add(lastChunk); - return true; - } - this.blocks.put(pair, previous); - lastChunk = previous; - } - } - lastChunk.setBlock(x & 15, y, z & 15, id, data); - return true; + public boolean isChunkLoaded(World world, int x, int z) { + return world.getChunkProvider().chunkExists(x, z); } @Override - public boolean setBiome(int x, int z, BaseBiome biome) { - long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x >> 4, z >> 4); - FaweChunk previous = this.blocks.put(pair, result); - if (previous != null) { - this.blocks.put(pair, previous); - result = previous; - } else { - chunks.add(result); - } - } - result.setBiome(x & 15, z & 15, biome); - return true; - } - - @Override - public FaweChunk next() { - lastX = Integer.MIN_VALUE; - lastZ = Integer.MIN_VALUE; - try { - if (this.blocks.size() == 0) { - return null; - } - synchronized (blocks) { - FaweChunk chunk = chunks.poll(); - if (chunk != null) { - blocks.remove(chunk.longHash()); - this.execute(chunk); - return chunk; - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - return null; - } - - @Override - public int size() { - return chunks.size(); - } - - private LinkedBlockingDeque> toUpdate = new LinkedBlockingDeque<>(); - - public boolean execute(FaweChunk fc) { - if (fc == null) { - return false; - } - // Load chunk - Chunk chunk = fc.getChunk(); - if (!chunk.isLoaded()) { - chunk.onChunkLoad(); - } - // Set blocks / entities / biome - if (!this.setComponents(fc)) { - return false; - } - fc.executeTasks(); - return true; - } - - @Override - public void clear() { - this.blocks.clear(); - this.chunks.clear(); - } - - @Override - public void setChunk(FaweChunk chunk) { - FaweChunk previous = this.blocks.put(chunk.longHash(), (FaweChunk) chunk); - if (previous != null) { - chunks.remove(previous); - } - chunks.add((FaweChunk) chunk); - } - - public void sendChunk(FaweChunk fc) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING; - TaskManager.IMP.sync(new Runnable() { - @Override - public void run() { - if (!result) { - fixLighting(fc, Settings.FIX_ALL_LIGHTING); - } - Chunk chunk = fc.getChunk(); - if (!chunk.isLoaded()) { - return; - } - World world = chunk.getWorld(); - ChunkCoordIntPair pos = chunk.getChunkCoordIntPair(); - int cx = pos.chunkXPos; - int cz = pos.chunkZPos; - for (FawePlayer fp : Fawe.get().getCachedPlayers()) { - ForgePlayer forgePlayer = (ForgePlayer) fp; - EntityPlayerMP player = forgePlayer.parent; - if (!player.worldObj.equals(world)) { - continue; - } - int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance(); - EntityPlayerMP nmsPlayer = (EntityPlayerMP) player; - BlockPos loc = player.getPosition(); - int px = loc.getX() >> 4; - int pz = loc.getZ() >> 4; - int dx = Math.abs(cx - (loc.getX() >> 4)); - int dz = Math.abs(cz - (loc.getZ() >> 4)); - if ((dx > view) || (dz > view)) { - continue; - } - NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler; - con.sendPacket(new S21PacketChunkData(chunk, false, 65535)); - // Try sending true, 0 first - // Try bulk chunk packet - } - } - }, false); - } - }, Settings.ASYNC_LIGHTING); - } - - public boolean setComponents(FaweChunk fc) { + public boolean setComponents(FaweChunk fc) { ForgeChunk_All fs = (ForgeChunk_All) fc; - Chunk forgeChunk = fc.getChunk(); + Chunk forgeChunk = fs.getChunk(); net.minecraft.world.World nmsWorld = forgeChunk.getWorld(); try { boolean flag = !nmsWorld.provider.getHasNoSky(); @@ -407,19 +184,19 @@ public class ForgeQueue_All extends FaweQueue { } catch (Throwable e) { e.printStackTrace(); } - byte[][] biomes = fs.biomes; + int[][] biomes = fs.biomes; if (biomes != null) { for (int x = 0; x < 16; x++) { - byte[] array = biomes[x]; + int[] array = biomes[x]; if (array == null) { continue; } for (int z = 0; z < 16; z++) { - byte biome = array[z]; + int biome = array[z]; if (biome == 0) { continue; } - forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = biome; + forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; } } } @@ -427,13 +204,44 @@ public class ForgeQueue_All extends FaweQueue { return true; } + @Override + public void refreshChunk(World world, Chunk chunk) { + if (!chunk.isLoaded()) { + return; + } + ChunkCoordIntPair pos = chunk.getChunkCoordIntPair(); + int cx = pos.chunkXPos; + int cz = pos.chunkZPos; + for (FawePlayer fp : Fawe.get().getCachedPlayers()) { + ForgePlayer forgePlayer = (ForgePlayer) fp; + EntityPlayerMP player = forgePlayer.parent; + if (!player.worldObj.equals(world)) { + continue; + } + int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance(); + EntityPlayerMP nmsPlayer = (EntityPlayerMP) player; + BlockPos loc = player.getPosition(); + int px = loc.getX() >> 4; + int pz = loc.getZ() >> 4; + int dx = Math.abs(cx - (loc.getX() >> 4)); + int dz = Math.abs(cz - (loc.getZ() >> 4)); + if ((dx > view) || (dz > view)) { + continue; + } + NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler; + con.sendPacket(new S21PacketChunkData(chunk, false, 65535)); + // Try sending true, 0 first + // Try bulk chunk packet + } + } + @Override public FaweChunk getChunk(int x, int z) { return new ForgeChunk_All(this, x, z); } @Override - public boolean fixLighting(FaweChunk chunk, boolean fixAll) { + public boolean fixLighting(FaweChunk chunk, boolean fixAll) { try { ForgeChunk_All fc = (ForgeChunk_All) chunk; Chunk forgeChunk = fc.getChunk(); diff --git a/settings.gradle b/settings.gradle index 6de5dbef..8b7727f8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ rootProject.name = 'FastAsyncWorldEdit' -include 'core', 'bukkit', 'forge189', 'forge1710', 'sponge' +include 'core', 'bukkit0', 'bukkit19', 'bukkit18', 'forge189', 'forge1710', 'sponge' diff --git a/sponge/src/main/java/com/boydti/fawe/sponge/FaweSponge.java b/sponge/src/main/java/com/boydti/fawe/sponge/FaweSponge.java index 5d79a258..ac213694 100644 --- a/sponge/src/main/java/com/boydti/fawe/sponge/FaweSponge.java +++ b/sponge/src/main/java/com/boydti/fawe/sponge/FaweSponge.java @@ -2,13 +2,14 @@ package com.boydti.fawe.sponge; import com.boydti.fawe.Fawe; import com.boydti.fawe.IFawe; -import com.boydti.fawe.config.BBC; import com.boydti.fawe.SpongeCommand; -import com.boydti.fawe.v1_8.SpongeQueue_1_8; +import com.boydti.fawe.config.BBC; import com.boydti.fawe.object.EditSessionWrapper; import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.regions.FaweMaskManager; +import com.boydti.fawe.sponge.v1_8.SpongeQueue_1_8; +import com.boydti.fawe.sponge.v1_8.SpongeQueue_ALL; import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.EditSession; @@ -112,8 +113,15 @@ public class FaweSponge implements IFawe { } @Override - public FaweQueue getNewQueue(String world) { - return new SpongeQueue_1_8(world); + public FaweQueue getNewQueue(String world, boolean fast) { + if (fast) { + try { + return new SpongeQueue_1_8(world); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return new SpongeQueue_ALL(world); } @Override diff --git a/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeChunk_1_8.java b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeChunk_1_8.java new file mode 100644 index 00000000..07b7355d --- /dev/null +++ b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeChunk_1_8.java @@ -0,0 +1,19 @@ +package com.boydti.fawe.sponge.v1_8; + +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.util.FaweQueue; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.world.World; + +public class SpongeChunk_1_8 extends CharFaweChunk { + + public SpongeChunk_1_8(FaweQueue parent, int x, int z) { + super(parent, x, z); + } + + @Override + public net.minecraft.world.chunk.Chunk getNewChunk() { + World world = Sponge.getServer().getWorld(getParent().world).get(); + return (net.minecraft.world.chunk.Chunk) world.loadChunk(getX(), 0, getZ(), true).get(); + } +} diff --git a/sponge/src/main/java/com/boydti/fawe/v1_8/SpongeQueue_1_8.java b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_1_8.java similarity index 59% rename from sponge/src/main/java/com/boydti/fawe/v1_8/SpongeQueue_1_8.java rename to sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_1_8.java index 136ec30d..016cf1c3 100644 --- a/sponge/src/main/java/com/boydti/fawe/v1_8/SpongeQueue_1_8.java +++ b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_1_8.java @@ -1,23 +1,14 @@ -package com.boydti.fawe.v1_8; +package com.boydti.fawe.sponge.v1_8; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.sponge.SpongeUtil; -import com.boydti.fawe.v0.SpongeQueue_0; +import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.PseudoRandom; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.object.exception.FaweException; -import com.boydti.fawe.util.TaskManager; -import com.flowpowered.math.vector.Vector3i; import java.lang.reflect.Field; -import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.entity.Entity; @@ -38,150 +29,114 @@ import org.spongepowered.api.world.Chunk; import org.spongepowered.api.world.Location; import org.spongepowered.api.world.World; -public class SpongeQueue_1_8 extends SpongeQueue_0 { - - public World spongeWorld; - +public class SpongeQueue_1_8 extends NMSMappedFaweQueue { public SpongeQueue_1_8(String world) { super(world); } - private final RunnableVal loadChunk = new RunnableVal() { - @Override - public void run(IntegerPair loc) { - if (spongeWorld == null) { - spongeWorld = Sponge.getServer().getWorld(world).get(); - } - Chunk chunk = spongeWorld.getChunk(loc.x, 0, loc.z).orElse(null); - if (chunk == null || !chunk.isLoaded()) { - spongeWorld.loadChunk(loc.x, 0, loc.z, true); - } - } - }; - @Override - public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { - if (y < 0 || y > 255) { - return 0; + public void refreshChunk(World world, net.minecraft.world.chunk.Chunk chunk) { + if (!chunk.isLoaded()) { + return; } - 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(); + int cx = chunk.xPosition; + int cz = chunk.zPosition; + for (Player player : Sponge.getServer().getOnlinePlayers()) { + if (!player.getWorld().equals(world)) { + continue; } - lcx = cx; - lcz = cz; - Chunk chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null); - if (chunk == null || !chunk.isLoaded()) { - boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); - if (sync) { - chunk = spongeWorld.loadChunk(cx, 0, cz, true).orElse(null); - } else if (Settings.CHUNK_WAIT > 0) { - loadChunk.value = new IntegerPair(cx, cz); - TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT); - chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null); - if (chunk == null || !chunk.isLoaded()) { - throw new FaweException.FaweChunkLoadException(); - } - } else { - return 0; - } + int view = player.getViewDistance(); + EntityPlayerMP nmsPlayer = (EntityPlayerMP) player; + Location loc = player.getLocation(); + int px = loc.getBlockX() >> 4; + int pz = loc.getBlockZ() >> 4; + int dx = Math.abs(cx - (loc.getBlockX() >> 4)); + int dz = Math.abs(cz - (loc.getBlockZ() >> 4)); + if ((dx > view) || (dz > view)) { + continue; } - lc = (net.minecraft.world.chunk.Chunk) chunk; - } else if (cy == lcy) { - return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0; + NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler; + net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk; + con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535)); + // Try sending true, 0 first + // Try bulk chunk packet } - 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 Collection> sendChunk(Collection> fcs) { - if (fcs.isEmpty()) { - return fcs; - } - for (FaweChunk chunk : fcs) { - sendChunk(chunk); - } - fcs.clear(); - return fcs; + public char[] getCachedSection(ExtendedBlockStorage[] chunk, int cy) { + ExtendedBlockStorage value = chunk[cy]; + return value == null ? null : value.getData(); } - public void sendChunk(FaweChunk fc) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING; - TaskManager.IMP.sync(new Runnable() { - @Override - public void run() { - if (!result) { - fixLighting(fc, Settings.FIX_ALL_LIGHTING); - } - Chunk chunk = fc.getChunk(); - if (!chunk.isLoaded()) { - return; - } - World world = chunk.getWorld(); - Vector3i pos = chunk.getBlockMin(); - int cx = pos.getX() >> 4; - int cz = pos.getZ() >> 4; - for (Player player : Sponge.getServer().getOnlinePlayers()) { - if (!player.getWorld().equals(world)) { - continue; - } - int view = player.getViewDistance(); - EntityPlayerMP nmsPlayer = (EntityPlayerMP) player; - Location loc = player.getLocation(); - int px = loc.getBlockX() >> 4; - int pz = loc.getBlockZ() >> 4; - int dx = Math.abs(cx - (loc.getBlockX() >> 4)); - int dz = Math.abs(cz - (loc.getBlockZ() >> 4)); - if ((dx > view) || (dz > view)) { - continue; - } - NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler; - net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk; - con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535)); - // Try sending true, 0 first - // Try bulk chunk packet - } - } - }, false); - } - }, Settings.ASYNC_LIGHTING); - } - - 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 boolean setComponents(FaweChunk fc) { + public World getWorld(String world) { + return Sponge.getServer().getWorld(this.world).get(); + } + + @Override + public boolean isChunkLoaded(World world, int x, int z) { + Chunk chunk = world.getChunk(x << 4, 0, z << 4).orElse(null); + return chunk != null && chunk.isLoaded(); + } + + @Override + public boolean regenerateChunk(World world, int x, int z) { + try { + net.minecraft.world.World nmsWorld = (net.minecraft.world.World) world; + IChunkProvider provider = nmsWorld.getChunkProvider(); + if (!(provider instanceof ChunkProviderServer)) { + return false; + } + ChunkProviderServer chunkServer = (ChunkProviderServer) provider; + Field chunkProviderField = chunkServer.getClass().getDeclaredField("field_73246_d"); + chunkProviderField.setAccessible(true); + IChunkProvider chunkProvider = (IChunkProvider) chunkProviderField.get(chunkServer); + long pos = ChunkCoordIntPair.chunkXZ2Int(x, z); + net.minecraft.world.chunk.Chunk mcChunk; + if (chunkServer.chunkExists(x, z)) { + mcChunk = chunkServer.loadChunk(x, z); + mcChunk.onChunkUnload(); + } + Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b"); + droppedChunksSetField.setAccessible(true); + Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer); + droppedChunksSet.remove(pos); + Field id2ChunkMapField = chunkServer.getClass().getDeclaredField("field_73244_f"); + id2ChunkMapField.setAccessible(true); + LongHashMap id2ChunkMap = (LongHashMap) id2ChunkMapField.get(chunkServer); + id2ChunkMap.remove(pos); + mcChunk = chunkProvider.provideChunk(x, z); + id2ChunkMap.add(pos, mcChunk); + List loadedChunks = chunkServer.func_152380_a(); + loadedChunks.add(mcChunk); + if (mcChunk != null) { + mcChunk.onChunkLoad(); + mcChunk.populateChunk(chunkProvider, chunkProvider, x, z); + } + return true; + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + @Override + public boolean setComponents(FaweChunk fc) { SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc; - Chunk spongeChunk = fc.getChunk(); - net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeChunk.getWorld(); + net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); + net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); try { boolean flag = !nmsWorld.provider.getHasNoSky(); // Sections - net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk; ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); Map tiles = nmsChunk.getTileEntityMap(); ClassInheritanceMultiMap[] entities = nmsChunk.getEntityLists(); // Trim tiles - Set> entryset = tiles.entrySet(); - Iterator> iterator = entryset.iterator(); + Set> entryset = tiles.entrySet(); + Iterator> iterator = entryset.iterator(); while (iterator.hasNext()) { - Entry tile = iterator.next(); + Map.Entry tile = iterator.next(); BlockPos pos = tile.getKey(); int lx = pos.getX() & 15; int ly = pos.getY(); @@ -204,7 +159,8 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { } // Efficiently merge sections for (int j = 0; j < sections.length; j++) { - if (fs.getCount(j) == 0) { + int count = fs.getCount(j); + if (count == 0) { continue; } char[] newArray = fs.getIdArray(j); @@ -212,14 +168,20 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { continue; } ExtendedBlockStorage section = sections[j]; - if ((section == null) || (fs.getCount(j) >= 4096)) { + + if ((section == null)) { section = new ExtendedBlockStorage(j << 4, flag); section.setData(newArray); sections[j] = section; continue; + } else if (count >= 4096){ + section.setData(newArray); + setCount(0, count - fs.getAir(j), section); + continue; } char[] currentArray = section.getData(); boolean fill = true; + int solid = 0; for (int k = 0; k < newArray.length; k++) { char n = newArray[k]; switch (n) { @@ -228,18 +190,22 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { continue; case 1: fill = false; + if (currentArray[k] > 1) { + solid++; + } currentArray[k] = 0; continue; default: + solid++; currentArray[k] = n; continue; } } + setCount(0, solid, section); if (fill) { fs.setCount(j, Short.MAX_VALUE); } } -// // Clear } catch (Throwable e) { e.printStackTrace(); } @@ -255,7 +221,7 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { if (biome == 0) { continue; } - spongeChunk.setBiome(x, z, SpongeUtil.getBiome(biome)); + nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; } } } @@ -263,24 +229,29 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { return true; } - /** - * This should be overridden by any specialized queues. - * @param x - * @param z - */ - @Override - public SpongeChunk_1_8 getChunk(int x, int z) { - return new SpongeChunk_1_8(this, x, z); + public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException { + Class clazz = section.getClass(); + Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c"); + Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b"); + fieldTickingBlockCount.setAccessible(true); + fieldNonEmptyBlockCount.setAccessible(true); + fieldTickingBlockCount.set(section, tickingBlockCount); + fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); } @Override - public boolean fixLighting(FaweChunk pc, boolean fixAll) { + public FaweChunk getChunk(int x, int z) { + return new SpongeChunk_1_8(this, x, z); + } + + + @Override + public boolean fixLighting(FaweChunk fc, boolean fixAll) { try { - SpongeChunk_1_8 bc = (SpongeChunk_1_8) pc; - Chunk spongeChunk = bc.getChunk(); - net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk; - if (!spongeChunk.isLoaded()) { - if (!spongeChunk.loadChunk(false)) { + SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc; + net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk(); + if (!nmsChunk.isLoaded()) { + if (!((Chunk) nmsChunk).loadChunk(false)) { return false; } } @@ -291,8 +262,8 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); - int X = pc.getX() << 4; - int Z = pc.getZ() << 4; + int X = bc.getX() << 4; + int Z = bc.getZ() << 4; for (int j = 0; j < sections.length; j++) { @@ -355,50 +326,6 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { return false; } - @Override - public boolean regenerateChunk(int x, int z) { - if (spongeWorld == null) { - spongeWorld = Sponge.getServer().getWorld(world).get(); - } - try { - net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeWorld; - IChunkProvider provider = nmsWorld.getChunkProvider(); - if (!(provider instanceof ChunkProviderServer)) { - return false; - } - ChunkProviderServer chunkServer = (ChunkProviderServer) provider; - Field chunkProviderField = chunkServer.getClass().getDeclaredField("field_73246_d"); - chunkProviderField.setAccessible(true); - IChunkProvider chunkProvider = (IChunkProvider) chunkProviderField.get(chunkServer); - long pos = ChunkCoordIntPair.chunkXZ2Int(x, z); - net.minecraft.world.chunk.Chunk mcChunk; - if (chunkServer.chunkExists(x, z)) { - mcChunk = chunkServer.loadChunk(x, z); - mcChunk.onChunkUnload(); - } - Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b"); - droppedChunksSetField.setAccessible(true); - Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer); - droppedChunksSet.remove(pos); - Field id2ChunkMapField = chunkServer.getClass().getDeclaredField("field_73244_f"); - id2ChunkMapField.setAccessible(true); - LongHashMap id2ChunkMap = (LongHashMap) id2ChunkMapField.get(chunkServer); - id2ChunkMap.remove(pos); - mcChunk = chunkProvider.provideChunk(x, z); - id2ChunkMap.add(pos, mcChunk); - List loadedChunks = chunkServer.func_152380_a(); - loadedChunks.add(mcChunk); - if (mcChunk != null) { - mcChunk.onChunkLoad(); - mcChunk.populateChunk(chunkProvider, chunkProvider, x, z); - } - return true; - } catch (Throwable e) { - e.printStackTrace(); - } - return false; - } - public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) { return isSolid(getId(sections, x, y + 1, z)) && isSolid(getId(sections, x + 1, y - 1, z)) @@ -427,4 +354,20 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 { int j = FaweCache.CACHE_J[y][x][z]; return array[j] >> 4; } + + @Override + public boolean loadChunk(World world, int x, int z, boolean generate) { + return getCachedChunk(world, x, z) != null; + } + + @Override + public ExtendedBlockStorage[] getCachedChunk(World world, int cx, int cz) { + Chunk chunk = world.loadChunk(cx, 0, cz, true).orElse(null); + return ((net.minecraft.world.chunk.Chunk) chunk).getBlockStorageArray(); + } + + @Override + public int getCombinedId4Data(char[] chars, int x, int y, int z) { + return chars[FaweCache.CACHE_J[y][x & 15][z & 15]]; + } } diff --git a/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_ALL.java b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_ALL.java new file mode 100644 index 00000000..f0260e08 --- /dev/null +++ b/sponge/src/main/java/com/boydti/fawe/sponge/v1_8/SpongeQueue_ALL.java @@ -0,0 +1,310 @@ +package com.boydti.fawe.sponge.v1_8; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.example.NMSMappedFaweQueue; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.PseudoRandom; +import java.lang.reflect.Field; +import java.util.List; +import java.util.Set; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.play.server.S21PacketChunkData; +import net.minecraft.util.BlockPos; +import net.minecraft.util.LongHashMap; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import net.minecraft.world.gen.ChunkProviderServer; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.block.BlockState; +import org.spongepowered.api.block.BlockTypes; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.world.Chunk; +import org.spongepowered.api.world.Location; +import org.spongepowered.api.world.World; +import org.spongepowered.api.world.extent.UnmodifiableBlockVolume; +import org.spongepowered.api.world.extent.worker.MutableBlockVolumeWorker; +import org.spongepowered.api.world.extent.worker.procedure.BlockVolumeMapper; + +public class SpongeQueue_ALL extends NMSMappedFaweQueue { + public SpongeQueue_ALL(String world) { + super(world); + } + + @Override + public void refreshChunk(World world, net.minecraft.world.chunk.Chunk chunk) { + if (!chunk.isLoaded()) { + return; + } + int cx = chunk.xPosition; + int cz = chunk.zPosition; + for (Player player : Sponge.getServer().getOnlinePlayers()) { + if (!player.getWorld().equals(world)) { + continue; + } + int view = player.getViewDistance(); + EntityPlayerMP nmsPlayer = (EntityPlayerMP) player; + Location loc = player.getLocation(); + int px = loc.getBlockX() >> 4; + int pz = loc.getBlockZ() >> 4; + int dx = Math.abs(cx - (loc.getBlockX() >> 4)); + int dz = Math.abs(cz - (loc.getBlockZ() >> 4)); + if ((dx > view) || (dz > view)) { + continue; + } + NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler; + net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk; + con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535)); + // Try sending true, 0 first + // Try bulk chunk packet + } + } + + @Override + public char[] getCachedSection(ExtendedBlockStorage[] chunk, int cy) { + ExtendedBlockStorage value = chunk[cy]; + return value == null ? null : value.getData(); + } + + @Override + public World getWorld(String world) { + return Sponge.getServer().getWorld(this.world).get(); + } + + @Override + public boolean isChunkLoaded(World world, int x, int z) { + Chunk chunk = world.getChunk(x << 4, 0, z << 4).orElse(null); + return chunk != null && chunk.isLoaded(); + } + + @Override + public boolean regenerateChunk(World world, int x, int z) { + try { + net.minecraft.world.World nmsWorld = (net.minecraft.world.World) world; + IChunkProvider provider = nmsWorld.getChunkProvider(); + if (!(provider instanceof ChunkProviderServer)) { + return false; + } + ChunkProviderServer chunkServer = (ChunkProviderServer) provider; + Field chunkProviderField = chunkServer.getClass().getDeclaredField("field_73246_d"); + chunkProviderField.setAccessible(true); + IChunkProvider chunkProvider = (IChunkProvider) chunkProviderField.get(chunkServer); + long pos = ChunkCoordIntPair.chunkXZ2Int(x, z); + net.minecraft.world.chunk.Chunk mcChunk; + if (chunkServer.chunkExists(x, z)) { + mcChunk = chunkServer.loadChunk(x, z); + mcChunk.onChunkUnload(); + } + Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b"); + droppedChunksSetField.setAccessible(true); + Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer); + droppedChunksSet.remove(pos); + Field id2ChunkMapField = chunkServer.getClass().getDeclaredField("field_73244_f"); + id2ChunkMapField.setAccessible(true); + LongHashMap id2ChunkMap = (LongHashMap) id2ChunkMapField.get(chunkServer); + id2ChunkMap.remove(pos); + mcChunk = chunkProvider.provideChunk(x, z); + id2ChunkMap.add(pos, mcChunk); + List loadedChunks = chunkServer.func_152380_a(); + loadedChunks.add(mcChunk); + if (mcChunk != null) { + mcChunk.onChunkLoad(); + mcChunk.populateChunk(chunkProvider, chunkProvider, x, z); + } + return true; + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + private BlockState AIR = BlockTypes.AIR.getDefaultState(); + + @Override + public boolean setComponents(FaweChunk fc) { + SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc; + net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); + Chunk spongeChunk = (Chunk) nmsChunk; + + char[][] ids = ((SpongeChunk_1_8) fc).getIdArrays(); + MutableBlockVolumeWorker blockWorker = spongeChunk.getBlockWorker(); + blockWorker.map(new BlockVolumeMapper() { + @Override + public BlockState map(UnmodifiableBlockVolume volume, int xx, int y, int zz) { + int x = xx & 15; + int z = zz & 15; + int i = FaweCache.CACHE_I[y][x][z]; + char[] array = ids[i]; + if (array == null) { + return null; + } + int combinedId = array[FaweCache.CACHE_J[y][x][z]]; + switch (combinedId) { + case 0: + return null; + case 1: + return AIR; + default: + int id = combinedId >> 4; + Block block = Block.getBlockById(id); + int data = combinedId & 0xf; + IBlockState ibd; + if (data != 0) { + ibd = block.getStateFromMeta(data); + } else { + ibd = block.getDefaultState(); + } + return (BlockState) ibd; + } + } + }); + sendChunk(fs); + return true; + } + + public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException { + Class clazz = section.getClass(); + Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c"); + Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b"); + fieldTickingBlockCount.setAccessible(true); + fieldNonEmptyBlockCount.setAccessible(true); + fieldTickingBlockCount.set(section, tickingBlockCount); + fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); + } + + @Override + public FaweChunk getChunk(int x, int z) { + return new SpongeChunk_1_8(this, x, z); + } + + + @Override + public boolean fixLighting(FaweChunk fc, boolean fixAll) { + try { + SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc; + net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk(); + if (!nmsChunk.isLoaded()) { + if (!((Chunk) nmsChunk).loadChunk(false)) { + return false; + } + } + nmsChunk.generateSkylightMap(); + if (bc.getTotalRelight() == 0 && !fixAll) { + return true; + } + ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); + net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); + + int X = bc.getX() << 4; + int Z = bc.getZ() << 4; + + + for (int j = 0; j < sections.length; j++) { + ExtendedBlockStorage section = sections[j]; + if (section == null) { + continue; + } + if ((bc.getRelight(j) == 0 && !fixAll) || bc.getCount(j) == 0 || (bc.getCount(j) >= 4096 && bc.getAir(j) == 0)) { + continue; + } + char[] array = section.getData(); + int l = PseudoRandom.random.random(2); + for (int k = 0; k < array.length; k++) { + int i = array[k]; + if (i < 16) { + continue; + } + short id = (short) (i >> 4); + switch (id) { // Lighting + default: + if (!fixAll) { + continue; + } + if ((k & 1) == l) { + l = 1 - l; + continue; + } + case 10: + case 11: + case 39: + case 40: + case 50: + case 51: + case 62: + case 74: + case 76: + case 89: + case 122: + case 124: + case 130: + case 138: + case 169: + int x = FaweCache.CACHE_X[j][k]; + int y = FaweCache.CACHE_Y[j][k]; + int z = FaweCache.CACHE_Z[j][k]; + if (isSurrounded(sections, x, y, z)) { + continue; + } + BlockPos pos = new BlockPos(X + x, y, Z + z); + nmsWorld.checkLight(pos); + } + } + } + return true; + } catch (Throwable e) { + if (Thread.currentThread() == Fawe.get().getMainThread()) { + e.printStackTrace(); + } + } + return false; + } + + public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) { + return isSolid(getId(sections, x, y + 1, z)) + && isSolid(getId(sections, x + 1, y - 1, z)) + && isSolid(getId(sections, x - 1, y, z)) + && isSolid(getId(sections, x, y, z + 1)) + && isSolid(getId(sections, x, y, z - 1)); + } + + public boolean isSolid(int i) { + return i != 0 && Block.getBlockById(i).isOpaqueCube(); + } + + public int getId(ExtendedBlockStorage[] sections, int x, int y, int z) { + if (x < 0 || x > 15 || z < 0 || z > 15) { + return 1; + } + if (y < 0 || y > 255) { + return 1; + } + int i = FaweCache.CACHE_I[y][x][z]; + ExtendedBlockStorage section = sections[i]; + if (section == null) { + return 0; + } + char[] array = section.getData(); + int j = FaweCache.CACHE_J[y][x][z]; + return array[j] >> 4; + } + + @Override + public boolean loadChunk(World world, int x, int z, boolean generate) { + return getCachedChunk(world, x, z) != null; + } + + @Override + public ExtendedBlockStorage[] getCachedChunk(World world, int cx, int cz) { + Chunk chunk = world.loadChunk(cx, 0, cz, true).orElse(null); + return ((net.minecraft.world.chunk.Chunk) chunk).getBlockStorageArray(); + } + + @Override + public int getCombinedId4Data(char[] chars, int x, int y, int z) { + return chars[FaweCache.CACHE_J[y][x & 15][z & 15]]; + } +} diff --git a/sponge/src/main/java/com/boydti/fawe/v0/SpongeQueue_0.java b/sponge/src/main/java/com/boydti/fawe/v0/SpongeQueue_0.java deleted file mode 100644 index 799cba40..00000000 --- a/sponge/src/main/java/com/boydti/fawe/v0/SpongeQueue_0.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.boydti.fawe.v0; - -import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.util.FaweQueue; -import com.sk89q.worldedit.world.biome.BaseBiome; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingDeque; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.world.Chunk; -import org.spongepowered.api.world.World; - -public abstract class SpongeQueue_0 extends FaweQueue { - - /** - * Map of chunks in the queue - */ - private final ConcurrentHashMap> blocks = new ConcurrentHashMap<>(); - private LinkedBlockingDeque> chunks = new LinkedBlockingDeque<>(); - - public SpongeQueue_0(String world) { - super(world); - } - - @Override - 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(int x, int z, Runnable runnable) { - long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x, z); - result.addTask(runnable); - final FaweChunk previous = this.blocks.put(pair, result); - if (previous == null) { - chunks.add(result); - return; - } - this.blocks.put(pair, previous); - result = previous; - } - result.addTask(runnable); - } - - private FaweChunk lastChunk; - private int lastX = Integer.MIN_VALUE; - private int lastZ = Integer.MIN_VALUE; - - @Override - public boolean setBlock(int x, final int y, int z, final short id, final byte data) { - if ((y > 255) || (y < 0)) { - return false; - } - int cx = x >> 4; - int cz = z >> 4; - if (cx != lastX || cz != lastZ) { - lastX = cx; - lastZ = cz; - long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL; - lastChunk = this.blocks.get(pair); - if (lastChunk == null) { - lastChunk = this.getChunk(x >> 4, z >> 4); - lastChunk.setBlock(x & 15, y, z & 15, id, data); - FaweChunk previous = this.blocks.put(pair, lastChunk); - if (previous == null) { - chunks.add(lastChunk); - return true; - } - this.blocks.put(pair, previous); - lastChunk = previous; - } - } - lastChunk.setBlock(x & 15, y, z & 15, id, data); - return true; - } - - @Override - public boolean setBiome(int x, int z, final BaseBiome biome) { - long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL; - FaweChunk result = this.blocks.get(pair); - if (result == null) { - result = this.getChunk(x >> 4, z >> 4); - final FaweChunk previous = this.blocks.put(pair, result); - if (previous != null) { - this.blocks.put(pair, previous); - result = previous; - } - } - result.setBiome(x & 15, z & 15, biome); - return true; - } - - @Override - public FaweChunk next() { - lastX = Integer.MIN_VALUE; - lastZ = Integer.MIN_VALUE; - try { - if (this.blocks.size() == 0) { - return null; - } - synchronized (blocks) { - FaweChunk chunk = chunks.poll(); - if (chunk != null) { - blocks.remove(chunk.longHash()); - this.execute(chunk); - return chunk; - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - return null; - } - - @Override - public int size() { - return chunks.size(); - } - - private final LinkedBlockingDeque> toUpdate = new LinkedBlockingDeque<>(); - - public boolean execute(final FaweChunk fc) { - if (fc == null) { - return false; - } - // Load chunk - final Chunk chunk = fc.getChunk(); - chunk.loadChunk(true); - // Set blocks / entities / biome - if (!this.setComponents(fc)) { - return false; - } - fc.executeTasks(); - return true; - } - - @Override - public void clear() { - this.blocks.clear(); - this.chunks.clear(); - } - - @Override - public void setChunk(final FaweChunk chunk) { - FaweChunk previous = this.blocks.put(chunk.longHash(), (FaweChunk) chunk); - if (previous != null) { - chunks.remove(previous); - } - chunks.add((FaweChunk) chunk); - } - - public abstract Collection> sendChunk(final Collection> fcs); - - public abstract boolean setComponents(final FaweChunk fc); - - @Override - public abstract FaweChunk getChunk(int x, int z); - - @Override - public abstract boolean fixLighting(final FaweChunk fc, final boolean fixAll); -} diff --git a/sponge/src/main/java/com/boydti/fawe/v1_8/SpongeChunk_1_8.java b/sponge/src/main/java/com/boydti/fawe/v1_8/SpongeChunk_1_8.java deleted file mode 100644 index 956ca1ef..00000000 --- a/sponge/src/main/java/com/boydti/fawe/v1_8/SpongeChunk_1_8.java +++ /dev/null @@ -1,244 +0,0 @@ -package com.boydti.fawe.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.spongepowered.api.Sponge; -import org.spongepowered.api.world.Chunk; -import org.spongepowered.api.world.World; - -public class SpongeChunk_1_8 extends FaweChunk { - - public char[][] ids; - public short[] count; - public short[] air; - public short[] relight; - public int[][] biomes; - public Chunk 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) { - World world = Sponge.getServer().getWorld(getParent().world).get(); - this.chunk = world.loadChunk(getX(), 0, getZ(), true).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 - * @return - */ - public int getCount(int i) { - return this.count[i]; - } - - public int getAir(int i) { - return this.air[i]; - } - - public void setCount(int i, short value) { - this.count[i] = value; - } - - /** - * Get the number of block changes in a specified section. - * @param i - * @return - */ - public int getRelight(int i) { - return this.relight[i]; - } - - public int getTotalCount() { - int total = 0; - for (int i = 0; i < 16; i++) { - total += this.count[i]; - } - return total; - } - - public int getTotalRelight() { - if (getTotalCount() == 0) { - Arrays.fill(this.count, (short) 1); - Arrays.fill(this.relight, Short.MAX_VALUE); - return Short.MAX_VALUE; - } - int total = 0; - for (int i = 0; i < 16; i++) { - total += this.relight[i]; - } - return total; - } - - /** - * Get the raw data for a section. - * @param i - * @return - */ - public char[] getIdArray(int i) { - return this.ids[i]; - } - - @Override - public void setBlock(int x, int y, int z, int id, byte data) { - int i = FaweCache.CACHE_I[y][x][z]; - int j = FaweCache.CACHE_J[y][x][z]; - char[] vs = this.ids[i]; - if (vs == null) { - vs = this.ids[i] = new char[4096]; - this.count[i]++; - } else if (vs[j] == 0) { - this.count[i]++; - } - switch (id) { - case 0: - this.air[i]++; - vs[j] = (char) 1; - return; - case 10: - case 11: - case 39: - case 40: - case 51: - case 74: - case 89: - case 122: - case 124: - case 138: - case 169: - this.relight[i]++; - case 2: - case 4: - case 13: - case 14: - case 15: - case 20: - case 21: - case 22: - case 30: - case 32: - case 37: - case 41: - case 42: - case 45: - case 46: - case 47: - case 48: - case 49: - case 55: - case 56: - case 57: - case 58: - case 60: - case 7: - case 8: - case 9: - case 73: - 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 129: - case 133: - case 165: - case 166: - case 170: - case 172: - case 173: - case 174: - case 181: - case 182: - case 188: - case 189: - case 190: - case 191: - case 192: - vs[j] = (char) (id << 4); - return; - case 130: - case 76: - case 62: - this.relight[i]++; - case 54: - case 146: - case 61: - case 65: - case 68: - if (data < 2) { - data = 2; - } - default: - vs[j] = (char) ((id << 4) + data); - return; - } - } - - @Override - public void setBiome(int x, int z, BaseBiome biome) { - if (this.biomes == null) { - this.biomes = new int[16][]; - } - int[] index = this.biomes[x]; - if (index == null) { - index = this.biomes[x] = new int[16]; - } - index[z] = biome.getId(); - } - - @Override - public FaweChunk copy(boolean shallow) { - SpongeChunk_1_8 toReturn = new SpongeChunk_1_8(getParent(), getX(), getZ()); - if (shallow) { - toReturn.ids = ids; - toReturn.air = air; - toReturn.biomes = biomes; - toReturn.chunk = chunk; - toReturn.count = count; - toReturn.relight = relight; - } else { - toReturn.air = this.air.clone(); - toReturn.count = this.count.clone(); - toReturn.relight = this.relight.clone(); - toReturn.ids = new char[this.ids.length][]; - for (int i = 0; i < this.ids.length; i++) { - char[] matrix = this.ids[i]; - if (matrix != null) { - toReturn.ids[i] = new char[matrix.length]; - System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length); - } - } - } - return toReturn; - } -}