diff --git a/build.gradle b/build.gradle index 01c93e83..8a2c3726 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,6 @@ buildscript { dependencies { classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' classpath 'org.ajoberstar:grgit:1.7.0' -// classpath 'it.unimi.dsi:fastutil:7.0.12' } } @@ -80,9 +79,9 @@ subprojects { repositories { mavenCentral() + maven {url "http://ci.emc.gs/nexus/content/groups/aikar/" } maven {url "http://ci.regularbox.com/plugin/repository/everything/"} maven {url "http://empcraft.com/maven2"} - maven {url "http://repo.mcstats.org/content/repositories/public"} maven {url "https://hub.spigotmc.org/nexus/content/groups/public/"} maven {url "http://maven.sk89q.com/repo/"} maven {url "http://nexus.hc.to/content/repositories/pub_releases"} diff --git a/bukkit/build.gradle b/bukkit/build.gradle index b53e2f7c..c2844d0c 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -37,6 +37,7 @@ apply plugin: 'com.github.johnrengelman.shadow' shadowJar { dependencies { include(dependency('com.github.luben:zstd-jni:1.1.1')) + include(dependency('co.aikar:fastutil-lite:1.0')) include(dependency(':core')) } archiveName = "${parent.name}-${project.name}-${parent.version}.jar" diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java index 34134d66..f3248a89 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitTaskMan.java @@ -1,7 +1,6 @@ package com.boydti.fawe.bukkit; import com.boydti.fawe.util.TaskManager; -import java.util.HashMap; import org.apache.commons.lang.mutable.MutableInt; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; @@ -25,7 +24,6 @@ public class BukkitTaskMan extends TaskManager { } public MutableInt index = new MutableInt(0); - public HashMap tasks = new HashMap<>(); @Override public void async(final Runnable r) { diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java index 00f1083d..71150922 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitChunk_All.java @@ -11,10 +11,10 @@ import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.bukkit.BukkitUtil; -import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.ArrayList; import org.bukkit.Bukkit; import org.bukkit.Chunk; +import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; @@ -75,36 +75,26 @@ public class BukkitChunk_All extends CharFaweChunk { long start = System.currentTimeMillis(); int recommended = 25 + BukkitQueue_All.ALLOCATE; boolean more = true; - BukkitQueue_All parent = (BukkitQueue_All) getParent(); + final BukkitQueue_All parent = (BukkitQueue_All) getParent(); final Chunk chunk = getChunk(); Object[] disableResult = parent.disableLighting(chunk); final World world = chunk.getWorld(); char[][] sections = getCombinedIdArrays(); + final int bx = getX() << 4; + final int bz = getZ() << 4; if (layer == -1) { // Biomes if (layer == 0) { - final int[][] biomes = getBiomeArray(); + final byte[] biomes = getBiomeArray(); if (biomes != null) { final LocalWorld lw = BukkitUtil.getLocalWorld(world); - final int X = getX() << 4; - final int Z = 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); + int index = 0; + Vector2D mutable = new Vector2D(); + for (int z = 0; z < 16; z++) { + mutable.z = bx + z; + for (int x = 0; x < 16; x++) { + mutable.x = bz + x; + lw.setBiome(mutable, FaweCache.getBiome(biomes[index++] & 0xFF)); } } } @@ -142,11 +132,11 @@ public class BukkitChunk_All extends CharFaweChunk { final byte[] cacheZ = FaweCache.CACHE_Z[layer]; boolean checkTime = !((getAir(layer) == 4096 || (getCount(layer) == 4096 && getAir(layer) == 0) || (getCount(layer) == getAir(layer)))); if (!checkTime) { - ArrayList threads = new ArrayList(); + final ArrayList threads = new ArrayList(); for (int k = 0; k < 16; k++) { final int l = k << 8; final int y = cacheY[l]; - Thread thread = new Thread(new Runnable() { + final Thread thread = new Thread(new Runnable() { @Override public void run() { for (int m = l; m < l + 256; m++) { @@ -166,6 +156,13 @@ public class BukkitChunk_All extends CharFaweChunk { int x = cacheX[m]; int z = cacheZ[m]; int id = combined >> 4; + if (FaweCache.hasNBT(id) && parent.adapter != null) { + CompoundTag nbt = getTile(x, y, z); + if (nbt != null) { + parent.adapter.setBlock(new Location(world, bx + x, y, bz + z), new BaseBlock(id, combined & 0xF, nbt), false); + continue; + } + } Block block = chunk.getBlock(x, y, z); setBlock(block, id, (byte) (combined & 0xF)); } @@ -214,15 +211,14 @@ public class BukkitChunk_All extends CharFaweChunk { int x = cacheX[j]; int z = cacheZ[j]; int y = cacheY[j]; - Block block = chunk.getBlock(x, y, z); if (FaweCache.hasNBT(id) && parent.adapter != null) { CompoundTag tile = getTile(x, y, z); if (tile != null) { - BaseBlock baseBlock = new BaseBlock(id, data, tile); - parent.adapter.setBlock(block.getLocation(), baseBlock, false); + parent.adapter.setBlock(new Location(world, bx + x, y, bz + z), new BaseBlock(id, combined & 0xF, tile), false); break; } } + Block block = chunk.getBlock(x, y, z); setBlock(block, id, (byte) data); if (light) { parent.disableLighting(disableResult); 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 index 554cc656..8ea789a6 100644 --- 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 @@ -161,11 +161,6 @@ public abstract class BukkitQueue_0 extends NMSMa return getWorldName() != null ? Bukkit.getWorld(getWorldName()) : null; } - @Override - public boolean isChunkLoaded(World world, int x, int z) { - return world.isChunkLoaded(x, z); - } - @Override public void sendChunk(int x, int z, int bitMask) {} @@ -188,15 +183,6 @@ public abstract class BukkitQueue_0 extends NMSMa return getWorld().getEnvironment() == World.Environment.NORMAL; } - @Override - public boolean loadChunk(World impWorld, int x, int z, boolean generate) { - if (impWorld.loadChunk(x, z, generate)) { - keepLoaded.put(MathMan.pairInt(x, z), System.currentTimeMillis()); - return true; - } - return false; - } - private volatile boolean timingsEnabled; private static boolean alertTimingsChange = true; private static Field fieldTimingsEnabled; diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java index 678bde66..67a3f4f7 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java @@ -3,18 +3,18 @@ package com.boydti.fawe.bukkit.v0; import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.util.TaskManager; +import com.boydti.fawe.util.MathMan; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.blocks.BaseBlock; import java.lang.reflect.Field; import java.lang.reflect.Method; import org.bukkit.Chunk; +import org.bukkit.ChunkSnapshot; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.block.Block; +import org.bukkit.block.Biome; -public class BukkitQueue_All extends BukkitQueue_0 { +public class BukkitQueue_All extends BukkitQueue_0 { public static int ALLOCATE; private static int LIGHT_MASK = 0x739C0; @@ -39,87 +39,108 @@ public class BukkitQueue_All extends BukkitQueue_0 { @Override public void setHeightMap(FaweChunk chunk, byte[] heightMap) { - // Do nothing + // Not supported } @Override - public void setSkyLight(Chunk chunk, int x, int y, int z, int value) { - + public void setSkyLight(ChunkSnapshot chunk, int x, int y, int z, int value) { + // Not supported } @Override - public void setBlockLight(Chunk chunk, int x, int y, int z, int value) { -// chunk.getBlock(x & 15, y, z & 15); + public void setBlockLight(ChunkSnapshot chunk, int x, int y, int z, int value) { + // Not supported } - 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(); + @Override + public int getCombinedId4Data(ChunkSnapshot chunk, int x, int y, int z) { + if (chunk.isSectionEmpty(y >> 4)) { + return 0; + } + int id = chunk.getBlockTypeId(x & 15, y, z & 15); + if (FaweCache.hasData(id)) { + int data = chunk.getBlockData(x & 15, y, z & 15); + return (id << 4) + data; + } else { + return id << 4; } - return combined; } @Override - public int getEmmittedLight(final Chunk chunk, int x, int y, int z) { - if (!chunk.isLoaded()) { - TaskManager.IMP.sync(new RunnableVal() { - @Override - public void run(Object value) { - chunk.load(true); + public int getBiome(ChunkSnapshot chunkSnapshot, int x, int z) { + Biome biome = chunkSnapshot.getBiome(x & 15, z & 15); + return adapter.getBiomeId(biome); + } + + @Override + public ChunkSnapshot getSections(ChunkSnapshot chunkSnapshot) { + return chunkSnapshot; + } + + @Override + public ChunkSnapshot getCachedChunk(World world, int cx, int cz) { + if (world.isChunkLoaded(cx, cz)) { + long pair = MathMan.pairInt(cx, cz); + Long originalKeep = keepLoaded.get(pair); + keepLoaded.put(pair, Long.MAX_VALUE); + if (world.isChunkLoaded(cx, cz)) { + Chunk chunk = world.getChunkAt(cx, cz); + if (originalKeep != null) { + keepLoaded.put(pair, originalKeep); + } else { + keepLoaded.remove(pair); } - }); + return chunk.getChunkSnapshot(false, true, false); + + } else { + keepLoaded.remove(pair); + return null; + } + } else { + return null; } - return chunk.getBlock(x, y, z).getLightFromBlocks(); } @Override - public int getSkyLight(final Chunk chunk, int x, int y, int z) { - if (!chunk.isLoaded()) { - TaskManager.IMP.sync(new RunnableVal() { - @Override - public void run(Object value) { - chunk.load(true); - } - }); - } - return chunk.getBlock(x, y, z).getLightFromSky(); + public int getEmmittedLight(final ChunkSnapshot chunk, int x, int y, int z) { + return chunk.getBlockEmittedLight(x & 15, y, z & 15); } @Override - public int getLight(final Chunk chunk, int x, int y, int z) { - if (!chunk.isLoaded()) { - TaskManager.IMP.sync(new RunnableVal() { - @Override - public void run(Object value) { - chunk.load(true); - } - }); - } - return chunk.getBlock(x, y, z).getLightLevel(); + public int getSkyLight(final ChunkSnapshot chunk, int x, int y, int z) { + return chunk.getBlockSkyLight(x & 15, y, z & 15); } @Override - public Chunk getCachedSections(World impWorld, int cx, int cz) { - return impWorld.getChunkAt(cx, cz); + public int getLight(final ChunkSnapshot chunk, int x, int y, int z) { + x = x & 15; + z = z & 15; + return Math.max(chunk.getBlockEmittedLight(x, y, z), chunk.getBlockSkyLight(x, y, z)); } @Override - public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { + public ChunkSnapshot loadChunk(World world, int x, int z, boolean generate) { + Chunk chunk = world.getChunkAt(x, z); + chunk.load(generate); + return chunk.isLoaded() ? chunk.getChunkSnapshot(false, true, false) : null; + } + + @Override + public ChunkSnapshot getCachedSections(World impWorld, int cx, int cz) { + return getCachedChunk(impWorld, cx, cz); + } + + @Override + public CompoundTag getTileEntity(ChunkSnapshot chunk, int x, int y, int z) { if (adapter == null) { return null; } Location loc = new Location(getWorld(), x, y, z); BaseBlock block = adapter.getBlock(loc); + System.out.println("Get tile " + x + "," + y + "," + z + " | " + (block != null ? block.getNbtData() : null) + " | done"); return block != null ? block.getNbtData() : null; } - @Override - public Chunk getChunk(World world, int x, int z) { - return world.getChunkAt(x, z); - } - @Override public FaweChunk getFaweChunk(int x, int z) { return new BukkitChunk_All(this, x, z); diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java index f78eb92e..fb2237d7 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java @@ -6,8 +6,9 @@ import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.IntegerTrio; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.TaskManager; -import java.util.HashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import java.util.HashSet; +import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -46,11 +47,37 @@ public class ChunkListener implements Listener { } } + public static void main(String[] args) { + Map map = new Long2ObjectOpenHashMap() { + @Override + public Object put(long l, Object o) { + synchronized (this) { + return super.put(l, o); + } + } + + @Override + public synchronized Object put(Long aLong, Object o) { + return super.put(aLong, o); + } + }; +// map = new ConcurrentHashMap<>(); + long start = System.currentTimeMillis(); + for (int j = 0; j < 50000; j++) { + for (long i = 0; i < 256; i++) { + map.put(i, i); + } + map.clear(); + } + System.out.println(System.currentTimeMillis() - start); + System.out.println(map.size()); + } + public static boolean physicsFreeze = false; public static boolean itemFreeze = false; private HashSet badChunks = new HashSet<>(); - private HashMap counter = new HashMap<>(); + private Map counter = new Long2ObjectOpenHashMap<>(); private int lastX = Integer.MIN_VALUE, lastZ = Integer.MIN_VALUE; private IntegerTrio lastCount; diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java index c8af66d0..1694279a 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10.java @@ -396,19 +396,11 @@ public class BukkitChunk_1_10 extends CharFaweChunk { getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); } // Set biomes - int[][] biomes = this.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; + if (this.biomes != null) { + byte[] currentBiomes = nmsChunk.getBiomeIndex(); + for (int i = 0 ; i < this.biomes.length; i++) { + if (this.biomes[i] != 0) { + currentBiomes[i] = this.biomes[i]; } } } diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java index b6483b78..15724e60 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java @@ -64,7 +64,7 @@ import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; -public class BukkitQueue_1_10 extends BukkitQueue_0 { +public class BukkitQueue_1_10 extends BukkitQueue_0 { protected static IBlockData air; protected static Field fieldBits; @@ -304,13 +304,42 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); + public CompoundTag getTileEntity(net.minecraft.server.v1_10_R1.Chunk chunk, int x, int y, int z) { + Map tiles = chunk.getTileEntities(); pos.c(x, y, z); TileEntity tile = tiles.get(pos); return tile != null ? getTag(tile) : null; @@ -627,11 +650,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 map = ReflectionUtils.getMap(nativeTag.getValue()); + map.put("Id", new StringTag(id)); + setEntity(nativeTag); + return true; + } else { + return false; + } + } + @Override public CharFaweChunk copy(boolean shallow) { BukkitChunk_1_11 copy; @@ -174,6 +210,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk[] entities = (Collection[]) getParent().getEntitySlices.invoke(nmsChunk); Map tiles = nmsChunk.getTileEntities(); - // copy -// BukkitChunk_1_11 copy = getParent().getFaweChunk(getX(), getZ()); // TODO // Set heightmap getParent().setHeightMap(this, heightMap); // Remove entities @@ -198,6 +233,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk ents = new ArrayList<>(entities[i]); for (Entity entity : ents) { if (entsToRemove.contains(entity.getUniqueID())) { + if (copy != null) { + copy.storeEntity(entity); + } nmsWorld.removeEntity(entity); } } @@ -211,7 +249,11 @@ public class BukkitChunk_1_11 extends CharFaweChunk= 4096) { Collection ents = entities[i]; if (!ents.isEmpty()) { -// copy.storeEntities(this, i); + if (copy != null) { + for (Entity entity : ents) { + copy.storeEntity(entity); + } + } synchronized (BukkitQueue_0.adapter) { ents.clear(); } @@ -220,8 +262,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk ents = entities[i]; if (!ents.isEmpty()) { char[] array = this.getIdArray(i); - if (array == null || entities[i] == null || entities[i].isEmpty()) continue; - ents = new ArrayList<>(entities[i]); + if (array == null || ents == null || ents.isEmpty()) continue; synchronized (BukkitQueue_0.adapter) { for (Entity entity : ents) { if (entity instanceof EntityPlayer) { @@ -232,7 +273,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk 255) continue; if (array[FaweCache.CACHE_J[y][z][x]] != 0) { -// copy.storeEntity(this, entity); + if (copy != null) { + copy.storeEntity(entity); + } nmsWorld.removeEntity(entity); } } @@ -291,11 +334,6 @@ public class BukkitChunk_1_11 extends CharFaweChunk> iterator = tiles.entrySet().iterator(); HashMap toRemove = null; @@ -315,11 +353,13 @@ public class BukkitChunk_1_11 extends CharFaweChunk(); } + if (copy != null) { + storeTile(tile.getValue(), tile.getKey()); + } toRemove.put(tile.getKey(), tile.getValue()); } } if (toRemove != null) { -// copy.storeTiles(this, toRemove); for (Map.Entry entry : toRemove.entrySet()) { BlockPosition bp = entry.getKey(); TileEntity tile = entry.getValue(); @@ -342,7 +382,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk { +public class BukkitQueue_1_11 extends BukkitQueue_0 { protected static IBlockData air; protected static Field fieldBits; @@ -150,6 +150,41 @@ public class BukkitQueue_1_11 extends BukkitQueue_0 tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); + public CompoundTag getTileEntity(net.minecraft.server.v1_11_R1.Chunk chunk, int x, int y, int z) { + Map tiles = chunk.getTileEntities(); pos.c(x, y, z); TileEntity tile = tiles.get(pos); return tile != null ? getTag(tile) : null; @@ -618,11 +648,6 @@ public class BukkitQueue_1_11 extends BukkitQueue_0 { } // Set biomes - int[][] biomes = this.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.m()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; // Biome array + if (this.biomes != null) { + byte[] currentBiomes = nmsChunk.m(); + for (int i = 0 ; i < this.biomes.length; i++) { + if (this.biomes[i] != 0) { + currentBiomes[i] = this.biomes[i]; } } } diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java index 9412193b..8892e457 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_7/BukkitQueue17.java @@ -48,7 +48,6 @@ import net.minecraft.server.v1_7_R4.WorldServer; import net.minecraft.server.v1_7_R4.WorldSettings; import net.minecraft.server.v1_7_R4.WorldType; import org.bukkit.Bukkit; -import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.WorldCreator; import org.bukkit.block.Biome; @@ -59,7 +58,7 @@ import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; -public class BukkitQueue17 extends BukkitQueue_0 { +public class BukkitQueue17 extends BukkitQueue_0 { protected static Field fieldData; protected static Field fieldIds; @@ -175,18 +174,48 @@ public class BukkitQueue17 extends BukkitQueue_0 tilesGeneric, Collection[] entitiesGeneric, Set createdEntities, boolean all) throws Exception { Map tiles = (Map) tilesGeneric; @@ -307,19 +314,14 @@ public class BukkitQueue17 extends BukkitQueue_0 tiles = ((CraftChunk) chunk).getHandle().tileEntities; + public CompoundTag getTileEntity(net.minecraft.server.v1_7_R4.Chunk chunk, int x, int y, int z) { + Map tiles = chunk.tileEntities; ChunkPosition pos = new ChunkPosition(x, y, z); TileEntity tile = tiles.get(pos); return tile != null ? getTag(tile) : null; } - @Override - public Chunk getChunk(World world, int x, int z) { - return world.getChunkAt(x, z); - } - public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { fieldTickingBlockCount.set(section, tickingBlockCount); fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); @@ -331,28 +333,22 @@ public class BukkitQueue17 extends BukkitQueue_0 { } // Set biomes - int[][] biomes = this.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; + if (this.biomes != null) { + byte[] currentBiomes = nmsChunk.getBiomeIndex(); + for (int i = 0 ; i < this.biomes.length; i++) { + if (this.biomes[i] != 0) { + currentBiomes[i] = this.biomes[i]; } } } diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java index e881a679..fcb8e4e6 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java @@ -47,7 +47,6 @@ import net.minecraft.server.v1_8_R3.WorldServer; import net.minecraft.server.v1_8_R3.WorldSettings; import net.minecraft.server.v1_8_R3.WorldType; import org.bukkit.Bukkit; -import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.WorldCreator; import org.bukkit.block.Biome; @@ -58,7 +57,7 @@ import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; -public class BukkitQueue18R3 extends BukkitQueue_0 { +public class BukkitQueue18R3 extends BukkitQueue_0 { public static Field isDirty; @@ -180,17 +179,43 @@ public class BukkitQueue18R3 extends BukkitQueue_0 tilesGeneric, Collection[] entitiesGeneric, Set createdEntities, boolean all) throws Exception { Map tiles = (Map) tilesGeneric; @@ -309,19 +312,14 @@ public class BukkitQueue18R3 extends BukkitQueue_0 tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); + public CompoundTag getTileEntity(net.minecraft.server.v1_8_R3.Chunk chunk, int x, int y, int z) { + Map tiles = chunk.getTileEntities(); pos.c(x, y, z); TileEntity tile = tiles.get(pos); return tile != null ? getTag(tile) : null; } - @Override - public Chunk getChunk(World world, int x, int z) { - return world.getChunkAt(x, z); - } - public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { fieldTickingBlockCount.set(section, tickingBlockCount); fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); @@ -333,28 +331,22 @@ public class BukkitQueue18R3 extends BukkitQueue_0 { getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); } // Set biomes - int[][] biomes = this.biomes; + byte[] biomes = this.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; + byte[] currentBiomes = nmsChunk.getBiomeIndex(); + for (int i = 0; i < currentBiomes.length; i++) { + byte newBiome = biomes[i]; + if (newBiome != 0) { + currentBiomes[i] = newBiome; } } } @@ -437,23 +430,6 @@ public class BukkitChunk_1_9 extends CharFaweChunk { } catch (Throwable e) { MainUtil.handleError(e); } - final int[][] biomes = this.getBiomeArray(); - 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]); - } - } - } return this; } -} +} \ No newline at end of file diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java index 3a585895..bdc7f1b4 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java @@ -62,7 +62,7 @@ import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.generator.ChunkGenerator; -public class BukkitQueue_1_9_R1 extends BukkitQueue_0 { +public class BukkitQueue_1_9_R1 extends BukkitQueue_0 { protected static IBlockData air; protected static Field fieldBits; @@ -191,13 +191,42 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0 tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); + public CompoundTag getTileEntity(net.minecraft.server.v1_9_R2.Chunk chunk, int x, int y, int z) { + Map tiles = chunk.getTileEntities(); pos.c(x, y, z); TileEntity tile = tiles.get(pos); return tile != null ? getTag(tile) : null; @@ -578,11 +601,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0 block @@ -129,7 +135,19 @@ public class FaweCache { return CACHE_COLOR[0]; } + public static final BaseBiome getBiome(int id) { + return CACHE_BIOME[id]; + } + static { + for (int i = 0; i < 256; i++) { + CACHE_BIOME[i] = new BaseBiome(i) { + @Override + public void setId(int id) { + throw new IllegalStateException("Cannot set id"); + } + }; + } for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { for (int y = 0; y < 256; y++) { diff --git a/core/src/main/java/com/boydti/fawe/config/BBC.java b/core/src/main/java/com/boydti/fawe/config/BBC.java index 94e8f5f5..b0577213 100644 --- a/core/src/main/java/com/boydti/fawe/config/BBC.java +++ b/core/src/main/java/com/boydti/fawe/config/BBC.java @@ -76,9 +76,11 @@ public enum BBC { COMMAND_REGEN_1("Region regenerated.\nTip: Use a seed with /regen [biome] [seed]", "WorldEdit.Regen"), COMMAND_REGEN_2("Region regenerated.", "WorldEdit.Regen"), COMMAND_TREE("%s0 trees created.", "WorldEdit.Tree"), + COMMAND_PUMPKIN("%s0 pumpkin patches created.", "WorldEdit.Tree"), COMMAND_FLORA("%s0 flora created.", "WorldEdit.Flora"), COMMAND_HISTORY_CLEAR("History cleared", "WorldEdit.History"), COMMAND_REDO_ERROR("Nothing left to redo. (See also `/inspect` and `/frb`)", "WorldEdit.History"), + COMMAND_HISTORY_OTHER_ERROR("Unable to find session for %s0.", "WorldEdit.History"), COMMAND_REDO_SUCCESS("Redo successful.", "WorldEdit.History"), COMMAND_UNDO_ERROR("Nothing left to undo. (See also `/inspect` and `/frb`)", "WorldEdit.History"), COMMAND_UNDO_SUCCESS("Undo successful.", "WorldEdit.History"), @@ -133,6 +135,7 @@ public enum BBC { BRUSH_TRANSFORM("Brush transform set", "WorldEdit.Brush"), BRUSH_MATERIAL("Brush material set", "WorldEdit.Brush"), + ROLLBACK_ELEMENT("Undoing %s0", "WorldEdit.Rollback"), TOOL_INSPECT("Inspect tool bound to %s0.", "WorldEdit.Tool"), @@ -145,13 +148,32 @@ public enum BBC { TOOL_REPL("Block replacer tool bound to %s0.", "WorldEdit.Tool"), TOOL_CYCLER("Block data cycler tool bound to %s0.", "WorldEdit.Tool"), TOOL_FLOOD_FILL("Block flood fill tool bound to %s0.", "WorldEdit.Tool"), - TOOL_FLOOD_FILL_RANGE_ERROR("Maximum range: %s0.", "WorldEdit.Tool"), + TOOL_RANGE_ERROR("Maximum range: %s0.", "WorldEdit.Tool"), + TOOL_RADIUS_ERROR("Maximum allowed brush radius: %s0.", "WorldEdit.Tool"), TOOL_DELTREE("Floating tree remover tool bound to %s0.", "WorldEdit.Tool"), TOOL_FARWAND("Far wand tool bound to %s0.", "WorldEdit.Tool"), TOOL_LRBUILD_BOUND("Long-range building tool bound to %s0.", "WorldEdit.Tool"), TOOL_LRBUILD_INFO("Left-click set to %s0; right-click set to %s1.", "WorldEdit.Tool"), SUPERPICKAXE_ENABLED("Super Pickaxe enabled.", "WorldEdit.Tool"), SUPERPICKAXE_DISABLED("Super Pickaxe disabled.", "WorldEdit.Tool"), + SUPERPICKAXE_AREA_ENABLED("Mode changed. Left click with a pickaxe. // to disable.", "WorldEdit.Tool"), + + SNAPSHOT_LOADED("Snapshot '%s0' loaded; now restoring...", "WorldEdit.Snapshot"), + SNAPSHOT_SET("Snapshot set to: %s0", "WorldEdit.Snapshot"), + SNAPSHOT_NEWEST("Now using newest snapshot.", "WorldEdit.Snapshot"), + SNAPSHOT_LIST_HEADER("Snapshots for world (%s0):", "WorldEdit.Snapshot"), + SNAPSHOT_LIST_FOOTER("Use /snap use [snapshot] or /snap use latest.", "WorldEdit.Snapshot"), + + BIOME_LIST_HEADER("Biomes (page %s0/%s1):", "WorldEdit.Biome"), + BIOME_CHANGED("Biomes were changed in %s0 columns.", "WorldEdit.Biome"), + + FAST_ENABLED("Fast mode enabled. History and edit restrictions will be bypassed.", "WorldEdit.General"), + FAST_DISABLED("Fast mode disabled", "WorldEdit.General"), + + PLACE_ENABLED("Now placing at pos #1.", "WorldEdit.General"), + PLACE_DISABLED("Now placing at the block you stand in.", "WorldEdit.General"), + + KILL_SUCCESS("Killed %s0 entities in a radius of %s1.", "WorldEdit.Utility"), SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"), @@ -163,6 +185,7 @@ public enum BBC { SCHEMATIC_LIST("Available schematics (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"), CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"), + CLIPBOARD_INVALID_FORMAT("Unknown clipboard format: %s0", "WorldEdit.Clipboard"), VISITOR_BLOCK("%s0 blocks affected", "WorldEdit.Visitor"), VISITOR_ENTITY("%s0 entities affected", "WorldEdit.Visitor"), @@ -174,6 +197,10 @@ public enum BBC { SELECTOR_CUBOID_POS2("pos2 set to %s0 %s1.", "WorldEdit.Selector"), SELECTOR_INVALID_COORDINATES("Invalid coordinates %s0", "WorldEdit.Selector"), SELECTOR_ALREADY_SET("Position already set.", "WorldEdit.Selector"), + SELECTOR_SET_DEFAULT("Your default region selector is now %s0.", "WorldEdit.Selector"), + + TIMEZONE_SET("Timezone set for this session to: %s0", "WorldEdit.Timezone"), + TIMEZONE_DISPLAY("The current time in that timezone is: %s0", "WorldEdit.Timezone"), COMMAND_INVALID_SYNTAX("The command was not used properly (no more help available).", "WorldEdit.Command"), @@ -222,7 +249,7 @@ public enum BBC { WHOOSH("Whoosh!", "Navigation"), POOF("Poof!", "Navigation"), THRU_FAIL("No free spot ahead of you found.", "Navigation"), - JUMPTO_FAIL("No block in sight!", "Navigation"), + NO_BLOCK("No block in sight! (or too far)", "Navigation"), UP_FAIL("You would hit something above you.", "Navigation"), SEL_CUBOID("Cuboid: left click for point 1, right click for point 2", "Selection"), diff --git a/core/src/main/java/com/boydti/fawe/config/Config.java b/core/src/main/java/com/boydti/fawe/config/Config.java index d3191ae6..1354cf39 100644 --- a/core/src/main/java/com/boydti/fawe/config/Config.java +++ b/core/src/main/java/com/boydti/fawe/config/Config.java @@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.configuration.MemorySection; import com.boydti.fawe.configuration.file.YamlConfiguration; import com.boydti.fawe.util.StringMan; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintWriter; import java.lang.annotation.ElementType; @@ -22,6 +23,10 @@ import java.util.Map; public class Config { + public Config() { + save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0); + } + /** * Get the value for a node
* Probably throws some error if you try to get a non existent key @@ -220,7 +225,7 @@ public class Config { return value != null ? value.toString() : "null"; } - private void save(PrintWriter writer, Class clazz, Object instance, int indent) { + private void save(PrintWriter writer, Class clazz, final Object instance, int indent) { try { String CTRF = System.lineSeparator(); String spacing = StringMan.repeat(" ", indent); 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 69ed72f4..d10d30ea 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -18,13 +18,13 @@ public class Settings extends Config { @Final public final String WIKI = "https://github.com/boy0001/FastAsyncWorldedit/wiki/"; @Final - public String DATE = null; // These values are set from FAWE before loading + public String DATE; // These values are set from FAWE before loading @Final - public String BUILD = null; // These values are set from FAWE before loading + public String BUILD; // These values are set from FAWE before loading @Final - public String COMMIT = null; // These values are set from FAWE before loading + public String COMMIT; // These values are set from FAWE before loading @Final - public String PLATFORM = null; // These values are set from FAWE before loading + public String PLATFORM; // These values are set from FAWE before loading @Comment("Allow the plugin to update") public boolean UPDATE = true; @@ -46,23 +46,23 @@ public class Settings extends Config { public int MAX_MEMORY_PERCENT = 95; @Create - public CLIPBOARD CLIPBOARD = null; + public CLIPBOARD CLIPBOARD; @Create - public LIGHTING LIGHTING = null; + public LIGHTING LIGHTING; @Create - public TICK_LIMITER TICK_LIMITER = null; + public TICK_LIMITER TICK_LIMITER; @Create - public WEB WEB = null; + public WEB WEB; @Create - public EXTENT EXTENT = null; + public EXTENT EXTENT; @Create - public EXPERIMENTAL EXPERIMENTAL = null; + public EXPERIMENTAL EXPERIMENTAL; @Create - public QUEUE QUEUE = null; + public QUEUE QUEUE; @Create - public HISTORY HISTORY = null; + public HISTORY HISTORY; @Create - public PATHS PATHS = null; + public PATHS PATHS; @Comment("Paths for various directories") public static final class PATHS { @@ -72,7 +72,7 @@ public class Settings extends Config { @Create // This value will be generated automatically - public ConfigBlock LIMITS = null; + public ConfigBlock LIMITS; @Comment({ "The \"default\" limit group affects those without a specific limit permission.", @@ -208,7 +208,7 @@ public class Settings extends Config { public static class QUEUE { @Create - public static PROGRESS PROGRESS = null; + public static PROGRESS PROGRESS; @Comment({ "If no blocks from completed edits are queued, and if the global queue has more available ", "chunks to place from still-processing edits than the target size setting, it will begin", diff --git a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java index 7437c2a9..27cad6f1 100644 --- a/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/example/CharFaweChunk.java @@ -5,7 +5,6 @@ import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.util.MathMan; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -19,7 +18,7 @@ public abstract class CharFaweChunk extends FaweChunk public final short[] air; public final byte[] heightMap; - public int[][] biomes; + public byte[] biomes; public HashMap tiles; public HashSet entities; public HashSet entityRemoves; @@ -121,7 +120,8 @@ public abstract class CharFaweChunk extends FaweChunk return this.ids; } - public int[][] getBiomeArray() { + @Override + public byte[] getBiomeArray() { return this.biomes; } @@ -342,15 +342,11 @@ public abstract class CharFaweChunk extends FaweChunk } @Override - public void setBiome(final int x, final int z, final BaseBiome biome) { + public void setBiome(final int x, final int z, final byte biome) { if (this.biomes == null) { - this.biomes = new int[16][]; + this.biomes = new byte[256]; } - int[] index = this.biomes[x]; - if (index == null) { - index = this.biomes[x] = new int[16]; - } - index[z] = biome.getId(); + biomes[((z & 15) << 4) + (x & 15)] = biome; } @Override diff --git a/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java b/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java index c3086e81..d27024f3 100644 --- a/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java +++ b/core/src/main/java/com/boydti/fawe/example/DefaultFaweQueueMap.java @@ -5,11 +5,11 @@ import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.SetQueue; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorCompletionService; public class DefaultFaweQueueMap implements IFaweQueueMap { @@ -20,12 +20,14 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { this.parent = parent; } - /** - * Map of chunks in the queue - */ - public final ConcurrentHashMap blocks = new ConcurrentHashMap(8, 0.9f, 1) { + public final Long2ObjectOpenHashMap blocks = new Long2ObjectOpenHashMap() { @Override public FaweChunk put(Long key, FaweChunk value) { + return put((long) key, value); + } + + @Override + public FaweChunk put(long key, FaweChunk value) { if (parent.getProgressTask() != null) { try { parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1); @@ -33,7 +35,9 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { e.printStackTrace(); } } - return super.put(key, value); + synchronized (this) { + return super.put(key, value); + } } }; @@ -109,67 +113,69 @@ public class DefaultFaweQueueMap implements IFaweQueueMap { @Override public boolean next(int amount, ExecutorCompletionService pool, long time) { - try { - boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; - int added = 0; - Iterator> iter = blocks.entrySet().iterator(); - if (amount == 1) { - long start = System.currentTimeMillis(); - do { - if (iter.hasNext()) { - FaweChunk chunk = iter.next().getValue(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - parent.start(chunk); - chunk.call(); - parent.end(chunk); - } else { - break; - } - } while (System.currentTimeMillis() - start < time); - } else { - boolean result = true; - // amount = 8; - for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) { - Map.Entry item = iter.next(); - FaweChunk chunk = item.getValue(); - if (skip && chunk == lastWrappedChunk) { - i--; - added--; - continue; - } - iter.remove(); - parent.start(chunk); - pool.submit(chunk); - } - // if result, then submitted = amount - if (result) { + synchronized (blocks) { + try { + boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; + int added = 0; + Iterator> iter = blocks.entrySet().iterator(); + if (amount == 1) { long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < time && result) { - if (result = iter.hasNext()) { - Map.Entry item = iter.next(); - FaweChunk chunk = item.getValue(); + do { + if (iter.hasNext()) { + FaweChunk chunk = iter.next().getValue(); if (skip && chunk == lastWrappedChunk) { continue; } iter.remove(); parent.start(chunk); - pool.submit(chunk); - FaweChunk fc = ((FaweChunk) pool.take().get()); - parent.end(fc); + chunk.call(); + parent.end(chunk); + } else { + break; + } + } while (System.currentTimeMillis() - start < time); + } else { + boolean result = true; + // amount = 8; + for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) { + Map.Entry item = iter.next(); + FaweChunk chunk = item.getValue(); + if (skip && chunk == lastWrappedChunk) { + i--; + added--; + continue; + } + iter.remove(); + parent.start(chunk); + pool.submit(chunk); + } + // if result, then submitted = amount + if (result) { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < time && result) { + if (result = iter.hasNext()) { + Map.Entry item = iter.next(); + FaweChunk chunk = item.getValue(); + if (skip && chunk == lastWrappedChunk) { + continue; + } + iter.remove(); + parent.start(chunk); + pool.submit(chunk); + FaweChunk fc = ((FaweChunk) pool.take().get()); + parent.end(fc); + } } } + for (int i = 0; i < added; i++) { + FaweChunk fc = ((FaweChunk) pool.take().get()); + parent.end(fc); + } } - for (int i = 0; i < added; i++) { - FaweChunk fc = ((FaweChunk) pool.take().get()); - parent.end(fc); - } + } catch (Throwable e) { + e.printStackTrace(); } - } catch (Throwable e) { - e.printStackTrace(); + return !blocks.isEmpty(); } - return !blocks.isEmpty(); } } diff --git a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java index 81d88ee3..d2064683 100644 --- a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java @@ -21,17 +21,36 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.UUID; -import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; -public abstract class MappedFaweQueue extends FaweQueue { +public abstract class MappedFaweQueue extends FaweQueue { private WORLD impWorld; private IFaweQueueMap map; + public int lastSectionX = Integer.MIN_VALUE; + public int lastSectionZ = Integer.MIN_VALUE; + public int lastSectionY = Integer.MIN_VALUE; + public CHUNK lastChunk; + public CHUNKSECTIONS lastChunkSections; + public SECTION lastSection; + + private CHUNK cachedLoadChunk; + public final RunnableVal loadChunk = new RunnableVal() { + + { + this.value = new IntegerPair(0, 0); + } + + @Override + public void run(IntegerPair coord) { + cachedLoadChunk = loadChunk(getWorld(), coord.x, coord.z, true); + } + }; + public MappedFaweQueue(final World world) { this(world, null); } @@ -102,21 +121,18 @@ public abstract class MappedFaweQueue extends FaweQueue { public abstract WORLD getImpWorld(); - public abstract boolean isChunkLoaded(WORLD world, int x, int z); - public abstract boolean regenerateChunk(WORLD world, int x, int z, BaseBiome biome, Long seed); @Override public abstract FaweChunk getFaweChunk(int x, int z); - public abstract boolean loadChunk(WORLD world, int x, int z, boolean generate); + public abstract CHUNK loadChunk(WORLD world, int x, int z, boolean generate); - public abstract CHUNK getCachedSections(WORLD world, int cx, int cz); + public abstract CHUNKSECTIONS getSections(CHUNK chunk); - @Override - public boolean isChunkLoaded(int x, int z) { - return isChunkLoaded(getWorld(), x, z); - }; + public abstract CHUNKSECTIONS getCachedSections(WORLD world, int cx, int cz); + + public abstract CHUNK getCachedChunk(WORLD world, int cx, int cz); public WORLD getWorld() { if (impWorld != null) { @@ -233,16 +249,12 @@ public abstract class MappedFaweQueue extends FaweQueue { @Override public int size() { int size = map.size(); - if (size == 0 && getStage() != SetQueue.QueueStage.INACTIVE) { + if (size == 0 && getStage() == SetQueue.QueueStage.NONE) { runTasks(); } return size; } - private ConcurrentLinkedDeque toUpdate = new ConcurrentLinkedDeque<>(); - - private int dispatched = 0; - @Override public void clear() { map.clear(); @@ -254,44 +266,53 @@ public abstract class MappedFaweQueue extends FaweQueue { map.add(chunk); } - public int lastChunkX = Integer.MIN_VALUE; - public int lastChunkZ = Integer.MIN_VALUE; - public int lastChunkY = Integer.MIN_VALUE; - - public CHUNK lastChunkSections; - public SECTION lastSection; - - public SECTION getCachedSection(CHUNK chunk, int cy) { + public SECTION getCachedSection(CHUNKSECTIONS chunk, int cy) { return (SECTION) lastChunkSections; } public abstract int getCombinedId4Data(SECTION section, int x, int y, int z); - public final RunnableVal loadChunk = new RunnableVal() { - @Override - public void run(IntegerPair coord) { - loadChunk(getWorld(), coord.x, coord.z, true); - } - }; + public abstract int getBiome(CHUNK chunk, int x, int z); - long average = 0; + public abstract CompoundTag getTileEntity(CHUNK chunk, int x, int y, int z); - public boolean ensureChunkLoaded(int cx, int cz) throws FaweException.FaweChunkLoadException { - if (!isChunkLoaded(cx, cz)) { - boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); - if (sync) { - loadChunk(getWorld(), cx, cz, true); - } else if (Settings.IMP.HISTORY.CHUNK_WAIT_MS > 0) { - loadChunk.value = new IntegerPair(cx, cz); - TaskManager.IMP.syncWhenFree(loadChunk, Settings.IMP.HISTORY.CHUNK_WAIT_MS); - if (!isChunkLoaded(cx, cz)) { - throw new FaweException.FaweChunkLoadException(); - } - } else { - return false; - } +// public CHUNKSECTIONS ensureSectionsLoaded(int cx, int cz) throws FaweException.FaweChunkLoadException { +// CHUNKSECTIONS sections = getCachedSections(getWorld(), cx, cz); +// if (sections != null) { +// return sections; +// } +// boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); +// if (sync) { +// CHUNK chunk = loadChunk(getWorld(), cx, cz, true); +// return chunk != null ? getSections(chunk) : null; +// } else if (Settings.IMP.HISTORY.CHUNK_WAIT_MS > 0) { +// cachedLoadChunk = null; +// loadChunk.value.x = cx; +// loadChunk.value.z = cz; +// TaskManager.IMP.syncWhenFree(loadChunk, Settings.IMP.HISTORY.CHUNK_WAIT_MS); +// return cachedLoadChunk != null ? getSections(cachedLoadChunk) : null; +// } else { +// return null; +// } +// } + + public CHUNK ensureChunkLoaded(int cx, int cz) throws FaweException.FaweChunkLoadException { + CHUNK chunk = getCachedChunk(getWorld(), cx, cz); + if (chunk != null) { + return chunk; + } + boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); + if (sync) { + return loadChunk(getWorld(), cx, cz, true); + } else if (Settings.IMP.HISTORY.CHUNK_WAIT_MS > 0) { + cachedLoadChunk = null; + loadChunk.value.x = cx; + loadChunk.value.z = cz; + TaskManager.IMP.syncWhenFree(loadChunk, Settings.IMP.HISTORY.CHUNK_WAIT_MS); + return cachedLoadChunk; + } else { + return null; } - return true; } @Override @@ -299,21 +320,24 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return false; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return false; } - lastSection = getCachedSection(lastChunkSections, cy); } - if (lastSection == null) { return false; } @@ -368,21 +392,24 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return 0; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return 0; } - lastSection = getCachedSection(lastChunkSections, cy); } - if (lastSection == null) { return 0; } @@ -394,24 +421,38 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (y >= FaweChunk.HEIGHT) { - return 15; - } - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return 0; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { - return getSkyLight(x, y + 16, z); + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { + return 0; } - lastSection = getCachedSection(lastChunkSections, cy); } if (lastSection == null) { + if (lastChunkSections == null) { + return 0; + } + int max = FaweChunk.HEIGHT >> 4; + do { + if (++cy >= max) { + return 15; + } + lastSection = getCachedSection(lastChunkSections, cy); + } while (lastSection == null); + } + if (lastSection == null) { + return getSkyLight(x, y + 16, z); } return getSkyLight(lastSection, x, y, z); @@ -422,19 +463,23 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return 0; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return 0; } - lastSection = getCachedSection(lastChunkSections, cy); } if (lastSection == null) { return 0; @@ -447,21 +492,24 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return 0; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return 0; } - lastSection = getCachedSection(lastChunkSections, cy); } - if (lastSection == null) { return 0; } @@ -473,21 +521,24 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return 0; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return 0; } - lastSection = getCachedSection(lastChunkSections, cy); } - if (lastSection == null) { return 0; } @@ -499,21 +550,24 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return 0; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return 0; } - lastSection = getCachedSection(lastChunkSections, cy); } - if (lastSection == null) { return 0; } @@ -537,24 +591,69 @@ public abstract class MappedFaweQueue extends FaweQueue { int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return 0; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return 0; } - lastSection = getCachedSection(lastChunkSections, cy); } - if (lastSection == null) { return 0; } return getCombinedId4Data(lastSection, x, y, z); } + + @Override + public int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException { + int cx = x >> 4; + int cz = z >> 4; + lastSectionY = -1; + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + } else { + lastChunkSections = null; + return 0; + } + } else if (lastChunk == null) { + return 0; + } + return getBiome(lastChunk, x, z); + } + + @Override + public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException { + int cx = x >> 4; + int cz = z >> 4; + lastSectionY = -1; + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + } else { + lastChunkSections = null; + return null; + } + } else if (lastChunk == null) { + return null; + } + return getTileEntity(lastChunk, 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 index 90837a73..5365067c 100644 --- a/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java @@ -3,17 +3,15 @@ package com.boydti.fawe.example; import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweChunk; -import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.TaskManager; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.world.World; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.UUID; -public abstract class NMSMappedFaweQueue extends MappedFaweQueue { +public abstract class NMSMappedFaweQueue extends MappedFaweQueue { private final int maxY; @@ -60,10 +58,13 @@ public abstract class NMSMappedFaweQueue ex @Override public void end(FaweChunk chunk) { super.end(chunk); - if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) { + if (Settings.IMP.LIGHTING.MODE == 0) { sendChunk(chunk); return; } + if (!Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) { + sendChunk(chunk); + } if (Settings.IMP.LIGHTING.MODE == 2) { relighter.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask()); return; @@ -90,7 +91,7 @@ public abstract class NMSMappedFaweQueue ex } if (relight) { relighter.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask()); - } else { + } else if (Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) { sendChunk(chunk); } } @@ -148,19 +149,23 @@ public abstract class NMSMappedFaweQueue ex int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return; } - lastSection = getCachedSection(lastChunkSections, cy); } if (lastSection == null) { return; @@ -172,19 +177,23 @@ public abstract class NMSMappedFaweQueue ex int cx = x >> 4; int cz = z >> 4; int cy = y >> 4; - if (cx != lastChunkX || cz != lastChunkZ) { - lastChunkX = cx; - lastChunkZ = cz; - if (!ensureChunkLoaded(cx, cz)) { + if (cx != lastSectionX || cz != lastSectionZ) { + lastSectionX = cx; + lastSectionZ = cz; + lastChunk = ensureChunkLoaded(cx, cz); + if (lastChunk != null) { + lastChunkSections = getSections(lastChunk); + lastSection = getCachedSection(lastChunkSections, cy); + } else { + lastChunkSections = null; return; } - lastChunkSections = getCachedSections(getWorld(), cx, cz); - lastSection = getCachedSection(lastChunkSections, cy); - } else if (cy != lastChunkY) { - if (lastChunkSections == null) { + } else if (cy != lastSectionY) { + if (lastChunkSections != null) { + lastSection = getCachedSection(lastChunkSections, cy); + } else { return; } - lastSection = getCachedSection(lastChunkSections, cy); } if (lastSection == null) { return; @@ -199,24 +208,4 @@ public abstract class NMSMappedFaweQueue ex public abstract void refreshChunk(FaweChunk fs); public abstract CharFaweChunk getPrevious(CharFaweChunk fs, CHUNKSECTION sections, Map tiles, Collection[] entities, Set createdEntities, boolean all) throws Exception; - - public abstract CompoundTag getTileEntity(CHUNK chunk, int x, int y, int z); - - public abstract CHUNK getChunk(WORLD world, int x, int z); - - private CHUNK lastChunk; - - @Override - public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException { - if (y < 0 || y > maxY) { - return null; - } - int cx = x >> 4; - int cz = z >> 4; - lastChunk = getChunk(getWorld(), cx, cz); - if (lastChunk == null) { - return null; - } - return getTileEntity(lastChunk, x, y, z); - } } diff --git a/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java b/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java index d8772722..94ed4590 100644 --- a/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java +++ b/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java @@ -5,6 +5,8 @@ import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.IntegerTrio; import com.boydti.fawe.util.MathMan; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -14,15 +16,14 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Queue; -import java.util.concurrent.ConcurrentHashMap; public class NMSRelighter implements Relighter{ private final NMSMappedFaweQueue queue; private final Map skyToRelight; - private final Map> lightQueue; + private final Map> lightQueue; private final Object present = new Object(); - private final HashMap chunksToSend; + private final Map chunksToSend; private final int maxY; private volatile boolean relighting = false; @@ -33,9 +34,9 @@ public class NMSRelighter implements Relighter{ public NMSRelighter(NMSMappedFaweQueue queue) { this.queue = queue; - this.skyToRelight = new ConcurrentHashMap<>(); - this.lightQueue = new ConcurrentHashMap<>(); - chunksToSend = new HashMap<>(); + this.skyToRelight = new Long2ObjectOpenHashMap<>(); + this.lightQueue = new Long2ObjectOpenHashMap<>(); + this.chunksToSend = new Long2ObjectOpenHashMap<>(); this.maxY = queue.getMaxY(); } @@ -63,7 +64,6 @@ public class NMSRelighter implements Relighter{ Iterator> iter = skyToRelight.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); - iter.remove(); RelightSkyEntry chunk = entry.getValue(); long pair = entry.getKey(); Integer existing = chunksToSend.get(pair); @@ -71,10 +71,11 @@ public class NMSRelighter implements Relighter{ queue.ensureChunkLoaded(chunk.x, chunk.z); Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z); queue.removeLighting(sections, FaweQueue.RelightMode.ALL, queue.hasSky()); + iter.remove(); } } - public void updateBlockLight(Map> map) { + public void updateBlockLight(Map> map) { int size = map.size(); if (size == 0) { return; @@ -84,17 +85,16 @@ public class NMSRelighter implements Relighter{ Map visited = new HashMap<>(); Map removalVisited = new HashMap<>(); - Iterator>> iter = map.entrySet().iterator(); + Iterator>> iter = map.entrySet().iterator(); while (iter.hasNext() && size-- > 0) { - Map.Entry> entry = iter.next(); - iter.remove(); + Map.Entry> entry = iter.next(); long index = entry.getKey(); - Map blocks = entry.getValue(); + Map blocks = entry.getValue(); int chunkX = MathMan.unpairIntX(index); int chunkZ = MathMan.unpairIntY(index); int bx = chunkX << 4; int bz = chunkZ << 4; - for (short blockHash : blocks.keySet()) { + for (int blockHash : blocks.keySet()) { int x = (blockHash >> 12 & 0xF) + bx; int y = (blockHash & 0xFF); int z = (blockHash >> 8 & 0xF) + bz; @@ -114,6 +114,7 @@ public class NMSRelighter implements Relighter{ } } } + iter.remove(); } while (!lightRemovalQueue.isEmpty()) { @@ -192,12 +193,12 @@ public class NMSRelighter implements Relighter{ public void addLightUpdate(int x, int y, int z) { long index = MathMan.pairInt((int) x >> 4, (int) z >> 4); - Map currentMap = lightQueue.get(index); + Map currentMap = lightQueue.get(index); if (currentMap == null) { - currentMap = new ConcurrentHashMap<>(8, 0.9f, 1); + currentMap = new Int2ObjectOpenHashMap<>(); this.lightQueue.put(index, currentMap); } - currentMap.put(MathMan.tripleBlockCoord(x, y, z), present); + currentMap.put((int) MathMan.tripleBlockCoord(x, y, z), present); } public synchronized void fixLightingSafe(boolean sky) { @@ -222,10 +223,10 @@ public class NMSRelighter implements Relighter{ Map.Entry entry = iter.next(); long pair = entry.getKey(); int bitMask = entry.getValue(); - iter.remove(); int x = MathMan.unpairIntX(pair); int z = MathMan.unpairIntY(pair); queue.sendChunk(x, z, bitMask); + iter.remove(); } } @@ -239,9 +240,9 @@ public class NMSRelighter implements Relighter{ Iterator> iter = skyToRelight.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); - iter.remove(); chunksToSend.put(entry.getKey(), entry.getValue().bitmask); chunksList.add(entry.getValue()); + iter.remove(); } Collections.sort(chunksList); int size = chunksList.size(); @@ -312,7 +313,6 @@ public class NMSRelighter implements Relighter{ int brightness = MathMan.unpair16y(pair); if (brightness > 1 && (brightness != 15 || opacity != 15)) { addLightUpdate(bx + x, y, bz + z); -// lightBlock(bx + x, y, bz + z, brightness); } switch (value) { case 0: diff --git a/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java b/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java index b4423736..0fef349a 100644 --- a/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java @@ -11,6 +11,7 @@ import java.util.Set; import java.util.UUID; public class NullFaweChunk extends FaweChunk { + public static final NullFaweChunk INSTANCE = new NullFaweChunk(null, 0 ,0); /** * A FaweSections object represents a chunk and the blocks that you wish to change in it. * @@ -32,6 +33,11 @@ public class NullFaweChunk extends FaweChunk { return null; } + @Override + public byte[] getBiomeArray() { + return new byte[256]; + } + @Override public int getBitMask() { return 0; @@ -92,6 +98,11 @@ public class NullFaweChunk extends FaweChunk { } + @Override + public void setBiome(int x, int z, byte biome) { + + } + @Override public FaweChunk copy(boolean shallow) { return this; diff --git a/core/src/main/java/com/boydti/fawe/example/WeakFaweQueueMap.java b/core/src/main/java/com/boydti/fawe/example/WeakFaweQueueMap.java index e5eed3e3..3a71d5e9 100644 --- a/core/src/main/java/com/boydti/fawe/example/WeakFaweQueueMap.java +++ b/core/src/main/java/com/boydti/fawe/example/WeakFaweQueueMap.java @@ -6,13 +6,13 @@ import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.SetQueue; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorCompletionService; public class WeakFaweQueueMap implements IFaweQueueMap { @@ -23,12 +23,14 @@ public class WeakFaweQueueMap implements IFaweQueueMap { this.parent = parent; } - /** - * Map of chunks in the queue - */ - public ConcurrentHashMap> blocks = new ConcurrentHashMap>(8, 0.9f, 1) { + public final Long2ObjectOpenHashMap> blocks = new Long2ObjectOpenHashMap>() { @Override public Reference put(Long key, Reference value) { + return put((long) key, value); + } + + @Override + public Reference put(long key, Reference value) { if (parent.getProgressTask() != null) { try { parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1); @@ -36,7 +38,9 @@ public class WeakFaweQueueMap implements IFaweQueueMap { e.printStackTrace(); } } - return super.put(key, value); + synchronized (this) { + return super.put(key, value); + } } }; @@ -142,83 +146,83 @@ public class WeakFaweQueueMap implements IFaweQueueMap { @Override public boolean next(int amount, ExecutorCompletionService pool, long time) { - try { - boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; - int added = 0; - Iterator>> iter = blocks.entrySet().iterator(); - if (amount == 1) { - long start = System.currentTimeMillis(); - do { - if (iter.hasNext()) { - Map.Entry> entry = iter.next(); - Reference chunkReference = entry.getValue(); - FaweChunk chunk = chunkReference.get(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - if (chunk != null) { - parent.start(chunk); - chunk.call(); - parent.end(chunk); + synchronized (blocks) { + try { + boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; + int added = 0; + Iterator>> iter = blocks.entrySet().iterator(); + if (amount == 1) { + long start = System.currentTimeMillis(); + do { + if (iter.hasNext()) { + Map.Entry> entry = iter.next(); + Reference chunkReference = entry.getValue(); + FaweChunk chunk = chunkReference.get(); + if (skip && chunk == lastWrappedChunk) { + continue; + } + iter.remove(); + if (chunk != null) { + parent.start(chunk); + chunk.call(); + parent.end(chunk); + } else { + Fawe.debug("Skipped modifying chunk due to low memory (3)"); + } } else { - Fawe.debug("Skipped modifying chunk due to low memory (3)"); + break; } + } while (System.currentTimeMillis() - start < time); + return !blocks.isEmpty(); + } + boolean result = true; + // amount = 8; + for (int i = 0; i < amount && (result = iter.hasNext());) { + Map.Entry> item = iter.next(); + Reference chunkReference = item.getValue(); + FaweChunk chunk = chunkReference.get(); + if (skip && chunk == lastWrappedChunk) { + continue; + } + iter.remove(); + if (chunk != null) { + parent.start(chunk); + pool.submit(chunk); + added++; + i++; } else { - break; + Fawe.debug("Skipped modifying chunk due to low memory (4)"); } - } while (System.currentTimeMillis() - start < time); - return !blocks.isEmpty(); - } - boolean result = true; - // amount = 8; - for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) { - Map.Entry> item = iter.next(); - Reference chunkReference = item.getValue(); - FaweChunk chunk = chunkReference.get(); - if (skip && chunk == lastWrappedChunk) { - i--; - added--; - continue; } - iter.remove(); - if (chunk != null) { - parent.start(chunk); - pool.submit(chunk); - } else { - Fawe.debug("Skipped modifying chunk due to low memory (4)"); - i--; - added--; - } - } - // if result, then submitted = amount - if (result) { - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < time && result) { - if (result = iter.hasNext()) { - Map.Entry> item = iter.next(); - Reference chunkReference = item.getValue(); - FaweChunk chunk = chunkReference.get(); - if (skip && chunk == lastWrappedChunk) { - continue; - } - iter.remove(); - if (chunk != null) { - parent.start(chunk); - pool.submit(chunk); - FaweChunk fc = ((FaweChunk) pool.take().get()); - parent.end(fc); + // if result, then submitted = amount + if (result) { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < time && result) { + if (result = iter.hasNext()) { + Map.Entry> item = iter.next(); + Reference chunkReference = item.getValue(); + FaweChunk chunk = chunkReference.get(); + if (skip && chunk == lastWrappedChunk) { + continue; + } + iter.remove(); + if (chunk != null) { + parent.start(chunk); + pool.submit(chunk); + FaweChunk fc = ((FaweChunk) pool.take().get()); + parent.end(fc); + } } } } + for (int i = 0; i < added; i++) { + FaweChunk fc = ((FaweChunk) pool.take().get()); + parent.end(fc); + } + } catch (Throwable e) { + e.printStackTrace(); } - for (int i = 0; i < added; i++) { - FaweChunk fc = ((FaweChunk) pool.take().get()); - parent.end(fc); - } - } catch (Throwable e) { - e.printStackTrace(); + return !blocks.isEmpty(); } - return !blocks.isEmpty(); } } diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java index e4dd0c3c..51773078 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java @@ -10,7 +10,6 @@ import com.boydti.fawe.util.MathMan; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.worldedit.world.biome.BaseBiome; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -241,9 +240,9 @@ public class MCAChunk extends FaweChunk { } @Override - public void setBiome(int x, int z, BaseBiome biome) { + public void setBiome(int x, int z, byte biome) { modified = true; - biomes[x + (z << 4)] = (byte) biome.getId();; + biomes[x + (z << 4)] = biome; } @Override @@ -292,6 +291,11 @@ public class MCAChunk extends FaweChunk { return id << 4; } + @Override + public byte[] getBiomeArray() { + return this.biomes; + } + @Override public Set getEntityRemoves() { return new HashSet<>(); diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java index 557dc0a4..8be99df1 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java @@ -41,6 +41,32 @@ public class MCAQueue extends NMSMappedFaweQueue implements Callable { return ids; } + public abstract byte[] getBiomeArray(); + public char[][] getCombinedIdArrays() { char[][] ids = new char[HEIGHT >> 4][]; for (int y = 0; y < HEIGHT >> 4; y++) { @@ -272,7 +274,11 @@ public abstract class FaweChunk implements Callable { */ public abstract CompoundTag getTile(int x, int y, int z); - public abstract void setBiome(final int x, final int z, final BaseBiome biome); + public void setBiome(final int x, final int z, final BaseBiome biome) { + setBiome(x, z, (byte) biome.getId()); + } + + public abstract void setBiome(final int x, final int z, final byte biome); /** * Spend time now so that the chunk can be more efficiently dispatched later
diff --git a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java index 363de060..4983024f 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java @@ -281,8 +281,6 @@ public abstract class FaweQueue { } } - public abstract boolean isChunkLoaded(final int x, final int z); - @Deprecated public boolean regenerateChunk(int x, int z) { return regenerateChunk(x, z, null, null); @@ -349,6 +347,8 @@ public abstract class FaweQueue { return getCombinedId4Data(x, y, z) != 0; } + public abstract int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException; + public abstract int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException; public abstract int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException; diff --git a/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java b/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java index 32e607d0..8cd547ad 100644 --- a/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java @@ -6,6 +6,7 @@ import com.boydti.fawe.object.exception.FaweException; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.entity.BaseEntity; @@ -15,6 +16,7 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; @@ -133,6 +135,17 @@ public class HistoryExtent extends AbstractDelegateExtent { return newList; } + @Override + public boolean setBiome(Vector2D position, BaseBiome newBiome) { + BaseBiome oldBiome = this.getBiome(position); + if (oldBiome.getId() != newBiome.getId()) { + this.changeSet.addBiomeChange(position.getBlockX(), position.getBlockZ(), oldBiome, newBiome); + return extent.setBiome(position, newBiome); + } else { + return false; + } + } + private class TrackedEntity implements Entity { private final Entity entity; diff --git a/core/src/main/java/com/boydti/fawe/object/NullChangeSet.java b/core/src/main/java/com/boydti/fawe/object/NullChangeSet.java index df0dcf6d..44afb47d 100644 --- a/core/src/main/java/com/boydti/fawe/object/NullChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/NullChangeSet.java @@ -5,6 +5,7 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.ArrayList; import java.util.Iterator; @@ -47,6 +48,11 @@ public class NullChangeSet extends FaweChangeSet { } + @Override + public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) { + + } + @Override public void addChangeTask(FaweQueue queue) { diff --git a/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java b/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java index 41ca5941..688c53ad 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java @@ -1,5 +1,6 @@ package com.boydti.fawe.object.brush; +import com.boydti.fawe.config.BBC; import com.boydti.fawe.object.extent.ResettableExtent; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; @@ -176,7 +177,7 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool { target = player.getBlockTrace(getRange(), true); if (target == null) { - player.printError("No block in sight!"); + BBC.NO_BLOCK.send(player); return true; } @@ -216,7 +217,7 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool { try { brush.build(action, editSession, target, material, size); } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError("Max blocks change limit reached."); // Never happens } finally { if (bag != null) { bag.flushChanges(); diff --git a/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java index cd450ca4..4e10bfdf 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java @@ -12,6 +12,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.function.pattern.Pattern; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.util.Map; public class ErodeBrush implements DoubleActionBrush { @@ -130,7 +131,7 @@ public class ErodeBrush implements DoubleActionBrush { } private void erosionIteration(int brushSize, int brushSizeSquared, int erodeFaces, FaweClipboard current, FaweClipboard target) { - Map frequency = Maps.newHashMap(); + Int2ObjectOpenHashMap frequency = new Int2ObjectOpenHashMap<>(); for (int x = -brushSize; x <= brushSize; x++) { for (int y = -brushSize; y <= brushSize; y++) { diff --git a/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java index 50ea684a..031c27b8 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java @@ -42,12 +42,12 @@ public class HeightBrush implements DoubleActionBrush { @Override public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { - int size = (int) (action == DoubleActionBrushTool.BrushAction.PRIMARY ? sizeDouble : -sizeDouble); + int size = (int) sizeDouble; Mask mask = tool.getMask(); if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { mask = null; } heightMap.setSize(size); - heightMap.apply(editSession, mask, position, size, rotation, yscale, true); + heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true); } } diff --git a/core/src/main/java/com/boydti/fawe/object/change/MutableBiomeChange.java b/core/src/main/java/com/boydti/fawe/object/change/MutableBiomeChange.java new file mode 100644 index 00000000..47d3a96b --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/change/MutableBiomeChange.java @@ -0,0 +1,36 @@ +package com.boydti.fawe.object.change; + +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.history.UndoContext; +import com.sk89q.worldedit.history.change.Change; +import com.sk89q.worldedit.world.biome.BaseBiome; + +public class MutableBiomeChange implements Change { + + private Vector2D pos; + private BaseBiome from; + private BaseBiome to; + public MutableBiomeChange() { + this.from = new BaseBiome(0); + this.to = new BaseBiome(0); + this.pos = new Vector2D(); + } + + public void setBiome(int x, int z, int from, int to) { + this.pos.x = x; + this.pos.z = z; + this.from.setId(from); + this.to.setId(to); + } + + @Override + public void undo(UndoContext context) throws WorldEditException { + context.getExtent().setBiome(pos, from); + } + + @Override + public void redo(UndoContext context) throws WorldEditException { + context.getExtent().setBiome(pos, to); + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java index 813797bd..43794735 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/AbstractDelegateChangeSet.java @@ -12,6 +12,7 @@ import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.history.change.EntityCreate; import com.sk89q.worldedit.history.change.EntityRemove; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.Iterator; public class AbstractDelegateChangeSet extends FaweChangeSet { @@ -71,6 +72,11 @@ public class AbstractDelegateChangeSet extends FaweChangeSet { return parent.size(); } + @Override + public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) { + parent.addBiomeChange(x, z, from, to); + } + @Override public void addTileCreate(CompoundTag tag) { parent.addTileCreate(tag); diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java index c4b9e870..599bfc75 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/CPUOptimizedChangeSet.java @@ -8,6 +8,7 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.ArrayList; import java.util.Iterator; @@ -56,6 +57,11 @@ public class CPUOptimizedChangeSet extends FaweChangeSet { throw new UnsupportedOperationException("Invalid mode"); } + @Override + public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) { + throw new UnsupportedOperationException("Invalid mode"); + } + @Override public void addTileCreate(CompoundTag tag) { throw new UnsupportedOperationException("Invalid mode"); diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java index 8d0eb534..ca23dfcf 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java @@ -13,13 +13,13 @@ import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.world.World; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -34,6 +34,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet { private UUID uuid; private File bdFile; + private File bioFile; private File nbtfFile; private File nbttFile; private File entfFile; @@ -49,6 +50,8 @@ public class DiskStorageHistory extends FaweStreamChangeSet { * { short rel x, short rel z, unsigned byte y, short combinedFrom, short combinedTo } */ private OutputStream osBD; + // biome + private OutputStream osBIO; // NBT From private NBTOutputStream osNBTF; // NBT To @@ -117,6 +120,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet { entfFile = new File(folder, index + ".entf"); enttFile = new File(folder, index + ".entt"); bdFile = new File(folder, index + ".bd"); + bioFile = new File(folder, index + ".bio"); } private void init(UUID uuid, int i) { @@ -165,12 +169,16 @@ public class DiskStorageHistory extends FaweStreamChangeSet { public boolean flush() { super.flush(); synchronized (this) { - boolean flushed = osBD != null || osNBTF != null || osNBTT != null && osENTCF != null || osENTCT != null; + boolean flushed = osBD != null || osBIO != null || osNBTF != null || osNBTT != null && osENTCF != null || osENTCT != null; try { if (osBD != null) { osBD.close(); osBD = null; } + if (osBIO != null) { + osBIO.close(); + osBIO = null; + } if (osNBTF != null) { osNBTF.close(); osNBTF = null; @@ -210,6 +218,9 @@ public class DiskStorageHistory extends FaweStreamChangeSet { if (bdFile.exists()) { total += bdFile.length(); } + if (bioFile.exists()) { + total += bioFile.length(); + } if (nbtfFile.exists()) { total += entfFile.length(); } @@ -239,6 +250,19 @@ public class DiskStorageHistory extends FaweStreamChangeSet { } } + @Override + public OutputStream getBiomeOS() throws IOException { + if (osBIO != null) { + return osBIO; + } + synchronized (this) { + bioFile.getParentFile().mkdirs(); + bioFile.createNewFile(); + osBIO = getCompressedOS(new FileOutputStream(bioFile)); + return osBIO; + } + } + @Override public NBTOutputStream getEntityCreateOS() throws IOException { if (osENTCT != null) { @@ -293,6 +317,15 @@ public class DiskStorageHistory extends FaweStreamChangeSet { return is; } + @Override + public InputStream getBiomeIS() throws IOException { + if (!bioFile.exists()) { + return null; + } + InputStream is = MainUtil.getCompressedIS(new FileInputStream(bioFile)); + return is; + } + @Override public NBTInputStream getEntityCreateIS() throws IOException { if (!enttFile.exists()) { @@ -426,25 +459,25 @@ public class DiskStorageHistory extends FaweStreamChangeSet { } } - public HashMap getBlocks() { - HashMap map = new HashMap<>(); + public Map getBlocks() { + Int2ObjectOpenHashMap map = new Int2ObjectOpenHashMap<>(); for (int i = 0; i < blocks.length; i++) { if (blocks[i] != 0) { - map.put(i, blocks[i]); + map.put(i, (Integer) blocks[i]); } } return map; } public Map getPercents() { - HashMap map = getBlocks(); + Map map = getBlocks(); int count = getSize(); - HashMap newMap = new HashMap(); + Int2ObjectOpenHashMap newMap = new Int2ObjectOpenHashMap(); for (Map.Entry entry : map.entrySet()) { int id = entry.getKey(); int changes = entry.getValue(); double percent = ((changes * 1000l) / count) / 10d; - newMap.put(id, percent); + newMap.put(id, (Double) percent); } return newMap; } diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java index 23627f4c..386ee57c 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java @@ -23,6 +23,7 @@ import com.sk89q.worldedit.history.change.EntityCreate; import com.sk89q.worldedit.history.change.EntityRemove; import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -119,6 +120,7 @@ public abstract class FaweChangeSet implements ChangeSet { public abstract void addTileRemove(CompoundTag tag); public abstract void addEntityRemove(CompoundTag tag); public abstract void addEntityCreate(CompoundTag tag); + public abstract void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to); public Iterator getIterator(BlockBag blockBag, int mode, boolean redo) { return getIterator(redo); } @@ -227,79 +229,81 @@ public abstract class FaweChangeSet implements ChangeSet { int cz = previous.getZ(); int bx = cx << 4; int bz = cz << 4; - // Biome changes - { - // TODO - } - // Block changes - // Current blocks -// char[][] currentIds = next.getCombinedIdArrays(); - // Previous blocks in modified sections (i.e. we skip sections that weren't modified) -// char[][] previousIds = previous.getCombinedIdArrays(); - for (int layer = 0; layer < layers; layer++) { - char[] currentLayer = next.getIdArray(layer); - char[] previousLayer = previous.getIdArray(layer); - if (currentLayer == null) { - continue; - } - int startY = layer << 4; - for (int y = 0; y < 16; y++) { - short[][] i1 = FaweCache.CACHE_J[y]; - int yy = y + startY; + synchronized (FaweChangeSet.this) { + // Biome changes + if (previous.getBiomeArray() != null) { + byte[] previousBiomes = previous.getBiomeArray(); + byte[] nextBiomes = next.getBiomeArray(); + int index = 0; for (int z = 0; z < 16; z++) { - int zz = z + bz; - short[] i2 = i1[z]; + int zz = bz + z; for (int x = 0; x < 16; x++) { - int xx = x + bx; - int index = i2[x]; - int combinedIdCurrent = currentLayer[index]; - switch (combinedIdCurrent) { - case 0: - continue; - case 1: - combinedIdCurrent = 0; - default: - char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0; - if (combinedIdCurrent != combinedIdPrevious) { - synchronized (FaweChangeSet.this) { + byte idFrom = previousBiomes[index]; + byte idTo = nextBiomes[index]; + if (idFrom != idTo && idTo != 0) { + addBiomeChange(bx + x, zz, FaweCache.getBiome(idFrom & 0xFF), FaweCache.getBiome(idTo & 0xFF)); + } + index++; + } + } + // TODO + } + // Block changes + for (int layer = 0; layer < layers; layer++) { + char[] currentLayer = next.getIdArray(layer); + char[] previousLayer = previous.getIdArray(layer); + if (currentLayer == null) { + continue; + } + int startY = layer << 4; + for (int y = 0; y < 16; y++) { + short[][] i1 = FaweCache.CACHE_J[y]; + int yy = y + startY; + for (int z = 0; z < 16; z++) { + int zz = z + bz; + short[] i2 = i1[z]; + for (int x = 0; x < 16; x++) { + int xx = x + bx; + int index = i2[x]; + int combinedIdCurrent = currentLayer[index]; + switch (combinedIdCurrent) { + case 0: + continue; + case 1: + combinedIdCurrent = 0; + default: + char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0; + if (combinedIdCurrent != combinedIdPrevious) { add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent); } - } + } } } } } - } - // Tile changes - { - // Tiles created - Map tiles = next.getTiles(); - for (Map.Entry entry : tiles.entrySet()) { - synchronized (FaweChangeSet.this) { + // Tile changes + { + // Tiles created + Map tiles = next.getTiles(); + for (Map.Entry entry : tiles.entrySet()) { addTileCreate(entry.getValue()); } - } - // Tiles removed - tiles = previous.getTiles(); - for (Map.Entry entry : tiles.entrySet()) { - synchronized (FaweChangeSet.this) { + // Tiles removed + tiles = previous.getTiles(); + for (Map.Entry entry : tiles.entrySet()) { addTileRemove(entry.getValue()); } } - } - // Entity changes - { - // Entities created - Set entities = next.getEntities(); - for (CompoundTag entityTag : entities) { - synchronized (FaweChangeSet.this) { + // Entity changes + { + // Entities created + Set entities = next.getEntities(); + for (CompoundTag entityTag : entities) { addEntityCreate(entityTag); } - } - // Entities removed - entities = previous.getEntities(); - for (CompoundTag entityTag : entities) { - synchronized (FaweChangeSet.this) { + // Entities removed + entities = previous.getEntities(); + for (CompoundTag entityTag : entities) { addEntityRemove(entityTag); } } diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java index 005d3ea5..6582b3d3 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/FaweStreamChangeSet.java @@ -3,6 +3,7 @@ package com.boydti.fawe.object.changeset; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweInputStream; import com.boydti.fawe.object.FaweOutputStream; +import com.boydti.fawe.object.change.MutableBiomeChange; import com.boydti.fawe.object.change.MutableBlockChange; import com.boydti.fawe.object.change.MutableEntityChange; import com.boydti.fawe.object.change.MutableFullBlockChange; @@ -15,12 +16,14 @@ import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BaseBiome; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; +import java.util.NoSuchElementException; public abstract class FaweStreamChangeSet extends FaweChangeSet { @@ -266,12 +269,14 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { } public abstract OutputStream getBlockOS(int x, int y, int z) throws IOException; + public abstract OutputStream getBiomeOS() throws IOException; public abstract NBTOutputStream getEntityCreateOS() throws IOException; public abstract NBTOutputStream getEntityRemoveOS() throws IOException; public abstract NBTOutputStream getTileCreateOS() throws IOException; public abstract NBTOutputStream getTileRemoveOS() throws IOException; public abstract InputStream getBlockIS() throws IOException; + public abstract InputStream getBiomeIS() throws IOException; public abstract NBTInputStream getEntityCreateIS() throws IOException; public abstract NBTInputStream getEntityRemoveIS() throws IOException; public abstract NBTInputStream getTileCreateIS() throws IOException; @@ -312,10 +317,32 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { } } + @Override + public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) { + blockSize++; + try { + OutputStream os = getBiomeOS(); + os.write((byte) (x >> 24)); + os.write((byte) (x >> 16)); + os.write((byte) (x >> 8)); + os.write((byte) (x)); + os.write((byte) (z >> 24)); + os.write((byte) (z >> 16)); + os.write((byte) (z >> 8)); + os.write((byte) (z)); + os.write(from.getId()); + os.write(to.getId()); + } + catch (Throwable e) { + MainUtil.handleError(e); + } + } + public void addTileCreate(CompoundTag tag) { if (tag == null) { return; } + blockSize++; try { NBTOutputStream nbtos = getTileCreateOS(); nbtos.writeTag(tag); @@ -328,6 +355,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { if (tag == null) { return; } + blockSize++; try { NBTOutputStream nbtos = getTileRemoveOS(); nbtos.writeTag(tag); @@ -340,6 +368,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { if (tag == null) { return; } + blockSize++; try { NBTOutputStream nbtos = getEntityRemoveOS(); nbtos.writeTag(tag); @@ -352,6 +381,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { if (tag == null) { return; } + blockSize++; try { NBTOutputStream nbtos = getEntityCreateOS(); nbtos.writeTag(tag); @@ -376,32 +406,83 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { idDel.readCombined(is, change, dir); return change; } catch (EOFException ignoreOEF) { - return null; } catch (Exception e) { e.printStackTrace(); MainUtil.handleError(e); } + try { + is.close(); + } catch (IOException e) { + MainUtil.handleError(e); + } return null; } @Override public boolean hasNext() { - if (last != null) { - return true; - } else if ((last = read()) != null) { - return true; + return last != null || ((last = read()) != null); + } + + @Override + public MutableBlockChange next() { + MutableBlockChange tmp = last; + if (tmp == null) { + tmp = read(); + } + last = null; + return tmp; + } + + @Override + public void remove() { + throw new IllegalArgumentException("CANNOT REMOVE"); + } + }; + } + + public Iterator getBiomeIterator(final boolean dir) throws IOException { + final InputStream is = getBiomeIS(); + if (is == null) { + return new ArrayList().iterator(); + } + final MutableBiomeChange change = new MutableBiomeChange(); + return new Iterator() { + private MutableBiomeChange last = new MutableBiomeChange(); + public MutableBiomeChange read() { + try { + int int1 = is.read(); + if (int1 != -1) { + int x = ((int1 << 24) + (is.read() << 16) + (is.read() << 8) + (is.read() << 0)); + int z = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + (is.read() << 0)); + int from = is.read(); + int to = is.read(); + change.setBiome(x, z, from, to); + return change; + } + } catch (EOFException ignoreOEF) { + } catch (Exception e) { + e.printStackTrace(); + MainUtil.handleError(e); } try { is.close(); } catch (IOException e) { MainUtil.handleError(e); } - return false; + return null; } @Override - public MutableBlockChange next() { - MutableBlockChange tmp = last; + public boolean hasNext() { + return last != null || ((last = read()) != null); + } + + @Override + public MutableBiomeChange next() { + MutableBiomeChange tmp = last; + if (tmp == null) { + tmp = read(); + } last = null; return tmp; } @@ -441,8 +522,13 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { idDel.readCombined(is, change, dir); return change; } catch (EOFException ignoreOEF) { - return null; } catch (Exception e) { + e.printStackTrace(); + MainUtil.handleError(e); + } + try { + is.close(); + } catch (IOException e) { MainUtil.handleError(e); } return null; @@ -450,23 +536,15 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { @Override public boolean hasNext() { - if (last == null) { - last = read(); - } - if (last != null) { - return true; - } - try { - is.close(); - } catch (IOException e) { - MainUtil.handleError(e); - } - return false; + return last != null || ((last = read()) != null); } @Override public MutableFullBlockChange next() { MutableFullBlockChange tmp = last; + if (tmp == null) { + tmp = read(); + } last = null; return tmp; } @@ -485,36 +563,35 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { final MutableEntityChange change = new MutableEntityChange(null, create); try { return new Iterator() { - private CompoundTag last = read(); + private MutableEntityChange last = read(); - public CompoundTag read() { + public MutableEntityChange read() { try { - return (CompoundTag) is.readTag(); - } catch (Exception ignoreEOS) {} - return null; - } - - @Override - public boolean hasNext() { - if (last == null) { - last = read(); - } - if (last != null) { - return true; - } + CompoundTag tag = (CompoundTag) is.readTag(); + change.tag = tag; + return change; + } catch (Exception ignoreOEF) {} try { is.close(); } catch (IOException e) { MainUtil.handleError(e); } - return false; + return null; + } + + @Override + public boolean hasNext() { + return last != null || ((last = read()) != null); } @Override public MutableEntityChange next() { - change.tag = last; + MutableEntityChange tmp = last; + if (tmp == null) { + tmp = read(); + } last = null; - return change; + return tmp; } @Override @@ -535,36 +612,35 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { final MutableTileChange change = new MutableTileChange(null, create); try { return new Iterator() { - private CompoundTag last = read(); + private MutableTileChange last = read(); - public CompoundTag read() { + public MutableTileChange read() { try { - return (CompoundTag) is.readTag(); - } catch (Exception ignoreEOS) {} - return null; - } - - @Override - public boolean hasNext() { - if (last == null) { - last = read(); - } - if (last != null) { - return true; - } + CompoundTag tag = (CompoundTag) is.readTag(); + change.tag = tag; + return change; + } catch (Exception ignoreOEF) {} try { is.close(); } catch (IOException e) { MainUtil.handleError(e); } - return false; + return null; + } + + @Override + public boolean hasNext() { + return last != null || ((last = read()) != null); } @Override public MutableTileChange next() { - change.tag = last; + MutableTileChange tmp = last; + if (tmp == null) { + tmp = read(); + } last = null; - return change; + return tmp; } @Override @@ -589,8 +665,10 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { final Iterator blockChange = getBlockIterator(dir); + final Iterator biomeChange = getBiomeIterator(dir); + return new Iterator() { - Iterator[] iterators = new Iterator[]{tileCreate, tileRemove, entityCreate, entityRemove, blockChange}; + Iterator[] iterators = new Iterator[]{tileCreate, tileRemove, entityCreate, entityRemove, blockChange, biomeChange}; int i = 0; Iterator current = iterators[0]; @@ -613,7 +691,15 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet { @Override public Change next() { - return current.next(); + try { + return current.next(); + } catch (Throwable ignore) { + if (i >= iterators.length - 1) { + throw new NoSuchElementException("End of iterator"); + } + current = iterators[++i]; + return next(); + } } }; } catch (Exception e) { diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java index 5ad7557c..5f3ae1c4 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/MemoryOptimizedHistory.java @@ -21,11 +21,14 @@ import java.io.OutputStream; */ public class MemoryOptimizedHistory extends FaweStreamChangeSet { - private int size = 0; private byte[][] ids; private FastByteArrayOutputStream idsStream; private FaweOutputStream idsStreamZip; + private byte[][] biomes; + private FastByteArrayOutputStream biomeStream; + private FaweOutputStream biomeStreamZip; + private byte[][] entC; private FastByteArrayOutputStream entCStream; private NBTOutputStream entCStreamZip; @@ -57,11 +60,16 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet { try { if (idsStream != null) { idsStreamZip.close(); - size = idsStream.getSize(); ids = idsStream.toByteArrays(); idsStream = null; idsStreamZip = null; } + if (biomeStream != null) { + biomeStreamZip.close(); + biomes = biomeStream.toByteArrays(); + biomeStream = null; + biomeStreamZip = null; + } if (entCStream != null) { entCStreamZip.close(); entC = entCStream.toByteArrays(); @@ -125,6 +133,27 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet { } } + @Override + public InputStream getBiomeIS() throws IOException { + if (biomes == null) { + return null; + } + FaweInputStream result = MainUtil.getCompressedIS(new FastByteArraysInputStream(biomes)); + return result; + } + + @Override + public OutputStream getBiomeOS() throws IOException { + if (biomeStreamZip != null) { + return biomeStreamZip; + } + synchronized (this) { + biomeStream = new FastByteArrayOutputStream(Settings.IMP.HISTORY.BUFFER_SIZE); + biomeStreamZip = getCompressedOS(biomeStream); + return biomeStreamZip; + } + } + @Override public InputStream getBlockIS() throws IOException { if (ids == null) { 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 ff440533..55ef380f 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 @@ -10,7 +10,6 @@ import com.sk89q.jnbt.DoubleTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.WorldEditException; @@ -85,10 +84,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent implements HasFa @Override public BaseBiome getBiome(final Vector2D position) { - if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) { - return EditSession.nullBiome; - } - return super.getBiome(position); + return FaweCache.CACHE_BIOME[queue.getBiomeId(position.getBlockX(), position.getBlockZ())]; } @Override diff --git a/core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java b/core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java index cf4fdaf6..0681444d 100644 --- a/core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java +++ b/core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java @@ -53,12 +53,11 @@ public class FuzzyRegion extends AbstractRegion { public Iterator iterator() { return new Iterator() { - private int index = -1; + private int index = set.nextSetBit(0); private BlockVector pos = new BlockVector(0, 0, 0); @Override public boolean hasNext() { - index = set.nextSetBit(index + 1); return index != -1; } @@ -71,6 +70,7 @@ public class FuzzyRegion extends AbstractRegion { pos.mutX(offsetX + (((b3 + ((MathMan.unpair8x(b2)) << 8)) << 21) >> 21)); pos.mutY(offsetY + b1); pos.mutZ(offsetZ + (((b4 + ((MathMan.unpair8y(b2)) << 8)) << 21) >> 21)); + index = set.nextSetBit(index + 1); return pos; } diff --git a/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotTrim.java b/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotTrim.java index 1d3b4e92..8a51cb9d 100644 --- a/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotTrim.java +++ b/core/src/main/java/com/boydti/fawe/regions/general/plot/PlotTrim.java @@ -56,7 +56,7 @@ public class PlotTrim implements Listener { } public void setChunk(int x, int z) { - this.ids = originalQueue.getChunk(originalQueue, x, z).ids; + this.ids = ((MCAChunk) originalQueue.getFaweChunk(x, z)).ids; } @EventHandler diff --git a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java index f70ae0ce..ca2509ab 100644 --- a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java @@ -1,5 +1,7 @@ package com.boydti.fawe.util; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.example.Relighter; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; @@ -7,6 +9,10 @@ import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.exception.FaweException; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; import java.io.File; import java.util.Collection; @@ -49,6 +55,11 @@ public class DelegateFaweQueue extends FaweQueue { parent.addEditSession(session); } + @Override + public World getWEWorld() { + return parent.getWEWorld(); + } + @Override public void setProgressTracker(RunnableVal2 progressTask) { parent.setProgressTracker(progressTask); @@ -89,6 +100,11 @@ public class DelegateFaweQueue extends FaweQueue { parent.setProgressTask(progressTask); } + @Override + public int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException { + return parent.getBiomeId(x, z); + } + @Override public void setChangeTask(RunnableVal2 changeTask) { parent.setChangeTask(changeTask); @@ -104,11 +120,26 @@ public class DelegateFaweQueue extends FaweQueue { parent.optimize(); } + @Override + public int setBlocks(CuboidRegion cuboid, int id, int data) { + return parent.setBlocks(cuboid, id, data); + } + @Override public boolean setBlock(int x, int y, int z, int id, int data) { return parent.setBlock(x, y, z, id, data); } + @Override + public boolean setBlock(int x, int y, int z, int id) { + return parent.setBlock(x, y, z, id); + } + + @Override + public boolean setBlock(int x, int y, int z, int id, int data, CompoundTag nbt) { + return parent.setBlock(x, y, z, id, data, nbt); + } + @Override public void setTile(int x, int y, int z, CompoundTag tag) { parent.setTile(x, y, z, tag); @@ -150,8 +181,24 @@ public class DelegateFaweQueue extends FaweQueue { } @Override - public boolean isChunkLoaded(int x, int z) { - return parent.isChunkLoaded(x, z); + public int getMaxY() { + return parent.getMaxY(); + } + + @Override + public void forEachBlockInChunk(int cx, int cz, RunnableVal2 onEach) { + parent.forEachBlockInChunk(cx, cz, onEach); + } + + @Override + public void forEachTileInChunk(int cx, int cz, RunnableVal2 onEach) { + parent.forEachTileInChunk(cx, cz, onEach); + } + + @Override + @Deprecated + public boolean regenerateChunk(int x, int z) { + return parent.regenerateChunk(x, z); } @Override @@ -179,6 +226,7 @@ public class DelegateFaweQueue extends FaweQueue { parent.sendBlockUpdate(blockMap, players); } + @Deprecated @Override public boolean next() { return parent.next(); @@ -209,6 +257,11 @@ public class DelegateFaweQueue extends FaweQueue { parent.addNotifyTask(x, z, runnable); } + @Override + public boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException { + return parent.hasBlock(x, y, z); + } + @Override public void addNotifyTask(Runnable runnable) { parent.addNotifyTask(runnable); @@ -224,6 +277,11 @@ public class DelegateFaweQueue extends FaweQueue { return parent.getCachedCombinedId4Data(x, y, z); } + @Override + public int getAdjacentLight(int x, int y, int z) { + return parent.getAdjacentLight(x, y, z); + } + @Override public boolean hasSky() { return parent.hasSky(); @@ -234,6 +292,11 @@ public class DelegateFaweQueue extends FaweQueue { return parent.getSkyLight(x, y, z); } + @Override + public int getLight(int x, int y, int z) { + return parent.getLight(x, y, z); + } + @Override public int getEmmittedLight(int x, int y, int z) { return parent.getEmmittedLight(x, y, z); @@ -249,23 +312,98 @@ public class DelegateFaweQueue extends FaweQueue { return parent.getCombinedId4Data(x, y, z, def); } + @Override + public int getCachedCombinedId4Data(int x, int y, int z, int def) { + return parent.getCachedCombinedId4Data(x, y, z, def); + } + @Override public int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) { return parent.getCombinedId4DataDebug(x, y, z, def, session); } + @Override + public int getBrightness(int x, int y, int z) { + return parent.getBrightness(x, y, z); + } + + @Override + public int getOpacityBrightnessPair(int x, int y, int z) { + return parent.getOpacityBrightnessPair(x, y, z); + } + + @Override + public int getOpacity(int x, int y, int z) { + return parent.getOpacity(x, y, z); + } + @Override public int size() { return parent.size(); } + @Override + public boolean isEmpty() { + return parent.isEmpty(); + } + + @Override + public void flush() { + parent.flush(); + } + + @Override + public SetQueue.QueueStage getStage() { + return parent.getStage(); + } + + @Override + public void setStage(SetQueue.QueueStage stage) { + parent.setStage(stage); + } + + @Override + public void flush(int time) { + parent.flush(time); + } + @Override public void runTasks() { parent.runTasks(); } + @Override + public void addTask(Runnable whenFree) { + parent.addTask(whenFree); + } + @Override public boolean enqueue() { return parent.enqueue(); } + + @Override + public void dequeue() { + parent.dequeue(); + } + + @Override + public Relighter getRelighter() { + return parent.getRelighter(); + } + + @Override + public Settings getSettings() { + return parent.getSettings(); + } + + @Override + public void setSettings(Settings settings) { + parent.setSettings(settings); + } + + @Override + public void setWorld(String world) { + parent.setWorld(world); + } } diff --git a/core/src/main/java/com/boydti/fawe/util/WESubscriber.java b/core/src/main/java/com/boydti/fawe/util/WESubscriber.java deleted file mode 100644 index d03cafa4..00000000 --- a/core/src/main/java/com/boydti/fawe/util/WESubscriber.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.boydti.fawe.util; - -import com.sk89q.worldedit.event.extent.EditSessionEvent; -import com.sk89q.worldedit.util.eventbus.EventHandler.Priority; -import com.sk89q.worldedit.util.eventbus.Subscribe; - -public class WESubscriber { - - @Subscribe(priority = Priority.VERY_EARLY) - public void onEditSession(final EditSessionEvent event) {} -} diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index a5531a1c..480c5922 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -72,7 +72,6 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.ChangeSetExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.MaskingExtent; -import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.world.SurvivalModeExtent; import com.sk89q.worldedit.function.GroundFunction; @@ -92,7 +91,6 @@ import com.sk89q.worldedit.function.mask.RegionMask; import com.sk89q.worldedit.function.operation.ChangeSetExecutor; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.function.operation.OperationQueue; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Patterns; @@ -1543,6 +1541,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting public boolean canBypassAll(Region region, boolean get, boolean set) { if (wrapped) return false; FaweRegionExtent regionExtent = getRegionExtent(); + if (!(region instanceof CuboidRegion)) return false; if (regionExtent != null) { if (!(region instanceof CuboidRegion)) return false; Vector pos1 = region.getMinimumPoint(); @@ -1950,7 +1949,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting checkNotNull(dir); checkArgument(distance >= 1, "distance >= 1 required"); final Vector displace = dir.multiply(distance); - // Remove the original blocks + + final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); + final Vector to = region.getMinimumPoint(); + final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to); + final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? new BlockPattern(replacement) : new BlockPattern(new BaseBlock(BlockID.AIR)); final BlockReplace remove = new BlockReplace(EditSession.this, pattern) { @Override @@ -1966,12 +1969,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } }; - // Copy to a buffer so we don't destroy our original before we can copy all the blocks from it - final ForgetfulExtentBuffer buffer = new ForgetfulExtentBuffer(EditSession.this, new RegionMask(region)); - final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, buffer, region.getMinimumPoint()); + copy.setSourceFunction(remove); + copy.setRepetitions(1); copy.setTransform(new AffineTransform().translate(dir.multiply(distance))); - copy.setSourceFunction(remove); // Remove - copy.setRemovingEntities(true); Mask sourceMask = getSourceMask(); if (sourceMask != null) { new MaskTraverser(sourceMask).reset(EditSession.this); @@ -1981,13 +1981,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting if (!copyAir) { copy.setSourceMask(new ExistingBlockMask(EditSession.this)); } - - // Then we need to copy the buffer to the world - final BlockReplace replace = new BlockReplace(EditSession.this, buffer); - final RegionVisitor visitor = new RegionVisitor(buffer.asRegion(), replace); - - final OperationQueue operation = new OperationQueue(copy, visitor); - Operations.completeSmart(operation, new Runnable() { + Operations.completeSmart(copy, new Runnable() { @Override public void run() { EditSession.this.flushQueue(); diff --git a/core/src/main/java/com/sk89q/worldedit/Vector2D.java b/core/src/main/java/com/sk89q/worldedit/Vector2D.java new file mode 100644 index 00000000..fdc51a38 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/Vector2D.java @@ -0,0 +1,670 @@ +/* + * 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; + +import com.sk89q.worldedit.math.transform.AffineTransform; + +/** + * An immutable 2-dimensional vector. + */ +public class Vector2D { + public static final Vector2D ZERO = new Vector2D(0, 0); + public static final Vector2D UNIT_X = new Vector2D(1, 0); + public static final Vector2D UNIT_Z = new Vector2D(0, 1); + public static final Vector2D ONE = new Vector2D(1, 1); + + public double x, z; + + /** + * Construct an instance. + * + * @param x the X coordinate + * @param z the Z coordinate + */ + public Vector2D(double x, double z) { + this.x = x; + this.z = z; + } + + /** + * Construct an instance. + * + * @param x the X coordinate + * @param z the Z coordinate + */ + public Vector2D(int x, int z) { + this.x = (double) x; + this.z = (double) z; + } + + /** + * Construct an instance. + * + * @param x the X coordinate + * @param z the Z coordinate + */ + public Vector2D(float x, float z) { + this.x = (double) x; + this.z = (double) z; + } + + /** + * Copy another vector. + * + * @param other the other vector + */ + public Vector2D(Vector2D other) { + this.x = other.x; + this.z = other.z; + } + + /** + * Construct a new instance with X and Z coordinates set to 0. + * + *

One can also refer to a static {@link #ZERO}.

+ */ + public Vector2D() { + this.x = 0; + this.z = 0; + } + + /** + * Get the X coordinate. + * + * @return the x coordinate + */ + public double getX() { + return x; + } + + /** + * Get the X coordinate rounded. + * + * @return the x coordinate + */ + public int getBlockX() { + return (int) Math.round(x); + } + + /** + * Set the X coordinate. + * + * @param x the new X + * @return a new vector + */ + public Vector2D setX(double x) { + return new Vector2D(x, z); + } + + /** + * Set the X coordinate. + * + * @param x the new X + * @return a new vector + */ + public Vector2D setX(int x) { + return new Vector2D(x, z); + } + + /** + * Get the Z coordinate. + * + * @return the z coordinate + */ + public double getZ() { + return z; + } + + /** + * Get the Z coordinate rounded. + * + * @return the z coordinate + */ + public int getBlockZ() { + return (int) Math.round(z); + } + + /** + * Set the Z coordinate. + * + * @param z the new Z + * @return a new vector + */ + public Vector2D setZ(double z) { + return new Vector2D(x, z); + } + + /** + * Set the Z coordinate. + * + * @param z the new Z + * @return a new vector + */ + public Vector2D setZ(int z) { + return new Vector2D(x, z); + } + + /** + * Add another vector to this vector and return the result as a new vector. + * + * @param other the other vector + * @return a new vector + */ + public Vector2D add(Vector2D other) { + return new Vector2D(x + other.x, z + other.z); + } + + /** + * Add another vector to this vector and return the result as a new vector. + * + * @param x the value to add + * @param z the value to add + * @return a new vector + */ + public Vector2D add(double x, double z) { + return new Vector2D(this.x + x, this.z + z); + } + + /** + * Add another vector to this vector and return the result as a new vector. + * + * @param x the value to add + * @param z the value to add + * @return a new vector + */ + public Vector2D add(int x, int z) { + return new Vector2D(this.x + x, this.z + z); + } + + /** + * Add a list of vectors to this vector and return the + * result as a new vector. + * + * @param others an array of vectors + * @return a new vector + */ + public Vector2D add(Vector2D... others) { + double newX = x, newZ = z; + + for (Vector2D other : others) { + newX += other.x; + newZ += other.z; + } + + return new Vector2D(newX, newZ); + } + + /** + * Subtract another vector from this vector and return the result + * as a new vector. + * + * @param other the other vector + * @return a new vector + */ + public Vector2D subtract(Vector2D other) { + return new Vector2D(x - other.x, z - other.z); + } + + /** + * Subtract another vector from this vector and return the result + * as a new vector. + * + * @param x the value to subtract + * @param z the value to subtract + * @return a new vector + */ + public Vector2D subtract(double x, double z) { + return new Vector2D(this.x - x, this.z - z); + } + + /** + * Subtract another vector from this vector and return the result + * as a new vector. + * + * @param x the value to subtract + * @param z the value to subtract + * @return a new vector + */ + public Vector2D subtract(int x, int z) { + return new Vector2D(this.x - x, this.z - z); + } + + /** + * Subtract a list of vectors from this vector and return the result + * as a new vector. + * + * @param others an array of vectors + * @return a new vector + */ + public Vector2D subtract(Vector2D... others) { + double newX = x, newZ = z; + + for (Vector2D other : others) { + newX -= other.x; + newZ -= other.z; + } + + return new Vector2D(newX, newZ); + } + + /** + * Multiply this vector by another vector on each component. + * + * @param other the other vector + * @return a new vector + */ + public Vector2D multiply(Vector2D other) { + return new Vector2D(x * other.x, z * other.z); + } + + /** + * Multiply this vector by another vector on each component. + * + * @param x the value to multiply + * @param z the value to multiply + * @return a new vector + */ + public Vector2D multiply(double x, double z) { + return new Vector2D(this.x * x, this.z * z); + } + + /** + * Multiply this vector by another vector on each component. + * + * @param x the value to multiply + * @param z the value to multiply + * @return a new vector + */ + public Vector2D multiply(int x, int z) { + return new Vector2D(this.x * x, this.z * z); + } + + /** + * Multiply this vector by zero or more vectors on each component. + * + * @param others an array of vectors + * @return a new vector + */ + public Vector2D multiply(Vector2D... others) { + double newX = x, newZ = z; + + for (Vector2D other : others) { + newX *= other.x; + newZ *= other.z; + } + + return new Vector2D(newX, newZ); + } + + /** + * Perform scalar multiplication and return a new vector. + * + * @param n the value to multiply + * @return a new vector + */ + public Vector2D multiply(double n) { + return new Vector2D(this.x * n, this.z * n); + } + + /** + * Perform scalar multiplication and return a new vector. + * + * @param n the value to multiply + * @return a new vector + */ + public Vector2D multiply(float n) { + return new Vector2D(this.x * n, this.z * n); + } + + /** + * Perform scalar multiplication and return a new vector. + * + * @param n the value to multiply + * @return a new vector + */ + public Vector2D multiply(int n) { + return new Vector2D(this.x * n, this.z * n); + } + + /** + * Divide this vector by another vector on each component. + * + * @param other the other vector + * @return a new vector + */ + public Vector2D divide(Vector2D other) { + return new Vector2D(x / other.x, z / other.z); + } + + /** + * Divide this vector by another vector on each component. + * + * @param x the value to divide by + * @param z the value to divide by + * @return a new vector + */ + public Vector2D divide(double x, double z) { + return new Vector2D(this.x / x, this.z / z); + } + + /** + * Divide this vector by another vector on each component. + * + * @param x the value to divide by + * @param z the value to divide by + * @return a new vector + */ + public Vector2D divide(int x, int z) { + return new Vector2D(this.x / x, this.z / z); + } + + /** + * Perform scalar division and return a new vector. + * + * @param n the value to divide by + * @return a new vector + */ + public Vector2D divide(int n) { + return new Vector2D(x / n, z / n); + } + + /** + * Perform scalar division and return a new vector. + * + * @param n the value to divide by + * @return a new vector + */ + public Vector2D divide(double n) { + return new Vector2D(x / n, z / n); + } + + /** + * Perform scalar division and return a new vector. + * + * @param n the value to divide by + * @return a new vector + */ + public Vector2D divide(float n) { + return new Vector2D(x / n, z / n); + } + + /** + * Get the length of the vector. + * + * @return length + */ + public double length() { + return Math.sqrt(x * x + z * z); + } + + /** + * Get the length, squared, of the vector. + * + * @return length, squared + */ + public double lengthSq() { + return x * x + z * z; + } + + /** + * Get the distance between this vector and another vector. + * + * @param other the other vector + * @return distance + */ + public double distance(Vector2D other) { + return Math.sqrt(Math.pow(other.x - x, 2) + Math.pow(other.z - z, 2)); + } + + /** + * Get the distance between this vector and another vector, squared. + * + * @param other the other vector + * @return distance + */ + public double distanceSq(Vector2D other) { + return Math.pow(other.x - x, 2) + + Math.pow(other.z - z, 2); + } + + /** + * Get the normalized vector, which is the vector divided by its + * length, as a new vector. + * + * @return a new vector + */ + public Vector2D normalize() { + return divide(length()); + } + + /** + * Gets the dot product of this and another vector. + * + * @param other the other vector + * @return the dot product of this and the other vector + */ + public double dot(Vector2D other) { + return x * other.x + z * other.z; + } + + /** + * Checks to see if a vector is contained with another. + * + * @param min the minimum point (X, Y, and Z are the lowest) + * @param max the maximum point (X, Y, and Z are the lowest) + * @return true if the vector is contained + */ + public boolean containedWithin(Vector2D min, Vector2D max) { + return x >= min.x && x <= max.x + && z >= min.z && z <= max.z; + } + + /** + * Checks to see if a vector is contained with another. + * + * @param min the minimum point (X, Y, and Z are the lowest) + * @param max the maximum point (X, Y, and Z are the lowest) + * @return true if the vector is contained + */ + public boolean containedWithinBlock(Vector2D min, Vector2D max) { + return getBlockX() >= min.getBlockX() && getBlockX() <= max.getBlockX() + && getBlockZ() >= min.getBlockZ() && getBlockZ() <= max.getBlockZ(); + } + + /** + * Floors the values of all components. + * + * @return a new vector + */ + public Vector2D floor() { + return new Vector2D(Math.floor(x), Math.floor(z)); + } + + /** + * Rounds all components up. + * + * @return a new vector + */ + public Vector2D ceil() { + return new Vector2D(Math.ceil(x), Math.ceil(z)); + } + + /** + * Rounds all components to the closest integer. + * + *

Components < 0.5 are rounded down, otherwise up.

+ * + * @return a new vector + */ + public Vector2D round() { + return new Vector2D(Math.floor(x + 0.5), Math.floor(z + 0.5)); + } + + /** + * Returns a vector with the absolute values of the components of + * this vector. + * + * @return a new vector + */ + public Vector2D positive() { + return new Vector2D(Math.abs(x), Math.abs(z)); + } + + /** + * Perform a 2D transformation on this vector and return a new one. + * + * @param angle in degrees + * @param aboutX about which x coordinate to rotate + * @param aboutZ about which z coordinate to rotate + * @param translateX what to add after rotation + * @param translateZ what to add after rotation + * @return a new vector + * @see AffineTransform another method to transform vectors + */ + public Vector2D transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) { + angle = Math.toRadians(angle); + double x = this.x - aboutX; + double z = this.z - aboutZ; + double x2 = x * Math.cos(angle) - z * Math.sin(angle); + double z2 = x * Math.sin(angle) + z * Math.cos(angle); + return new Vector2D( + x2 + aboutX + translateX, + z2 + aboutZ + translateZ + ); + } + + /** + * Returns whether this vector is collinear with another vector. + * + * @param other the other vector + * @return true if collinear + */ + public boolean isCollinearWith(Vector2D other) { + if (x == 0 && z == 0) { + // this is a zero vector + return true; + } + + final double otherX = other.x; + final double otherZ = other.z; + + if (otherX == 0 && otherZ == 0) { + // other is a zero vector + return true; + } + + if ((x == 0) != (otherX == 0)) return false; + if ((z == 0) != (otherZ == 0)) return false; + + final double quotientX = otherX / x; + if (!Double.isNaN(quotientX)) { + return other.equals(multiply(quotientX)); + } + + final double quotientZ = otherZ / z; + if (!Double.isNaN(quotientZ)) { + return other.equals(multiply(quotientZ)); + } + + throw new RuntimeException("This should not happen"); + } + + /** + * Create a new {@code BlockVector2D} from this vector. + * + * @return a new {@code BlockVector2D} + */ + public BlockVector2D toBlockVector2D() { + return new BlockVector2D(this); + } + + /** + * Creates a 3D vector by adding a zero Y component to this vector. + * + * @return a new vector + */ + public Vector toVector() { + return new Vector(x, 0, z); + } + + /** + * Creates a 3D vector by adding the specified Y component to this vector. + * + * @param y the Y component + * @return a new vector + */ + public Vector toVector(double y) { + return new Vector(x, y, z); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Vector2D)) { + return false; + } + + Vector2D other = (Vector2D) obj; + return other.x == this.x && other.z == this.z; + + } + + @Override + public int hashCode() { + return ((new Double(x)).hashCode() >> 13) ^ + (new Double(z)).hashCode(); + } + + @Override + public String toString() { + return "(" + x + ", " + z + ")"; + } + + /** + * Gets the minimum components of two vectors. + * + * @param v1 the first vector + * @param v2 the second vector + * @return minimum + */ + public static Vector2D getMinimum(Vector2D v1, Vector2D v2) { + return new Vector2D( + Math.min(v1.x, v2.x), + Math.min(v1.z, v2.z) + ); + } + + /** + * Gets the maximum components of two vectors. + * + * @param v1 the first vector + * @param v2 the second vector + * @return maximum + */ + public static Vector2D getMaximum(Vector2D v1, Vector2D v2) { + return new Vector2D( + Math.max(v1.x, v2.x), + Math.max(v1.z, v2.z) + ); + } + + public static Class inject() { + return Vector2D.class; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index 58fa5b0a..1462da3a 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -94,7 +94,7 @@ public class BiomeCommands { BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry(); List biomes = biomeRegistry.getBiomes(); int totalPages = biomes.size() / 19 + 1; - player.print(BBC.getPrefix() + "Available Biomes (page " + page + "/" + totalPages + ") :"); + BBC.BIOME_LIST_HEADER.send(player, page, totalPages); for (BaseBiome biome : biomes) { if (offset > 0) { offset--; @@ -106,7 +106,7 @@ public class BiomeCommands { break; } } else { - player.print(BBC.getPrefix() + " "); + player.print(BBC.getPrefix() + " "); } } } @@ -132,19 +132,15 @@ public class BiomeCommands { if (args.hasFlag('t')) { Vector blockPosition = player.getBlockTrace(300); if (blockPosition == null) { - player.printError("No block in sight!"); + BBC.NO_BLOCK.send(player); return; } BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D()); biomes.add(biome); - - qualifier = "at line of sight point"; } else if (args.hasFlag('p')) { BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D()); biomes.add(biome); - - qualifier = "at your position"; } else { World world = player.getWorld(); Region region = session.getSelection(world); @@ -158,17 +154,15 @@ public class BiomeCommands { biomes.add(world.getBiome(pt.toVector2D())); } } - - qualifier = "in your selection"; } - player.print(biomes.size() != 1 ? "Biomes " + qualifier + ":" : "Biome " + qualifier + ":"); + BBC.BIOME_LIST_HEADER.send(player, 1, 1); for (BaseBiome biome : biomes) { BiomeData data = biomeRegistry.getData(biome); if (data != null) { player.print(BBC.getPrefix() + " " + data.getName()); } else { - player.print(BBC.getPrefix() + " "); + player.print(BBC.getPrefix() + " "); } } } @@ -204,7 +198,7 @@ public class BiomeCommands { FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace); Operations.completeLegacy(visitor); - player.print(BBC.getPrefix() + "Biomes were changed in " + visitor.getAffected() + " columns. You may have to rejoin your game (or close and reopen your world) to see a change."); + BBC.BIOME_CHANGED.send(player, visitor.getAffected()); } public static Class inject() { diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 55d5ecdd..1753fe01 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -438,7 +438,7 @@ public class BrushCommands { maxRadius = Math.max(config.maxBrushRadius, config.butcherMaxRadius); } if (radius > maxRadius) { - player.printError("Maximum allowed brush radius: " + maxRadius); + BBC.TOOL_RADIUS_ERROR.send(player, maxRadius); return; } 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 a3c740ce..2042b4e4 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -42,7 +42,6 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; @@ -233,7 +232,7 @@ public class ClipboardCommands { public void download(final Player player, final LocalSession session, @Optional("schematic") final String formatName) throws CommandException, WorldEditException { final ClipboardFormat format = ClipboardFormat.findByAlias(formatName); if (format == null) { - player.printError("Unknown schematic format: " + formatName); + BBC.CLIPBOARD_INVALID_FORMAT.send(player, formatName); return; } ClipboardHolder holder = session.getClipboard(); @@ -467,32 +466,6 @@ public class ClipboardCommands { BBC.COMMAND_FLIPPED.send(player); } - @Command( - aliases = { "/load" }, - usage = "", - desc = "Load a schematic into your clipboard", - min = 0, - max = 1 - ) - @Deprecated - @CommandPermissions("worldedit.clipboard.load") - public void load(Actor actor) { - actor.printError("This command is no longer used. See //schematic load."); - } - - @Command( - aliases = { "/save" }, - usage = "", - desc = "Save a schematic into your clipboard", - min = 0, - max = 1 - ) - @Deprecated - @CommandPermissions("worldedit.clipboard.save") - public void save(Actor actor) { - actor.printError("This command is no longer used. See //schematic save."); - } - @Command( aliases = { "clearclipboard" }, usage = "", diff --git a/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 1eb93986..18f8084f 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -8,7 +8,6 @@ import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; @@ -55,36 +54,6 @@ public class GeneralCommands { } } - @Command( - aliases = { "/limit" }, - usage = "", - desc = "Modify block change limit", - min = 1, - max = 1 - ) - @CommandPermissions("worldedit.limit") - public void limit(Player player, LocalSession session, CommandContext args) throws WorldEditException { - - LocalConfiguration config = worldEdit.getConfiguration(); - boolean mayDisable = player.hasPermission("worldedit.limit.unrestricted"); - - int limit = Math.max(-1, args.getInteger(0)); - if (!mayDisable && config.maxChangeLimit > -1) { - if (limit > config.maxChangeLimit) { - player.printError("Your maximum allowable limit is " + config.maxChangeLimit + "."); - return; - } - } - - session.setBlockChangeLimit(limit); - - if (limit != -1) { - player.print(BBC.getPrefix() + "Block change limit set to " + limit + ". (Use //limit -1 to go back to the default.)"); - } else { - player.print(BBC.getPrefix() + "Block change limit set to " + limit + "."); - } - } - @Command( aliases = { "/fast" }, usage = "[on|off]", @@ -98,20 +67,20 @@ public class GeneralCommands { String newState = args.getString(0, null); if (session.hasFastMode()) { if ("on".equals(newState)) { - player.printError("Fast mode already enabled."); + BBC.FAST_ENABLED.send(player); return; } session.setFastMode(false); - player.print(BBC.getPrefix() + "Fast mode disabled."); + BBC.FAST_DISABLED.send(player); } else { if ("off".equals(newState)) { - player.printError("Fast mode already disabled."); + BBC.FAST_DISABLED.send(player); return; } session.setFastMode(true); - player.print(BBC.getPrefix() + "Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes."); + BBC.FAST_ENABLED.send(player); } } @@ -197,9 +166,9 @@ public class GeneralCommands { public void togglePlace(Player player, LocalSession session, CommandContext args) throws WorldEditException { if (session.togglePlacementPosition()) { - player.print(BBC.getPrefix() + "Now placing at pos #1."); + BBC.PLACE_ENABLED.send(player); } else { - player.print(BBC.getPrefix() + "Now placing at the block you stand in."); + BBC.PLACE_DISABLED.send(player); } } diff --git a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index f93839b5..c0bb89a5 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -119,7 +119,7 @@ public class GenerationCommands { Vector pos = session.getPlacementPosition(player); int affected = editSession.makeCylinder(pos, Patterns.wrap(pattern), radiusX, radiusZ, height, !hollow); - player.print(BBC.getPrefix() + affected + " block(s) have been created."); + BBC.VISITOR_BLOCK.send(player, affected); } @Command( @@ -185,7 +185,7 @@ public class GenerationCommands { int affected = editSession.makeSphere(pos, Patterns.wrap(pattern), radiusX, radiusY, radiusZ, !hollow); player.findFreePosition(); - player.print(BBC.getPrefix() + affected + " block(s) have been created."); + BBC.VISITOR_BLOCK.send(player, affected); } @Command( @@ -201,7 +201,7 @@ public class GenerationCommands { public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size, @Optional("tree") TreeType type, @Optional("5") double density) throws WorldEditException { density = density / 100; int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, new TreeGenerator(type)); - player.print(BBC.getPrefix() + affected + " trees created."); + BBC.COMMAND_TREE.send(player, affected); } @Command( @@ -215,7 +215,7 @@ public class GenerationCommands { @Logging(POSITION) public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException { int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem); - player.print(BBC.getPrefix() + affected + " pumpkin patches created."); + BBC.COMMAND_PUMPKIN.send(player, affected); } @Command( @@ -246,7 +246,7 @@ public class GenerationCommands { worldEdit.checkMaxRadius(size); int affected = editSession.makePyramid(pos, Patterns.wrap(pattern), size, !hollow); player.findFreePosition(); - player.print(BBC.getPrefix() + affected + " block(s) have been created."); + BBC.VISITOR_BLOCK.send(player, affected); } @Command( @@ -309,7 +309,7 @@ public class GenerationCommands { try { final int affected = editSession.makeShape(region, zero, unit, Patterns.wrap(pattern), expression, hollow); player.findFreePosition(); - player.print(BBC.getPrefix() + affected + " block(s) have been created."); + BBC.VISITOR_BLOCK.send(player, affected); } catch (ExpressionException e) { player.printError(e.getMessage()); } @@ -374,7 +374,7 @@ public class GenerationCommands { try { final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow); player.findFreePosition(); - player.print(BBC.getPrefix() + "" + affected + " columns affected."); + BBC.VISITOR_FLAT.send(player, affected); } catch (ExpressionException e) { player.printError(e.getMessage()); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index c55471cb..fc4a390d 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -222,7 +222,7 @@ public class HistoryCommands { player.checkPermission("worldedit.history.undo.other"); LocalSession sess = worldEdit.getSession(args.getString(1)); if (sess == null) { - player.printError("Unable to find session for " + args.getString(1)); + BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, args.getString(1)); break; } undone = sess.undo(session.getBlockBag(player), player); @@ -257,7 +257,7 @@ public class HistoryCommands { player.checkPermission("worldedit.history.redo.other"); LocalSession sess = worldEdit.getSession(args.getString(1)); if (sess == null) { - player.printError("Unable to find session for " + args.getString(1)); + BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, args.getString(1)); break; } redone = sess.redo(session.getBlockBag(player), player); diff --git a/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index 98b1b45c..b9357d21 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -185,7 +185,7 @@ public class NavigationCommands { player.findFreePosition(pos); BBC.POOF.send(player); } else { - BBC.JUMPTO_FAIL.send(player); + BBC.NO_BLOCK.send(player); } } diff --git a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index df091026..a230f533 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -789,7 +789,7 @@ public class SelectionCommands { if (found != null) { session.setDefaultRegionSelector(found); - player.print(BBC.getPrefix() + "Your default region selector is now " + found.name() + "."); + BBC.SELECTOR_SET_DEFAULT.send(player, found.name()); } else { throw new RuntimeException("Something unexpected happened. Please report this."); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java index 0375209d..ff3824d0 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java @@ -77,12 +77,12 @@ public class SnapshotCommands { int num = args.argsLength() > 0 ? Math.min(40, Math.max(5, args.getInteger(0))) : 5; - player.print(BBC.getPrefix() + "Snapshots for world: '" + player.getWorld().getName() + "'"); + BBC.SNAPSHOT_LIST_HEADER.send(player, player.getWorld().getName()); for (byte i = 0; i < Math.min(num, snapshots.size()); i++) { player.print(BBC.getPrefix() + (i + 1) + ". " + snapshots.get(i).getName()); } - player.print(BBC.getPrefix() + "Use /snap use [snapshot] or /snap use latest."); + BBC.SNAPSHOT_LIST_FOOTER.send(player); } else { player.printError("No snapshots are available. See console for details."); @@ -129,7 +129,7 @@ public class SnapshotCommands { if (snapshot != null) { session.setSnapshot(null); - player.print(BBC.getPrefix() + "Now using newest snapshot."); + BBC.SNAPSHOT_NEWEST.send(player); } else { player.printError("No snapshots were found."); } @@ -139,7 +139,7 @@ public class SnapshotCommands { } else { try { session.setSnapshot(config.snapshotRepo.getSnapshot(name)); - player.print(BBC.getPrefix() + "Snapshot set to: " + name); + BBC.SNAPSHOT_SET.send(player, name); } catch (InvalidSnapshotException e) { player.printError("That snapshot does not exist or is not available."); } @@ -187,7 +187,7 @@ public class SnapshotCommands { return; } session.setSnapshot(snapshot); - player.print(BBC.getPrefix() + "Snapshot set to: " + snapshot.getName()); + BBC.SNAPSHOT_SET.send(player, snapshot.getName()); } catch (MissingWorldException e) { player.printError("No snapshots were found for this world."); } @@ -224,7 +224,7 @@ public class SnapshotCommands { + dateFormat.format(date.getTime()) + "."); } else { session.setSnapshot(snapshot); - player.print(BBC.getPrefix() + "Snapshot set to: " + snapshot.getName()); + BBC.SNAPSHOT_SET.send(player, snapshot.getName()); } } catch (MissingWorldException ex) { player.printError("No snapshots were found for this world."); @@ -258,11 +258,10 @@ public class SnapshotCommands { Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName()); if (snapshot == null) { dateFormat.setTimeZone(session.getTimeZone()); - player.printError("Couldn't find a snapshot after " - + dateFormat.format(date.getTime()) + "."); + player.printError("Couldn't find a snapshot after " + dateFormat.format(date.getTime()) + "."); } else { session.setSnapshot(snapshot); - player.print(BBC.getPrefix() + "Snapshot set to: " + snapshot.getName()); + BBC.SNAPSHOT_SET.send(player, snapshot.getName()); } } catch (MissingWorldException ex) { player.printError("No snapshots were found for this world."); diff --git a/core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index 8c50f246..d81f2e2b 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -115,7 +115,7 @@ public class SnapshotUtilCommands { // Load chunk store try { chunkStore = snapshot.getChunkStore(); - player.print(BBC.getPrefix() + "Snapshot '" + snapshot.getName() + "' loaded; now restoring..."); + BBC.SNAPSHOT_LOADED.send(player, snapshot.getName()); } catch (DataException e) { player.printError("Failed to load snapshot: " + e.getMessage()); return; diff --git a/core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java index 1a95eeef..c4f6b37f 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java @@ -48,7 +48,7 @@ public class SuperPickaxeCommands { session.setSuperPickaxe(new SinglePickaxe()); session.enableSuperPickAxe(); - player.print(BBC.getPrefix() + "Mode changed. Left click with a pickaxe. // to disable."); + BBC.SUPERPICKAXE_AREA_ENABLED.send(player); } @Command( @@ -65,13 +65,13 @@ public class SuperPickaxeCommands { int range = args.getInteger(0); if (range > config.maxSuperPickaxeSize) { - player.printError("Maximum range: " + config.maxSuperPickaxeSize); + BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); return; } session.setSuperPickaxe(new AreaPickaxe(range)); session.enableSuperPickAxe(); - player.print(BBC.getPrefix() + "Mode changed. Left click with a pickaxe. // to disable."); + BBC.SUPERPICKAXE_AREA_ENABLED.send(player); } @Command( @@ -88,13 +88,13 @@ public class SuperPickaxeCommands { double range = args.getDouble(0); if (range > config.maxSuperPickaxeSize) { - player.printError("Maximum range: " + config.maxSuperPickaxeSize); + BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); return; } session.setSuperPickaxe(new RecursivePickaxe(range)); session.enableSuperPickAxe(); - player.print(BBC.getPrefix() + "Mode changed. Left click with a pickaxe. // to disable."); + BBC.SUPERPICKAXE_AREA_ENABLED.send(player); } public static Class inject() { diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 1d435d09..7a791ae1 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -155,7 +155,7 @@ public class ToolCommands { int range = args.getInteger(1); if (range > config.maxSuperPickaxeSize) { - BBC.TOOL_FLOOD_FILL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); + BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); return; } diff --git a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 2983d3c1..33aeea49 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -442,7 +442,7 @@ public class UtilityCommands { killed += visitor.getAffected(); } - actor.print(BBC.getPrefix() + "Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + "."); + BBC.KILL_SUCCESS.send(actor, killed, radius); if (editSession != null) { session.remember(editSession); @@ -502,7 +502,7 @@ public class UtilityCommands { removed += visitor.getAffected(); } - actor.print(BBC.getPrefix() + "Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal."); + BBC.KILL_SUCCESS.send(removed, radius); if (editSession != null) { session.remember(editSession); diff --git a/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index 258adace..21eb3453 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -107,9 +107,8 @@ public class WorldEditCommands { public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException { TimeZone tz = TimeZone.getTimeZone(args.getString(0)); session.setTimezone(tz); - player.print(BBC.getPrefix() + "Timezone set for this session to: " + tz.getDisplayName()); - player.print(BBC.getPrefix() + "The current time in that timezone is: " - + dateFormat.format(Calendar.getInstance(tz).getTime())); + BBC.TIMEZONE_SET.send(player, tz.getDisplayName()); + BBC.TIMEZONE_DISPLAY.send(player, dateFormat.format(Calendar.getInstance(tz).getTime())); } @Command( diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index e60e1d4c..03b26eae 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -1,5 +1,6 @@ package com.sk89q.worldedit.command.tool; +import com.boydti.fawe.config.BBC; import com.boydti.fawe.object.extent.ResettableExtent; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; @@ -176,7 +177,7 @@ public class BrushTool implements TraceTool { target = player.getBlockTrace(getRange(), true); if (target == null) { - player.printError("No block in sight!"); + BBC.NO_BLOCK.send(player); return true; } @@ -216,7 +217,7 @@ public class BrushTool implements TraceTool { try { brush.build(editSession, target, material, size); } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); + player.printError("Max blocks change limit reached."); // Never happens } finally { if (bag != null) { bag.flushChanges(); diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java b/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java index aeb0e2ab..ef8b38a5 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java +++ b/core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.command.tool; +import com.boydti.fawe.config.BBC; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; @@ -82,7 +83,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo target = player.getBlockTraceFace(getRange(), true); if (target == null) { - player.printError("No block in sight!"); + BBC.NO_BLOCK.send(player); return null; } diff --git a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java index 5b9a5df4..9f496f6e 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultBlockParser.java @@ -22,7 +22,7 @@ package com.sk89q.worldedit.extension.factory; import com.boydti.fawe.jnbt.JSON2NBT; import com.boydti.fawe.jnbt.NBTException; import com.boydti.fawe.util.MathMan; -import com.intellectualcrafters.plot.util.StringMan; +import com.boydti.fawe.util.StringMan; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.BlockVector; diff --git a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java index 4e936544..8c960462 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java @@ -282,19 +282,19 @@ public class DefaultMaskParser extends FaweParser { int requiredMin = 1; int requiredMax = 8; if (split.length == 2) { - String[] split2 = split[1].split(":"); + String[] split2 = split[1].split("[:|,]"); requiredMin = (int) Math.abs(Expression.compile(split2[0]).evaluate()); - if (split2.length == 2) { + if (split2.length >= 2) { requiredMax = (int) Math.abs(Expression.compile(split2[1]).evaluate()); } } if (firstChar == '~') { - return new AdjacentMask(extent, worldEdit.getBlockFactory().parseFromListInput(input.substring(1), tempContext), requiredMin, requiredMax); + return new AdjacentMask(extent, worldEdit.getBlockFactory().parseFromListInput(split[0], tempContext), requiredMin, requiredMax); } else { return new WallMask(extent, worldEdit.getBlockFactory().parseFromListInput(input.substring(1), tempContext), requiredMin, requiredMax); } } catch (NumberFormatException | ExpressionException e) { - throw new SuggestInputParseException(input, "~="); + throw new SuggestInputParseException(input, "~=:"); } } case '>': diff --git a/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index c448452b..dc492825 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -482,7 +482,7 @@ public class PlatformManager { if (pos != null) { player.findFreePosition(pos); } else { - player.printError("No block in sight (or too far)!"); + BBC.NO_BLOCK.send(player); } event.setCancelled(true); diff --git a/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java b/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java index a58c6033..d8cc0d83 100644 --- a/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java +++ b/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java @@ -28,8 +28,8 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.storage.ChunkStore; +import java.util.AbstractSet; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.Set; @@ -315,18 +315,60 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { @Override public Set getChunks() { - Set chunks = new LinkedHashSet(); - Vector min = getMinimumPoint(); Vector max = getMaximumPoint(); + final int maxX = max.getBlockX() >> ChunkStore.CHUNK_SHIFTS; + final int minX = min.getBlockX() >> ChunkStore.CHUNK_SHIFTS; + final int maxZ = max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; + final int minZ = min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; + final int size = (maxX - minX + 1) * (maxZ - minZ + 1); - for (int x = max.getBlockX() >> ChunkStore.CHUNK_SHIFTS; x >= min.getBlockX() >> ChunkStore.CHUNK_SHIFTS; --x) { - for (int z = max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; z >= min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; --z) { - chunks.add(new Vector2D(x, z)); + return new AbstractSet() { + @Override + public Iterator iterator() { + return new Iterator() { + private Vector2D pos = new Vector2D(minX, minZ); + @Override + public boolean hasNext() { + return pos != null; + } + + @Override + public Vector2D next() { + Vector2D result = pos; + // calc next + if (pos.getX() < maxX) { + pos = new Vector2D(pos.getX() + 1, pos.getZ()); + } else if (pos.getZ() < maxZ) { + pos = new Vector2D(minX, pos.getZ() + 1); + } else { + pos = null; + } + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("This set is immutable."); + } + }; } - } - return chunks; + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object o) { + if (o instanceof Vector2D) { + Vector2D cv = (Vector2D) o; + return cv.getX() >= minX && cv.getX() <= maxX && cv.getZ() >= minZ && cv.getZ() <= maxZ; + } else { + return false; + } + } + }; } @Override diff --git a/forge110/build.gradle b/forge110/build.gradle index 263c1075..40b105c2 100644 --- a/forge110/build.gradle +++ b/forge110/build.gradle @@ -58,6 +58,7 @@ shadowJar { relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' dependencies { include(dependency('com.github.luben:zstd-jni:1.1.1')) + include(dependency('co.aikar:fastutil-lite:1.0')) include(dependency(':core')) include(dependency('org.yaml:snakeyaml:1.16')) } diff --git a/forge111/build.gradle b/forge111/build.gradle index c7380bb0..950b05e6 100644 --- a/forge111/build.gradle +++ b/forge111/build.gradle @@ -58,6 +58,7 @@ shadowJar { relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' dependencies { include(dependency('com.github.luben:zstd-jni:1.1.1')) + include(dependency('co.aikar:fastutil-lite:1.0')) include(dependency(':core')) include(dependency('org.yaml:snakeyaml:1.16')) } diff --git a/forge1710/build.gradle b/forge1710/build.gradle index d8bec635..dfbd68c5 100644 --- a/forge1710/build.gradle +++ b/forge1710/build.gradle @@ -49,6 +49,7 @@ shadowJar { relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' dependencies { include(dependency('com.github.luben:zstd-jni:1.1.1')) + include(dependency('co.aikar:fastutil-lite:1.0')) include(dependency(':core')) include(dependency('org.yaml:snakeyaml:1.16')) } diff --git a/forge189/build.gradle b/forge189/build.gradle index cc0b9fd6..a0ad89ac 100644 --- a/forge189/build.gradle +++ b/forge189/build.gradle @@ -58,6 +58,7 @@ shadowJar { relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' dependencies { include(dependency('com.github.luben:zstd-jni:1.1.1')) + include(dependency('co.aikar:fastutil-lite:1.0')) include(dependency(':core')) include(dependency('org.yaml:snakeyaml:1.16')) } diff --git a/forge194/build.gradle b/forge194/build.gradle index a30c49d2..b328804a 100644 --- a/forge194/build.gradle +++ b/forge194/build.gradle @@ -57,6 +57,7 @@ shadowJar { relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' dependencies { include(dependency('com.github.luben:zstd-jni:1.1.1')) + include(dependency('co.aikar:fastutil-lite:1.0')) include(dependency(':core')) include(dependency('org.yaml:snakeyaml:1.16')) } diff --git a/nukkit/build.gradle b/nukkit/build.gradle index 21eaede6..99c97d27 100644 --- a/nukkit/build.gradle +++ b/nukkit/build.gradle @@ -23,6 +23,7 @@ jar.enabled = false shadowJar { dependencies { include(dependency('com.github.luben:zstd-jni:1.1.1')) + include(dependency('co.aikar:fastutil-lite:1.0')) include(dependency(name: 'worldedit-core-6.1.4-SNAPSHOT-dist')) include(dependency('com.google.code.gson:gson:2.2.4')) include(dependency('org.yaml:snakeyaml:1.16')) diff --git a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java index 95afdabc..7697705d 100644 --- a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java +++ b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java @@ -28,9 +28,6 @@ public class FaweNukkit implements IFawe, Listener { private final NukkitWorldEdit plugin; public FaweNukkit(NukkitWorldEdit mod) { - Settings.IMP.HISTORY.USE_DISK = true; - Settings.IMP.CLIPBOARD.USE_DISK = true; - Settings.IMP.HISTORY.COMPRESSION_LEVEL = 9; this.plugin = mod; FaweChunk.HEIGHT = 128; plugin.getServer().getPluginManager().registerEvents(this, plugin); diff --git a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitChunk.java b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitChunk.java index a5aeac6a..d2ae5235 100644 --- a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitChunk.java +++ b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitChunk.java @@ -14,7 +14,6 @@ import com.boydti.fawe.util.MainUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.Vector2D; -import com.sk89q.worldedit.world.biome.BaseBiome; import java.io.IOException; import java.util.Map; @@ -80,28 +79,18 @@ public class NukkitChunk extends CharFaweChunk { final BaseFullChunk chunk = getChunk(); getParent().setHeightMap(this, heightMap); char[][] sections = getCombinedIdArrays(); - final int[][] biomes = getBiomeArray(); final int X = getX() << 4; final int Z = getZ() << 4; if (biomes != null) { final LocalWorld lw = NukkitUtil.getLocalWorld(world); - 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); + final byte[] biomes = getBiomeArray(); + int index = 0; + Vector2D mutable = new Vector2D(); + for (int z = 0; z < 16; z++) { + mutable.z = Z + z; + for (int x = 0; x < 16; x++) { + mutable.x = X + x; + lw.setBiome(mutable, FaweCache.getBiome(biomes[index++] & 0xFF)); } } } diff --git a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java index fbd4dc4f..3cc4872d 100644 --- a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java +++ b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/queue/NukkitQueue.java @@ -236,21 +236,11 @@ public class NukkitQueue extends NMSMappedFaweQueue tasks = new HashMap<>(); + private final ConcurrentHashMap tasks = new ConcurrentHashMap<>(); @Override public int repeat(Runnable runnable, int interval) {