Fix biome change not sending packet
Add optimized biome get and set (AsyncWorld, EditSession etc.)
Add undo for biome changes
Fix tile entities for slow (non NMS) bukkit queue
Translate some stuff
Fix some concurrency issues with autoqueue
cuboid region geChunks() now has fixed memory cost (applies to commands
e.g. //listchunks)
Fix some undo issues
This commit is contained in:
Jesse Boyd 2017-01-29 09:25:53 +11:00
parent 708ac6e03f
commit ebc7ba43e6
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
87 changed files with 2345 additions and 1094 deletions

View File

@ -7,7 +7,6 @@ buildscript {
dependencies { dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
classpath 'org.ajoberstar:grgit:1.7.0' classpath 'org.ajoberstar:grgit:1.7.0'
// classpath 'it.unimi.dsi:fastutil:7.0.12'
} }
} }
@ -80,9 +79,9 @@ subprojects {
repositories { repositories {
mavenCentral() mavenCentral()
maven {url "http://ci.emc.gs/nexus/content/groups/aikar/" }
maven {url "http://ci.regularbox.com/plugin/repository/everything/"} maven {url "http://ci.regularbox.com/plugin/repository/everything/"}
maven {url "http://empcraft.com/maven2"} 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 "https://hub.spigotmc.org/nexus/content/groups/public/"}
maven {url "http://maven.sk89q.com/repo/"} maven {url "http://maven.sk89q.com/repo/"}
maven {url "http://nexus.hc.to/content/repositories/pub_releases"} maven {url "http://nexus.hc.to/content/repositories/pub_releases"}

View File

@ -37,6 +37,7 @@ apply plugin: 'com.github.johnrengelman.shadow'
shadowJar { shadowJar {
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(':core')) include(dependency(':core'))
} }
archiveName = "${parent.name}-${project.name}-${parent.version}.jar" archiveName = "${parent.name}-${project.name}-${parent.version}.jar"

View File

@ -1,7 +1,6 @@
package com.boydti.fawe.bukkit; package com.boydti.fawe.bukkit;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import java.util.HashMap;
import org.apache.commons.lang.mutable.MutableInt; import org.apache.commons.lang.mutable.MutableInt;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
@ -25,7 +24,6 @@ public class BukkitTaskMan extends TaskManager {
} }
public MutableInt index = new MutableInt(0); public MutableInt index = new MutableInt(0);
public HashMap<Integer, Integer> tasks = new HashMap<>();
@Override @Override
public void async(final Runnable r) { public void async(final Runnable r) {

View File

@ -11,10 +11,10 @@ import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.bukkit.BukkitUtil; import com.sk89q.worldedit.bukkit.BukkitUtil;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList; import java.util.ArrayList;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -75,36 +75,26 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
int recommended = 25 + BukkitQueue_All.ALLOCATE; int recommended = 25 + BukkitQueue_All.ALLOCATE;
boolean more = true; boolean more = true;
BukkitQueue_All parent = (BukkitQueue_All) getParent(); final BukkitQueue_All parent = (BukkitQueue_All) getParent();
final Chunk chunk = getChunk(); final Chunk chunk = getChunk();
Object[] disableResult = parent.disableLighting(chunk); Object[] disableResult = parent.disableLighting(chunk);
final World world = chunk.getWorld(); final World world = chunk.getWorld();
char[][] sections = getCombinedIdArrays(); char[][] sections = getCombinedIdArrays();
final int bx = getX() << 4;
final int bz = getZ() << 4;
if (layer == -1) { if (layer == -1) {
// Biomes // Biomes
if (layer == 0) { if (layer == 0) {
final int[][] biomes = getBiomeArray(); final byte[] biomes = getBiomeArray();
if (biomes != null) { if (biomes != null) {
final LocalWorld lw = BukkitUtil.getLocalWorld(world); final LocalWorld lw = BukkitUtil.getLocalWorld(world);
final int X = getX() << 4; int index = 0;
final int Z = getZ() << 4; Vector2D mutable = new Vector2D();
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++) { for (int z = 0; z < 16; z++) {
final int biome = array[z]; mutable.z = bx + z;
if (biome == 0) { for (int x = 0; x < 16; x++) {
continue; mutable.x = bz + x;
} lw.setBiome(mutable, FaweCache.getBiome(biomes[index++] & 0xFF));
if (last != biome) {
last = biome;
bb.setId(biome);
}
lw.setBiome(new Vector2D(X + x, Z + z), bb);
} }
} }
} }
@ -142,11 +132,11 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
final byte[] cacheZ = FaweCache.CACHE_Z[layer]; final byte[] cacheZ = FaweCache.CACHE_Z[layer];
boolean checkTime = !((getAir(layer) == 4096 || (getCount(layer) == 4096 && getAir(layer) == 0) || (getCount(layer) == getAir(layer)))); boolean checkTime = !((getAir(layer) == 4096 || (getCount(layer) == 4096 && getAir(layer) == 0) || (getCount(layer) == getAir(layer))));
if (!checkTime) { if (!checkTime) {
ArrayList<Thread> threads = new ArrayList<Thread>(); final ArrayList<Thread> threads = new ArrayList<Thread>();
for (int k = 0; k < 16; k++) { for (int k = 0; k < 16; k++) {
final int l = k << 8; final int l = k << 8;
final int y = cacheY[l]; final int y = cacheY[l];
Thread thread = new Thread(new Runnable() { final Thread thread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
for (int m = l; m < l + 256; m++) { for (int m = l; m < l + 256; m++) {
@ -166,6 +156,13 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
int x = cacheX[m]; int x = cacheX[m];
int z = cacheZ[m]; int z = cacheZ[m];
int id = combined >> 4; 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); Block block = chunk.getBlock(x, y, z);
setBlock(block, id, (byte) (combined & 0xF)); setBlock(block, id, (byte) (combined & 0xF));
} }
@ -214,15 +211,14 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
int x = cacheX[j]; int x = cacheX[j];
int z = cacheZ[j]; int z = cacheZ[j];
int y = cacheY[j]; int y = cacheY[j];
Block block = chunk.getBlock(x, y, z);
if (FaweCache.hasNBT(id) && parent.adapter != null) { if (FaweCache.hasNBT(id) && parent.adapter != null) {
CompoundTag tile = getTile(x, y, z); CompoundTag tile = getTile(x, y, z);
if (tile != null) { if (tile != null) {
BaseBlock baseBlock = new BaseBlock(id, data, tile); parent.adapter.setBlock(new Location(world, bx + x, y, bz + z), new BaseBlock(id, combined & 0xF, tile), false);
parent.adapter.setBlock(block.getLocation(), baseBlock, false);
break; break;
} }
} }
Block block = chunk.getBlock(x, y, z);
setBlock(block, id, (byte) data); setBlock(block, id, (byte) data);
if (light) { if (light) {
parent.disableLighting(disableResult); parent.disableLighting(disableResult);

View File

@ -161,11 +161,6 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
return getWorldName() != null ? Bukkit.getWorld(getWorldName()) : null; return getWorldName() != null ? Bukkit.getWorld(getWorldName()) : null;
} }
@Override
public boolean isChunkLoaded(World world, int x, int z) {
return world.isChunkLoaded(x, z);
}
@Override @Override
public void sendChunk(int x, int z, int bitMask) {} public void sendChunk(int x, int z, int bitMask) {}
@ -188,15 +183,6 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
return getWorld().getEnvironment() == World.Environment.NORMAL; 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 volatile boolean timingsEnabled;
private static boolean alertTimingsChange = true; private static boolean alertTimingsChange = true;
private static Field fieldTimingsEnabled; private static Field fieldTimingsEnabled;

View File

@ -3,18 +3,18 @@ package com.boydti.fawe.bukkit.v0;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Biome;
public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> { public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot, ChunkSnapshot> {
public static int ALLOCATE; public static int ALLOCATE;
private static int LIGHT_MASK = 0x739C0; private static int LIGHT_MASK = 0x739C0;
@ -39,87 +39,108 @@ public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
@Override @Override
public void setHeightMap(FaweChunk chunk, byte[] heightMap) { public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
// Do nothing // Not supported
} }
@Override @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 @Override
public void setBlockLight(Chunk chunk, int x, int y, int z, int value) { public void setBlockLight(ChunkSnapshot chunk, int x, int y, int z, int value) {
// chunk.getBlock(x & 15, y, z & 15); // 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();
}
return combined;
} }
@Override @Override
public int getEmmittedLight(final Chunk chunk, int x, int y, int z) { public int getCombinedId4Data(ChunkSnapshot chunk, int x, int y, int z) {
if (!chunk.isLoaded()) { if (chunk.isSectionEmpty(y >> 4)) {
TaskManager.IMP.sync(new RunnableVal<Object>() { return 0;
@Override
public void run(Object value) {
chunk.load(true);
} }
}); 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 chunk.getBlock(x, y, z).getLightFromBlocks();
} }
@Override @Override
public int getSkyLight(final Chunk chunk, int x, int y, int z) { public int getBiome(ChunkSnapshot chunkSnapshot, int x, int z) {
if (!chunk.isLoaded()) { Biome biome = chunkSnapshot.getBiome(x & 15, z & 15);
TaskManager.IMP.sync(new RunnableVal<Object>() { return adapter.getBiomeId(biome);
@Override
public void run(Object value) {
chunk.load(true);
}
});
}
return chunk.getBlock(x, y, z).getLightFromSky();
} }
@Override @Override
public int getLight(final Chunk chunk, int x, int y, int z) { public ChunkSnapshot getSections(ChunkSnapshot chunkSnapshot) {
if (!chunk.isLoaded()) { return chunkSnapshot;
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
chunk.load(true);
}
});
}
return chunk.getBlock(x, y, z).getLightLevel();
} }
@Override @Override
public Chunk getCachedSections(World impWorld, int cx, int cz) { public ChunkSnapshot getCachedChunk(World world, int cx, int cz) {
return impWorld.getChunkAt(cx, 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;
}
} }
@Override @Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { public int getEmmittedLight(final ChunkSnapshot chunk, int x, int y, int z) {
return chunk.getBlockEmittedLight(x & 15, y, z & 15);
}
@Override
public int getSkyLight(final ChunkSnapshot chunk, int x, int y, int z) {
return chunk.getBlockSkyLight(x & 15, y, z & 15);
}
@Override
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 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) { if (adapter == null) {
return null; return null;
} }
Location loc = new Location(getWorld(), x, y, z); Location loc = new Location(getWorld(), x, y, z);
BaseBlock block = adapter.getBlock(loc); 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; return block != null ? block.getNbtData() : null;
} }
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Override @Override
public FaweChunk getFaweChunk(int x, int z) { public FaweChunk getFaweChunk(int x, int z) {
return new BukkitChunk_All(this, x, z); return new BukkitChunk_All(this, x, z);

View File

@ -6,8 +6,9 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.IntegerTrio; import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import java.util.HashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
@ -46,11 +47,37 @@ public class ChunkListener implements Listener {
} }
} }
public static void main(String[] args) {
Map<Long, Object> map = new Long2ObjectOpenHashMap<Object>() {
@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 physicsFreeze = false;
public static boolean itemFreeze = false; public static boolean itemFreeze = false;
private HashSet<Long> badChunks = new HashSet<>(); private HashSet<Long> badChunks = new HashSet<>();
private HashMap<Long, IntegerTrio> counter = new HashMap<>(); private Map<Long, IntegerTrio> counter = new Long2ObjectOpenHashMap<>();
private int lastX = Integer.MIN_VALUE, lastZ = Integer.MIN_VALUE; private int lastX = Integer.MIN_VALUE, lastZ = Integer.MIN_VALUE;
private IntegerTrio lastCount; private IntegerTrio lastCount;

View File

@ -396,19 +396,11 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
} }
// Set biomes // Set biomes
int[][] biomes = this.biomes; if (this.biomes != null) {
if (biomes != null) { byte[] currentBiomes = nmsChunk.getBiomeIndex();
for (int x = 0; x < 16; x++) { for (int i = 0 ; i < this.biomes.length; i++) {
int[] array = biomes[x]; if (this.biomes[i] != 0) {
if (array == null) { currentBiomes[i] = this.biomes[i];
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;
} }
} }
} }

View File

@ -64,7 +64,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> { public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R1.Chunk, ChunkSection[], ChunkSection> {
protected static IBlockData air; protected static IBlockData air;
protected static Field fieldBits; protected static Field fieldBits;
@ -304,13 +304,42 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
} }
@Override @Override
public ChunkSection[] getCachedSections(World world, int cx, int cz) { public int getBiome(net.minecraft.server.v1_10_R1.Chunk chunk, int x, int z) {
CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz); return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
return chunk.getHandle().getSections();
} }
@Override @Override
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) { public net.minecraft.server.v1_10_R1.ChunkSection[] getSections(net.minecraft.server.v1_10_R1.Chunk chunk) {
return chunk.getSections();
}
@Override
public net.minecraft.server.v1_10_R1.Chunk loadChunk(World world, int x, int z, boolean generate) {
net.minecraft.server.v1_10_R1.Chunk chunk;
net.minecraft.server.v1_10_R1.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer();
if (generate) {
return provider.getOrLoadChunkAt(x, z);
} else {
return provider.loadChunk(x, z);
}
}
@Override
public net.minecraft.server.v1_10_R1.ChunkSection[] getCachedSections(World world, int cx, int cz) {
net.minecraft.server.v1_10_R1.Chunk chunk = ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
if (chunk != null) {
return chunk.getSections();
}
return null;
}
@Override
public net.minecraft.server.v1_10_R1.Chunk getCachedChunk(World world, int cx, int cz) {
return ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
}
@Override
public net.minecraft.server.v1_10_R1.ChunkSection getCachedSection(net.minecraft.server.v1_10_R1.ChunkSection[] chunkSections, int cy) {
return chunkSections[cy]; return chunkSections[cy];
} }
@ -350,27 +379,21 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
@Override @Override
public void sendChunk(int x, int z, int bitMask) { public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) { net.minecraft.server.v1_10_R1.Chunk chunk = getCachedChunk(getWorld(), x, z);
return; if (chunk != null) {
sendChunk(chunk, bitMask);
} }
sendChunk(getWorld().getChunkAt(x, z), bitMask);
} }
@Override @Override
public void refreshChunk(FaweChunk fc) { public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_10 fs = (BukkitChunk_1_10) fc; net.minecraft.server.v1_10_R1.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (!isChunkLoaded(fc.getX(), fc.getZ())) { if (chunk != null) {
return; sendChunk(chunk, fc.getBitMask());
} }
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
} }
public void sendChunk(Chunk chunk, int mask) { public void sendChunk(net.minecraft.server.v1_10_R1.Chunk nmsChunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
WorldServer w = (WorldServer) nmsChunk.getWorld(); WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap(); PlayerChunkMap chunkMap = w.getPlayerChunkMap();
PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ); PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ);
@ -609,8 +632,8 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
@Override @Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { public CompoundTag getTileEntity(net.minecraft.server.v1_10_R1.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z); pos.c(x, y, z);
TileEntity tile = tiles.get(pos); TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null; return tile != null ? getTag(tile) : null;
@ -627,11 +650,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
} }
} }
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Deprecated @Deprecated
public boolean unloadChunk(final String world, final Chunk chunk) { public boolean unloadChunk(final String world, final Chunk chunk) {
net.minecraft.server.v1_10_R1.Chunk c = ((CraftChunk) chunk).getHandle(); net.minecraft.server.v1_10_R1.Chunk c = ((CraftChunk) chunk).getHandle();

View File

@ -16,7 +16,9 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.Constants;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -64,6 +66,40 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
super(parent, x, z, ids, count, air, heightMap); super(parent, x, z, ids, count, air, heightMap);
} }
public void storeBiomes(byte[] biomes) {
this.biomes = Arrays.copyOf(biomes, biomes.length);
}
public boolean storeTile(TileEntity tile, BlockPosition pos) {
NBTTagCompound tag = new NBTTagCompound();
CompoundTag nativeTag = getParent().getTag(tile);
setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag);
return true;
}
public boolean storeEntity(Entity ent) throws InvocationTargetException, IllegalAccessException {
if (ent instanceof EntityPlayer) {
return false;
}
int x = ((int) Math.round(ent.locX) & 15);
int z = ((int) Math.round(ent.locZ) & 15);
int y = ((int) Math.round(ent.locY) & 0xFF);
int i = FaweCache.CACHE_I[y][z][x];
int j = FaweCache.CACHE_J[y][z][x];
String id = EntityTypes.b(ent);
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) getParent().methodToNative.invoke(getParent().adapter, tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
setEntity(nativeTag);
return true;
} else {
return false;
}
}
@Override @Override
public CharFaweChunk copy(boolean shallow) { public CharFaweChunk copy(boolean shallow) {
BukkitChunk_1_11 copy; BukkitChunk_1_11 copy;
@ -174,6 +210,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
@Override @Override
public FaweChunk call() { public FaweChunk call() {
try { try {
BukkitChunk_1_11_Copy copy = getParent().getChangeTask() != null ? new BukkitChunk_1_11_Copy(getParent(), getX(), getZ()) : null;
final Chunk chunk = this.getChunk(); final Chunk chunk = this.getChunk();
final World world = chunk.getWorld(); final World world = chunk.getWorld();
int bx = this.getX() << 4; int bx = this.getX() << 4;
@ -186,8 +223,6 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
ChunkSection[] sections = nmsChunk.getSections(); ChunkSection[] sections = nmsChunk.getSections();
final Collection<Entity>[] entities = (Collection<Entity>[]) getParent().getEntitySlices.invoke(nmsChunk); final Collection<Entity>[] entities = (Collection<Entity>[]) getParent().getEntitySlices.invoke(nmsChunk);
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities(); Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
// copy
// BukkitChunk_1_11 copy = getParent().getFaweChunk(getX(), getZ()); // TODO
// Set heightmap // Set heightmap
getParent().setHeightMap(this, heightMap); getParent().setHeightMap(this, heightMap);
// Remove entities // Remove entities
@ -198,6 +233,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
Collection<Entity> ents = new ArrayList<>(entities[i]); Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) { for (Entity entity : ents) {
if (entsToRemove.contains(entity.getUniqueID())) { if (entsToRemove.contains(entity.getUniqueID())) {
if (copy != null) {
copy.storeEntity(entity);
}
nmsWorld.removeEntity(entity); nmsWorld.removeEntity(entity);
} }
} }
@ -211,7 +249,11 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
} else if (count >= 4096) { } else if (count >= 4096) {
Collection<Entity> ents = entities[i]; Collection<Entity> ents = entities[i];
if (!ents.isEmpty()) { if (!ents.isEmpty()) {
// copy.storeEntities(this, i); if (copy != null) {
for (Entity entity : ents) {
copy.storeEntity(entity);
}
}
synchronized (BukkitQueue_0.adapter) { synchronized (BukkitQueue_0.adapter) {
ents.clear(); ents.clear();
} }
@ -220,8 +262,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
Collection<Entity> ents = entities[i]; Collection<Entity> ents = entities[i];
if (!ents.isEmpty()) { if (!ents.isEmpty()) {
char[] array = this.getIdArray(i); char[] array = this.getIdArray(i);
if (array == null || entities[i] == null || entities[i].isEmpty()) continue; if (array == null || ents == null || ents.isEmpty()) continue;
ents = new ArrayList<>(entities[i]);
synchronized (BukkitQueue_0.adapter) { synchronized (BukkitQueue_0.adapter) {
for (Entity entity : ents) { for (Entity entity : ents) {
if (entity instanceof EntityPlayer) { if (entity instanceof EntityPlayer) {
@ -232,7 +273,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
int y = (int) Math.round(entity.locY); int y = (int) Math.round(entity.locY);
if (y < 0 || y > 255) continue; if (y < 0 || y > 255) continue;
if (array[FaweCache.CACHE_J[y][z][x]] != 0) { if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
// copy.storeEntity(this, entity); if (copy != null) {
copy.storeEntity(entity);
}
nmsWorld.removeEntity(entity); nmsWorld.removeEntity(entity);
} }
} }
@ -291,11 +334,6 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
} }
} }
} }
// Change task
if (getParent().getChangeTask() != null) {
BukkitChunk_1_11 previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
getParent().getChangeTask().run(previous, this);
}
// Trim tiles // Trim tiles
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator(); Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
HashMap<BlockPosition, TileEntity> toRemove = null; HashMap<BlockPosition, TileEntity> toRemove = null;
@ -315,11 +353,13 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
if (toRemove == null) { if (toRemove == null) {
toRemove = new HashMap<>(); toRemove = new HashMap<>();
} }
if (copy != null) {
storeTile(tile.getValue(), tile.getKey());
}
toRemove.put(tile.getKey(), tile.getValue()); toRemove.put(tile.getKey(), tile.getValue());
} }
} }
if (toRemove != null) { if (toRemove != null) {
// copy.storeTiles(this, toRemove);
for (Map.Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) { for (Map.Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
BlockPosition bp = entry.getKey(); BlockPosition bp = entry.getKey();
TileEntity tile = entry.getValue(); TileEntity tile = entry.getValue();
@ -342,7 +382,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
continue; continue;
} }
ChunkSection section = sections[j]; ChunkSection section = sections[j];
// copy.storeBlocks(this, section); if (copy != null) {
copy.storeSection(section, j);
}
if (section == null) { if (section == null) {
if (count == countAir) { if (count == countAir) {
continue; continue;
@ -410,20 +452,14 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
} }
// Set biomes // Set biomes
int[][] biomes = this.biomes; if (this.biomes != null) {
if (biomes != null) { if (copy != null) {
// copy.storeBiomes(this); copy.storeBiomes(nmsChunk.getBiomeIndex());
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
} }
for (int z = 0; z < 16; z++) { byte[] currentBiomes = nmsChunk.getBiomeIndex();
int biome = array[z]; for (int i = 0 ; i < this.biomes.length; i++) {
if (biome == 0) { if (this.biomes[i] != 0) {
continue; currentBiomes[i] = this.biomes[i];
}
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
} }
} }
} }
@ -442,10 +478,10 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
tileEntity.a(tag); // ReadTagIntoTile tileEntity.a(tag); // ReadTagIntoTile
} }
} }
// Change task? // Change task
// if (getParent().getChangeTask() != null) { // TODO if (copy != null) {
// getParent().getChangeTask().run(copy, this); getParent().getChangeTask().run(copy, this);
// } }
} catch (Throwable e) { } catch (Throwable e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }

View File

@ -1,6 +1,9 @@
package com.boydti.fawe.bukkit.v1_11; package com.boydti.fawe.bukkit.v1_11;
import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.FaweQueue;
import net.minecraft.server.v1_11_R1.ChunkSection;
import net.minecraft.server.v1_11_R1.DataPaletteBlock;
import net.minecraft.server.v1_11_R1.NibbleArray;
public class BukkitChunk_1_11_Copy extends BukkitChunk_1_11 { public class BukkitChunk_1_11_Copy extends BukkitChunk_1_11 {
public final byte[][] idsBytes; public final byte[][] idsBytes;
@ -17,6 +20,21 @@ public class BukkitChunk_1_11_Copy extends BukkitChunk_1_11 {
this.datasBytes[i] = data; this.datasBytes[i] = data;
} }
public boolean storeSection(ChunkSection section, int layer) throws IllegalAccessException {
if (section == null) {
return false;
}
DataPaletteBlock blocks = section.getBlocks();
byte[] ids = new byte[4096];
NibbleArray data = new NibbleArray();
blocks.exportData(ids, data);
set(layer, ids, data.asBytes());
short solid = (short) getParent().fieldNonEmptyBlockCount.getInt(section);
count[layer] = solid;
air[layer] = (short) (4096 - solid);
return true;
}
@Override @Override
public char[][] getCombinedIdArrays() { public char[][] getCombinedIdArrays() {
for (int i = 0; i < ids.length; i++) { for (int i = 0; i < ids.length; i++) {

View File

@ -68,7 +68,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> { public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R1.Chunk, ChunkSection[], ChunkSection> {
protected static IBlockData air; protected static IBlockData air;
protected static Field fieldBits; protected static Field fieldBits;
@ -150,6 +150,41 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
getImpWorld(); getImpWorld();
} }
@Override
public ChunkSection[] getSections(net.minecraft.server.v1_11_R1.Chunk chunk) {
return chunk.getSections();
}
@Override
public net.minecraft.server.v1_11_R1.Chunk loadChunk(World world, int x, int z, boolean generate) {
net.minecraft.server.v1_11_R1.Chunk chunk;
net.minecraft.server.v1_11_R1.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_11_R1.CraftWorld) world).getHandle().getChunkProviderServer();
if (generate) {
return provider.getOrLoadChunkAt(x, z);
} else {
return provider.loadChunk(x, z);
}
}
@Override
public ChunkSection[] getCachedSections(World world, int cx, int cz) {
net.minecraft.server.v1_11_R1.Chunk chunk = ((org.bukkit.craftbukkit.v1_11_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
if (chunk != null) {
return chunk.getSections();
}
return null;
}
@Override
public net.minecraft.server.v1_11_R1.Chunk getCachedChunk(World world, int cx, int cz) {
return ((org.bukkit.craftbukkit.v1_11_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
}
@Override
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
}
@Override @Override
public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) { public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
if (biome != null) { if (biome != null) {
@ -310,17 +345,6 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}); });
} }
@Override
public ChunkSection[] getCachedSections(World world, int cx, int cz) {
CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz);
return chunk.getHandle().getSections();
}
@Override
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
}
@Override @Override
public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) { public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) {
DataPaletteBlock dataPalette = lastSection.getBlocks(); DataPaletteBlock dataPalette = lastSection.getBlocks();
@ -334,6 +358,11 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
} }
} }
@Override
public int getBiome(net.minecraft.server.v1_11_R1.Chunk chunk, int x, int z) {
return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
@Override @Override
public int getOpacity(ChunkSection section, int x, int y, int z) { public int getOpacity(ChunkSection section, int x, int y, int z) {
DataPaletteBlock dataPalette = section.getBlocks(); DataPaletteBlock dataPalette = section.getBlocks();
@ -357,27 +386,21 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
@Override @Override
public void sendChunk(int x, int z, int bitMask) { public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) { net.minecraft.server.v1_11_R1.Chunk chunk = getCachedChunk(getWorld(), x, z);
return; if (chunk != null) {
sendChunk(chunk, bitMask);
} }
sendChunk(getWorld().getChunkAt(x, z), bitMask);
} }
@Override @Override
public void refreshChunk(FaweChunk fc) { public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_11 fs = (BukkitChunk_1_11) fc; net.minecraft.server.v1_11_R1.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (!isChunkLoaded(fc.getX(), fc.getZ())) { if (chunk != null) {
return; sendChunk(chunk, fc.getBitMask());
} }
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
} }
public void sendChunk(Chunk chunk, int mask) { public void sendChunk(net.minecraft.server.v1_11_R1.Chunk nmsChunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
net.minecraft.server.v1_11_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
WorldServer w = (WorldServer) nmsChunk.getWorld(); WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap(); PlayerChunkMap chunkMap = w.getPlayerChunkMap();
PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ); PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ);
@ -387,6 +410,13 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
if (playerChunk.c.isEmpty()) { if (playerChunk.c.isEmpty()) {
return; return;
} }
if (mask == 0) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65535);
for (EntityPlayer player : playerChunk.c) {
player.playerConnection.sendPacket(packet);
}
return;
}
// Send chunks // Send chunks
boolean empty = false; boolean empty = false;
ChunkSection[] sections = nmsChunk.getSections(); ChunkSection[] sections = nmsChunk.getSections();
@ -396,7 +426,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
empty = true; empty = true;
} }
} }
if (mask == 0 || mask == 0 || mask == 65535 && hasEntities(nmsChunk)) { if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280); PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280);
for (EntityPlayer player : playerChunk.c) { for (EntityPlayer player : playerChunk.c) {
player.playerConnection.sendPacket(packet); player.playerConnection.sendPacket(packet);
@ -600,8 +630,8 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
@Override @Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { public CompoundTag getTileEntity(net.minecraft.server.v1_11_R1.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z); pos.c(x, y, z);
TileEntity tile = tiles.get(pos); TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null; return tile != null ? getTag(tile) : null;
@ -618,11 +648,6 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
} }
} }
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Deprecated @Deprecated
public boolean unloadChunk(final String world, final Chunk chunk) { public boolean unloadChunk(final String world, final Chunk chunk) {
net.minecraft.server.v1_11_R1.Chunk c = ((CraftChunk) chunk).getHandle(); net.minecraft.server.v1_11_R1.Chunk c = ((CraftChunk) chunk).getHandle();

View File

@ -352,19 +352,11 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk, BukkitQueue17> {
} }
// Set biomes // Set biomes
int[][] biomes = this.biomes; if (this.biomes != null) {
if (biomes != null) { byte[] currentBiomes = nmsChunk.m();
for (int x = 0; x < 16; x++) { for (int i = 0 ; i < this.biomes.length; i++) {
int[] array = biomes[x]; if (this.biomes[i] != 0) {
if (array == null) { currentBiomes[i] = this.biomes[i];
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
} }
} }
} }

View File

@ -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.WorldSettings;
import net.minecraft.server.v1_7_R4.WorldType; import net.minecraft.server.v1_7_R4.WorldType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.WorldCreator; import org.bukkit.WorldCreator;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
@ -59,7 +58,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> { public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Chunk, ChunkSection[], ChunkSection> {
protected static Field fieldData; protected static Field fieldData;
protected static Field fieldIds; protected static Field fieldIds;
@ -175,18 +174,48 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
} }
} }
@Override
public boolean isChunkLoaded(int x, int z) {
return getWorld().isChunkLoaded(x, z);
}
public World getWorld(String world) { public World getWorld(String world) {
return Bukkit.getWorld(world); return Bukkit.getWorld(world);
} }
@Override @Override
public boolean loadChunk(World world, int x, int z, boolean generate) { public int getBiome(net.minecraft.server.v1_7_R4.Chunk chunk, int x, int z) {
return getCachedSections(world, x, z) != null; return chunk.m()[((z & 15) << 4) + (x & 15)];
}
@Override
public net.minecraft.server.v1_7_R4.ChunkSection[] getSections(net.minecraft.server.v1_7_R4.Chunk chunk) {
return chunk.getSections();
}
@Override
public net.minecraft.server.v1_7_R4.Chunk loadChunk(World world, int x, int z, boolean generate) {
net.minecraft.server.v1_7_R4.Chunk chunk;
net.minecraft.server.v1_7_R4.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_7_R4.CraftWorld) world).getHandle().chunkProviderServer;
if (generate) {
return provider.getOrCreateChunk(x, z);
} else {
return provider.loadChunk(x, z);
}
}
@Override
public net.minecraft.server.v1_7_R4.ChunkSection[] getCachedSections(World world, int cx, int cz) {
net.minecraft.server.v1_7_R4.Chunk chunk = ((org.bukkit.craftbukkit.v1_7_R4.CraftWorld) world).getHandle().chunkProviderServer.getChunkIfLoaded(cx, cz);
if (chunk != null) {
return chunk.getSections();
}
return null;
}
@Override
public net.minecraft.server.v1_7_R4.Chunk getCachedChunk(World world, int cx, int cz) {
return ((org.bukkit.craftbukkit.v1_7_R4.CraftWorld) world).getHandle().chunkProviderServer.getChunkIfLoaded(cx, cz);
}
@Override
public net.minecraft.server.v1_7_R4.ChunkSection getCachedSection(net.minecraft.server.v1_7_R4.ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
} }
@Override @Override
@ -200,18 +229,6 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
} }
} }
@Override
public ChunkSection[] getCachedSections(World world, int x, int z) {
Chunk chunk = world.getChunkAt(x, z);
if (chunk == null) {
return null;
}
if (!chunk.isLoaded()) {
chunk.load(true);
}
return ((CraftChunk) chunk).getHandle().getSections();
}
@Override @Override
public int getCombinedId4Data(ChunkSection ls, int x, int y, int z) { public int getCombinedId4Data(ChunkSection ls, int x, int y, int z) {
byte[] ids = ls.getIdArray(); byte[] ids = ls.getIdArray();
@ -221,16 +238,6 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
return combined; return combined;
} }
@Override
public boolean isChunkLoaded(World world, int x, int z) {
return world.isChunkLoaded(x, z);
}
@Override
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
}
@Override @Override
public CharFaweChunk getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception { public CharFaweChunk getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Map<ChunkPosition, TileEntity> tiles = (Map<ChunkPosition, TileEntity>) tilesGeneric; Map<ChunkPosition, TileEntity> tiles = (Map<ChunkPosition, TileEntity>) tilesGeneric;
@ -307,19 +314,14 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
} }
@Override @Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { public CompoundTag getTileEntity(net.minecraft.server.v1_7_R4.Chunk chunk, int x, int y, int z) {
Map<ChunkPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().tileEntities; Map<ChunkPosition, TileEntity> tiles = chunk.tileEntities;
ChunkPosition pos = new ChunkPosition(x, y, z); ChunkPosition pos = new ChunkPosition(x, y, z);
TileEntity tile = tiles.get(pos); TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null; 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 { public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
fieldTickingBlockCount.set(section, tickingBlockCount); fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
@ -331,28 +333,22 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
@Override @Override
public void sendChunk(int x, int z, int bitMask) { public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) { net.minecraft.server.v1_7_R4.Chunk chunk = getCachedChunk(getWorld(), x, z);
return; if (chunk != null) {
sendChunk(chunk, bitMask);
} }
sendChunk(getWorld().getChunkAt(x, z), bitMask);
} }
@Override @Override
public void refreshChunk(FaweChunk fc) { public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_7 fs = (BukkitChunk_1_7) fc; net.minecraft.server.v1_7_R4.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (!isChunkLoaded(fc.getX(), fc.getZ())) { if (chunk != null) {
return; sendChunk(chunk, fc.getBitMask());
} }
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
} }
public void sendChunk(Chunk chunk, int mask) { public void sendChunk(net.minecraft.server.v1_7_R4.Chunk nmsChunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
try { try {
net.minecraft.server.v1_7_R4.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
ChunkCoordIntPair pos = nmsChunk.l(); // getPosition() ChunkCoordIntPair pos = nmsChunk.l(); // getPosition()
WorldServer w = (WorldServer) nmsChunk.world; WorldServer w = (WorldServer) nmsChunk.world;
PlayerChunkMap chunkMap = w.getPlayerChunkMap(); PlayerChunkMap chunkMap = w.getPlayerChunkMap();

View File

@ -285,19 +285,11 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
} }
// Set biomes // Set biomes
int[][] biomes = this.biomes; if (this.biomes != null) {
if (biomes != null) { byte[] currentBiomes = nmsChunk.getBiomeIndex();
for (int x = 0; x < 16; x++) { for (int i = 0 ; i < this.biomes.length; i++) {
int[] array = biomes[x]; if (this.biomes[i] != 0) {
if (array == null) { currentBiomes[i] = this.biomes[i];
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;
} }
} }
} }

View File

@ -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.WorldSettings;
import net.minecraft.server.v1_8_R3.WorldType; import net.minecraft.server.v1_8_R3.WorldType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.WorldCreator; import org.bukkit.WorldCreator;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
@ -58,7 +57,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> { public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.Chunk, ChunkSection[], ChunkSection> {
public static Field isDirty; public static Field isDirty;
@ -180,17 +179,43 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
} }
@Override @Override
public boolean isChunkLoaded(int x, int z) { public int getBiome(net.minecraft.server.v1_8_R3.Chunk chunk, int x, int z) {
return getWorld().isChunkLoaded(x, z); return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
public World getWorld(String world) {
return Bukkit.getWorld(world);
} }
@Override @Override
public boolean loadChunk(World world, int x, int z, boolean generate) { public net.minecraft.server.v1_8_R3.ChunkSection[] getSections(net.minecraft.server.v1_8_R3.Chunk chunk) {
return getCachedSections(world, x, z) != null; return chunk.getSections();
}
@Override
public net.minecraft.server.v1_8_R3.Chunk loadChunk(World world, int x, int z, boolean generate) {
net.minecraft.server.v1_8_R3.Chunk chunk;
net.minecraft.server.v1_8_R3.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_8_R3.CraftWorld) world).getHandle().chunkProviderServer;
if (generate) {
return provider.getOrCreateChunk(x, z);
} else {
return provider.loadChunk(x, z);
}
}
@Override
public net.minecraft.server.v1_8_R3.ChunkSection[] getCachedSections(World world, int cx, int cz) {
net.minecraft.server.v1_8_R3.Chunk chunk = ((CraftWorld) world).getHandle().chunkProviderServer.getChunkIfLoaded(cx, cz);
if (chunk != null) {
return chunk.getSections();
}
return null;
}
@Override
public net.minecraft.server.v1_8_R3.Chunk getCachedChunk(World world, int cx, int cz) {
return ((org.bukkit.craftbukkit.v1_8_R3.CraftWorld) world).getHandle().chunkProviderServer.getChunkIfLoaded(cx, cz);
}
@Override
public net.minecraft.server.v1_8_R3.ChunkSection getCachedSection(net.minecraft.server.v1_8_R3.ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
} }
@Override @Override
@ -204,34 +229,12 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
} }
} }
@Override
public ChunkSection[] getCachedSections(World world, int x, int z) {
Chunk chunk = world.getChunkAt(x, z);
if (chunk == null) {
return null;
}
if (!chunk.isLoaded()) {
chunk.load(true);
}
return ((CraftChunk) chunk).getHandle().getSections();
}
@Override @Override
public int getCombinedId4Data(ChunkSection section, int x, int y, int z) { public int getCombinedId4Data(ChunkSection section, int x, int y, int z) {
char[] ls = section.getIdArray(); char[] ls = section.getIdArray();
return ls[FaweCache.CACHE_J[y][z & 15][x & 15]]; return ls[FaweCache.CACHE_J[y][z & 15][x & 15]];
} }
@Override
public boolean isChunkLoaded(World world, int x, int z) {
return world.isChunkLoaded(x, z);
}
@Override
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
}
@Override @Override
public CharFaweChunk getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception { public CharFaweChunk getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric; Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric;
@ -309,19 +312,14 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
private BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); private BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
@Override @Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { public CompoundTag getTileEntity(net.minecraft.server.v1_8_R3.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z); pos.c(x, y, z);
TileEntity tile = tiles.get(pos); TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null; 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 { public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
fieldTickingBlockCount.set(section, tickingBlockCount); fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
@ -333,28 +331,22 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
@Override @Override
public void sendChunk(int x, int z, int bitMask) { public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) { net.minecraft.server.v1_8_R3.Chunk chunk = getCachedChunk(getWorld(), x, z);
return; if (chunk != null) {
sendChunk(chunk, bitMask);
} }
sendChunk(getWorld().getChunkAt(x, z), bitMask);
} }
@Override @Override
public void refreshChunk(FaweChunk fc) { public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_8 fs = (BukkitChunk_1_8) fc; net.minecraft.server.v1_8_R3.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (!isChunkLoaded(fc.getX(), fc.getZ())) { if (chunk != null) {
return; sendChunk(chunk, fc.getBitMask());
} }
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
} }
public void sendChunk(Chunk chunk, int mask) { public void sendChunk(net.minecraft.server.v1_8_R3.Chunk nmsChunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
try { try {
net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
WorldServer w = (WorldServer) nmsChunk.getWorld(); WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap(); PlayerChunkMap chunkMap = w.getPlayerChunkMap();
int x = nmsChunk.locX; int x = nmsChunk.locX;

View File

@ -39,7 +39,6 @@ import net.minecraft.server.v1_9_R2.NBTTagCompound;
import net.minecraft.server.v1_9_R2.TileEntity; import net.minecraft.server.v1_9_R2.TileEntity;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk; import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
@ -403,19 +402,13 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
} }
// Set biomes // Set biomes
int[][] biomes = this.biomes; byte[] biomes = this.biomes;
if (biomes != null) { if (biomes != null) {
for (int x = 0; x < 16; x++) { byte[] currentBiomes = nmsChunk.getBiomeIndex();
int[] array = biomes[x]; for (int i = 0; i < currentBiomes.length; i++) {
if (array == null) { byte newBiome = biomes[i];
continue; if (newBiome != 0) {
} currentBiomes[i] = newBiome;
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
} }
} }
} }
@ -437,23 +430,6 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
} catch (Throwable e) { } catch (Throwable e) {
MainUtil.handleError(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; return this;
} }
} }

View File

@ -62,7 +62,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> { public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_R2.Chunk, ChunkSection[], ChunkSection> {
protected static IBlockData air; protected static IBlockData air;
protected static Field fieldBits; protected static Field fieldBits;
@ -191,13 +191,42 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
} }
@Override @Override
public ChunkSection[] getCachedSections(World world, int cx, int cz) { public int getBiome(net.minecraft.server.v1_9_R2.Chunk chunk, int x, int z) {
CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz); return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
return chunk.getHandle().getSections();
} }
@Override @Override
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) { public net.minecraft.server.v1_9_R2.ChunkSection[] getSections(net.minecraft.server.v1_9_R2.Chunk chunk) {
return chunk.getSections();
}
@Override
public net.minecraft.server.v1_9_R2.Chunk loadChunk(World world, int x, int z, boolean generate) {
net.minecraft.server.v1_9_R2.Chunk chunk;
net.minecraft.server.v1_9_R2.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_9_R2.CraftWorld) world).getHandle().getChunkProviderServer();
if (generate) {
return provider.getOrLoadChunkAt(x, z);
} else {
return provider.loadChunk(x, z);
}
}
@Override
public net.minecraft.server.v1_9_R2.ChunkSection[] getCachedSections(World world, int cx, int cz) {
net.minecraft.server.v1_9_R2.Chunk chunk = ((org.bukkit.craftbukkit.v1_9_R2.CraftWorld) world).getHandle().getChunkProviderServer().getLoadedChunkAt(cx, cz);
if (chunk != null) {
return chunk.getSections();
}
return null;
}
@Override
public net.minecraft.server.v1_9_R2.Chunk getCachedChunk(World world, int cx, int cz) {
return ((org.bukkit.craftbukkit.v1_9_R2.CraftWorld) world).getHandle().getChunkProviderServer().getLoadedChunkAt(cx, cz);
}
@Override
public net.minecraft.server.v1_9_R2.ChunkSection getCachedSection(net.minecraft.server.v1_9_R2.ChunkSection[] chunkSections, int cy) {
return chunkSections[cy]; return chunkSections[cy];
} }
@ -216,27 +245,21 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
@Override @Override
public void sendChunk(int x, int z, int bitMask) { public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) { net.minecraft.server.v1_9_R2.Chunk chunk = getCachedChunk(getWorld(), x, z);
return; if (chunk != null) {
sendChunk(chunk, bitMask);
} }
sendChunk(getWorld().getChunkAt(x, z), bitMask);
} }
@Override @Override
public void refreshChunk(FaweChunk fc) { public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_9 fs = (BukkitChunk_1_9) fc; net.minecraft.server.v1_9_R2.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (!isChunkLoaded(fc.getX(), fc.getZ())) { if (chunk != null) {
return; sendChunk(chunk, fc.getBitMask());
} }
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
} }
public void sendChunk(Chunk chunk, int mask) { public void sendChunk(net.minecraft.server.v1_9_R2.Chunk nmsChunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
WorldServer w = (WorldServer) nmsChunk.getWorld(); WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap(); PlayerChunkMap chunkMap = w.getPlayerChunkMap();
PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ); PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ);
@ -560,8 +583,8 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
@Override @Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) { public CompoundTag getTileEntity(net.minecraft.server.v1_9_R2.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities(); Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z); pos.c(x, y, z);
TileEntity tile = tiles.get(pos); TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null; return tile != null ? getTag(tile) : null;
@ -578,11 +601,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
} }
} }
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Deprecated @Deprecated
public boolean unloadChunk(final String world, final Chunk chunk) { public boolean unloadChunk(final String world, final Chunk chunk) {
net.minecraft.server.v1_9_R2.Chunk c = ((CraftChunk) chunk).getHandle(); net.minecraft.server.v1_9_R2.Chunk c = ((CraftChunk) chunk).getHandle();

View File

@ -805,7 +805,7 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue
@Override @Override
public Biome getBiome(int x, int z) { public Biome getBiome(int x, int z) {
throw new UnsupportedOperationException("NOT IMPLEMENTED"); return adapter.getBiome(queue.getBiomeId(x, z));
} }
@Override @Override

View File

@ -7,6 +7,7 @@ dependencies {
compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT' compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT'
compile 'org.primesoft:BlocksHub:2.0' compile 'org.primesoft:BlocksHub:2.0'
compile 'com.github.luben:zstd-jni:1.1.1' compile 'com.github.luben:zstd-jni:1.1.1'
compile 'co.aikar:fastutil-lite:1.0'
compile(group: 'com.sk89q.worldedit', name: 'worldedit-core', version:'6.1.3-SNAPSHOT') { compile(group: 'com.sk89q.worldedit', name: 'worldedit-core', version:'6.1.3-SNAPSHOT') {
exclude(module: 'bukkit-classloader-check') exclude(module: 'bukkit-classloader-check')
} }

View File

@ -16,7 +16,6 @@ import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.Updater; import com.boydti.fawe.util.Updater;
import com.boydti.fawe.util.WEManager; import com.boydti.fawe.util.WEManager;
import com.boydti.fawe.util.WESubscriber;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;
@ -25,6 +24,7 @@ import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BlockData; import com.sk89q.worldedit.blocks.BlockData;
import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BiomeCommands;
@ -254,7 +254,6 @@ public class Fawe {
Fawe.debug("Plugin 'PlotSquared' found. Using it now."); Fawe.debug("Plugin 'PlotSquared' found. Using it now.");
} catch (Throwable e) {} } catch (Throwable e) {}
Fawe.this.worldedit = WorldEdit.getInstance(); Fawe.this.worldedit = WorldEdit.getInstance();
Fawe.this.setupEvents();
} }
}, 0); }, 0);
@ -298,10 +297,6 @@ public class Fawe {
return timer.getTPS(); return timer.getTPS();
} }
private void setupEvents() {
WorldEdit.getInstance().getEventBus().register(new WESubscriber());
}
private void setupCommands() { private void setupCommands() {
this.IMP.setupCommand("wea", new Wea()); this.IMP.setupCommand("wea", new Wea());
this.IMP.setupCommand("select", new WorldEditRegion()); this.IMP.setupCommand("select", new WorldEditRegion());
@ -417,6 +412,7 @@ public class Fawe {
BlockWorldVector.inject(); // Optimizations BlockWorldVector.inject(); // Optimizations
BlockVector.inject(); // Optimizations BlockVector.inject(); // Optimizations
Vector.inject(); // Optimizations Vector.inject(); // Optimizations
Vector2D.inject(); // Optimizations
// Pattern // Pattern
Patterns.inject(); // Optimizations (reduce object creation) Patterns.inject(); // Optimizations (reduce object creation)
RandomPattern.inject(); // Optimizations RandomPattern.inject(); // Optimizations
@ -538,6 +534,11 @@ public class Fawe {
ne.addNotificationListener(new NotificationListener() { ne.addNotificationListener(new NotificationListener() {
@Override @Override
public void handleNotification(final Notification notification, final Object handback) { public void handleNotification(final Notification notification, final Object handback) {
final long heapSize = Runtime.getRuntime().totalMemory();
final long heapMaxSize = Runtime.getRuntime().maxMemory();
if (heapSize < heapMaxSize) {
return;
}
MemUtil.memoryLimitedTask(); MemUtil.memoryLimitedTask();
} }
}, null, null); }, null, null);

View File

@ -17,6 +17,7 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.CuboidClipboard; import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.awt.Color; import java.awt.Color;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -60,6 +61,11 @@ public class FaweCache {
*/ */
public final static byte[] CACHE_DATA = new byte[65535]; public final static byte[] CACHE_DATA = new byte[65535];
/**
* Immutable biome cache
*/
public final static BaseBiome[] CACHE_BIOME = new BaseBiome[256];
/** /**
* Immutable BaseBlock cache * Immutable BaseBlock cache
* [ combined ] => block * [ combined ] => block
@ -129,7 +135,19 @@ public class FaweCache {
return CACHE_COLOR[0]; return CACHE_COLOR[0];
} }
public static final BaseBiome getBiome(int id) {
return CACHE_BIOME[id];
}
static { 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 x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
for (int y = 0; y < 256; y++) { for (int y = 0; y < 256; y++) {

View File

@ -76,9 +76,11 @@ public enum BBC {
COMMAND_REGEN_1("Region regenerated.\nTip: Use a seed with /regen [biome] [seed]", "WorldEdit.Regen"), COMMAND_REGEN_1("Region regenerated.\nTip: Use a seed with /regen [biome] [seed]", "WorldEdit.Regen"),
COMMAND_REGEN_2("Region regenerated.", "WorldEdit.Regen"), COMMAND_REGEN_2("Region regenerated.", "WorldEdit.Regen"),
COMMAND_TREE("%s0 trees created.", "WorldEdit.Tree"), COMMAND_TREE("%s0 trees created.", "WorldEdit.Tree"),
COMMAND_PUMPKIN("%s0 pumpkin patches created.", "WorldEdit.Tree"),
COMMAND_FLORA("%s0 flora created.", "WorldEdit.Flora"), COMMAND_FLORA("%s0 flora created.", "WorldEdit.Flora"),
COMMAND_HISTORY_CLEAR("History cleared", "WorldEdit.History"), COMMAND_HISTORY_CLEAR("History cleared", "WorldEdit.History"),
COMMAND_REDO_ERROR("Nothing left to redo. (See also `/inspect` and `/frb`)", "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_REDO_SUCCESS("Redo successful.", "WorldEdit.History"),
COMMAND_UNDO_ERROR("Nothing left to undo. (See also `/inspect` and `/frb`)", "WorldEdit.History"), COMMAND_UNDO_ERROR("Nothing left to undo. (See also `/inspect` and `/frb`)", "WorldEdit.History"),
COMMAND_UNDO_SUCCESS("Undo successful.", "WorldEdit.History"), COMMAND_UNDO_SUCCESS("Undo successful.", "WorldEdit.History"),
@ -133,6 +135,7 @@ public enum BBC {
BRUSH_TRANSFORM("Brush transform set", "WorldEdit.Brush"), BRUSH_TRANSFORM("Brush transform set", "WorldEdit.Brush"),
BRUSH_MATERIAL("Brush material set", "WorldEdit.Brush"), BRUSH_MATERIAL("Brush material set", "WorldEdit.Brush"),
ROLLBACK_ELEMENT("Undoing %s0", "WorldEdit.Rollback"), ROLLBACK_ELEMENT("Undoing %s0", "WorldEdit.Rollback"),
TOOL_INSPECT("Inspect tool bound to %s0.", "WorldEdit.Tool"), 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_REPL("Block replacer tool bound to %s0.", "WorldEdit.Tool"),
TOOL_CYCLER("Block data cycler 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("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_DELTREE("Floating tree remover tool bound to %s0.", "WorldEdit.Tool"),
TOOL_FARWAND("Far wand 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_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"), TOOL_LRBUILD_INFO("Left-click set to %s0; right-click set to %s1.", "WorldEdit.Tool"),
SUPERPICKAXE_ENABLED("Super Pickaxe enabled.", "WorldEdit.Tool"), SUPERPICKAXE_ENABLED("Super Pickaxe enabled.", "WorldEdit.Tool"),
SUPERPICKAXE_DISABLED("Super Pickaxe disabled.", "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"), 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"), SCHEMATIC_LIST("Available schematics (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"),
CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"), CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"),
CLIPBOARD_INVALID_FORMAT("Unknown clipboard format: %s0", "WorldEdit.Clipboard"),
VISITOR_BLOCK("%s0 blocks affected", "WorldEdit.Visitor"), VISITOR_BLOCK("%s0 blocks affected", "WorldEdit.Visitor"),
VISITOR_ENTITY("%s0 entities 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_CUBOID_POS2("pos2 set to %s0 %s1.", "WorldEdit.Selector"),
SELECTOR_INVALID_COORDINATES("Invalid coordinates %s0", "WorldEdit.Selector"), SELECTOR_INVALID_COORDINATES("Invalid coordinates %s0", "WorldEdit.Selector"),
SELECTOR_ALREADY_SET("Position already set.", "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"), 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"), WHOOSH("Whoosh!", "Navigation"),
POOF("Poof!", "Navigation"), POOF("Poof!", "Navigation"),
THRU_FAIL("No free spot ahead of you found.", "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"), UP_FAIL("You would hit something above you.", "Navigation"),
SEL_CUBOID("Cuboid: left click for point 1, right click for point 2", "Selection"), SEL_CUBOID("Cuboid: left click for point 1, right click for point 2", "Selection"),

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.configuration.MemorySection; import com.boydti.fawe.configuration.MemorySection;
import com.boydti.fawe.configuration.file.YamlConfiguration; import com.boydti.fawe.configuration.file.YamlConfiguration;
import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.StringMan;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
@ -22,6 +23,10 @@ import java.util.Map;
public class Config { public class Config {
public Config() {
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0);
}
/** /**
* Get the value for a node<br> * Get the value for a node<br>
* Probably throws some error if you try to get a non existent key * 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"; 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 { try {
String CTRF = System.lineSeparator(); String CTRF = System.lineSeparator();
String spacing = StringMan.repeat(" ", indent); String spacing = StringMan.repeat(" ", indent);

View File

@ -18,13 +18,13 @@ public class Settings extends Config {
@Final @Final
public final String WIKI = "https://github.com/boy0001/FastAsyncWorldedit/wiki/"; public final String WIKI = "https://github.com/boy0001/FastAsyncWorldedit/wiki/";
@Final @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 @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 @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 @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") @Comment("Allow the plugin to update")
public boolean UPDATE = true; public boolean UPDATE = true;
@ -46,23 +46,23 @@ public class Settings extends Config {
public int MAX_MEMORY_PERCENT = 95; public int MAX_MEMORY_PERCENT = 95;
@Create @Create
public CLIPBOARD CLIPBOARD = null; public CLIPBOARD CLIPBOARD;
@Create @Create
public LIGHTING LIGHTING = null; public LIGHTING LIGHTING;
@Create @Create
public TICK_LIMITER TICK_LIMITER = null; public TICK_LIMITER TICK_LIMITER;
@Create @Create
public WEB WEB = null; public WEB WEB;
@Create @Create
public EXTENT EXTENT = null; public EXTENT EXTENT;
@Create @Create
public EXPERIMENTAL EXPERIMENTAL = null; public EXPERIMENTAL EXPERIMENTAL;
@Create @Create
public QUEUE QUEUE = null; public QUEUE QUEUE;
@Create @Create
public HISTORY HISTORY = null; public HISTORY HISTORY;
@Create @Create
public PATHS PATHS = null; public PATHS PATHS;
@Comment("Paths for various directories") @Comment("Paths for various directories")
public static final class PATHS { public static final class PATHS {
@ -72,7 +72,7 @@ public class Settings extends Config {
@Create // This value will be generated automatically @Create // This value will be generated automatically
public ConfigBlock<LIMITS> LIMITS = null; public ConfigBlock<LIMITS> LIMITS;
@Comment({ @Comment({
"The \"default\" limit group affects those without a specific limit permission.", "The \"default\" limit group affects those without a specific limit permission.",
@ -208,7 +208,7 @@ public class Settings extends Config {
public static class QUEUE { public static class QUEUE {
@Create @Create
public static PROGRESS PROGRESS = null; public static PROGRESS PROGRESS;
@Comment({ @Comment({
"If no blocks from completed edits are queued, and if the global queue has more available ", "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", "chunks to place from still-processing edits than the target size setting, it will begin",

View File

@ -5,7 +5,6 @@ import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -19,7 +18,7 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
public final short[] air; public final short[] air;
public final byte[] heightMap; public final byte[] heightMap;
public int[][] biomes; public byte[] biomes;
public HashMap<Short, CompoundTag> tiles; public HashMap<Short, CompoundTag> tiles;
public HashSet<CompoundTag> entities; public HashSet<CompoundTag> entities;
public HashSet<UUID> entityRemoves; public HashSet<UUID> entityRemoves;
@ -121,7 +120,8 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
return this.ids; return this.ids;
} }
public int[][] getBiomeArray() { @Override
public byte[] getBiomeArray() {
return this.biomes; return this.biomes;
} }
@ -342,15 +342,11 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
} }
@Override @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) { if (this.biomes == null) {
this.biomes = new int[16][]; this.biomes = new byte[256];
} }
int[] index = this.biomes[x]; biomes[((z & 15) << 4) + (x & 15)] = biome;
if (index == null) {
index = this.biomes[x] = new int[16];
}
index[z] = biome.getId();
} }
@Override @Override

View File

@ -5,11 +5,11 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.SetQueue;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorCompletionService;
public class DefaultFaweQueueMap implements IFaweQueueMap { public class DefaultFaweQueueMap implements IFaweQueueMap {
@ -20,12 +20,14 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
this.parent = parent; this.parent = parent;
} }
/** public final Long2ObjectOpenHashMap<FaweChunk> blocks = new Long2ObjectOpenHashMap<FaweChunk>() {
* Map of chunks in the queue
*/
public final ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<Long, FaweChunk>(8, 0.9f, 1) {
@Override @Override
public FaweChunk put(Long key, FaweChunk value) { public FaweChunk put(Long key, FaweChunk value) {
return put((long) key, value);
}
@Override
public FaweChunk put(long key, FaweChunk value) {
if (parent.getProgressTask() != null) { if (parent.getProgressTask() != null) {
try { try {
parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1); parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1);
@ -33,8 +35,10 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
e.printStackTrace(); e.printStackTrace();
} }
} }
synchronized (this) {
return super.put(key, value); return super.put(key, value);
} }
}
}; };
@Override @Override
@ -109,6 +113,7 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
@Override @Override
public boolean next(int amount, ExecutorCompletionService pool, long time) { public boolean next(int amount, ExecutorCompletionService pool, long time) {
synchronized (blocks) {
try { try {
boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE;
int added = 0; int added = 0;
@ -172,4 +177,5 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
} }
return !blocks.isEmpty(); return !blocks.isEmpty();
} }
}
} }

View File

@ -21,17 +21,36 @@ import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue { public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> extends FaweQueue {
private WORLD impWorld; private WORLD impWorld;
private IFaweQueueMap map; 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<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
{
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) { public MappedFaweQueue(final World world) {
this(world, null); this(world, null);
} }
@ -102,21 +121,18 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
public abstract WORLD getImpWorld(); 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); public abstract boolean regenerateChunk(WORLD world, int x, int z, BaseBiome biome, Long seed);
@Override @Override
public abstract FaweChunk getFaweChunk(int x, int z); 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 abstract CHUNKSECTIONS getCachedSections(WORLD world, int cx, int cz);
public boolean isChunkLoaded(int x, int z) {
return isChunkLoaded(getWorld(), x, z); public abstract CHUNK getCachedChunk(WORLD world, int cx, int cz);
};
public WORLD getWorld() { public WORLD getWorld() {
if (impWorld != null) { if (impWorld != null) {
@ -233,16 +249,12 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
@Override @Override
public int size() { public int size() {
int size = map.size(); int size = map.size();
if (size == 0 && getStage() != SetQueue.QueueStage.INACTIVE) { if (size == 0 && getStage() == SetQueue.QueueStage.NONE) {
runTasks(); runTasks();
} }
return size; return size;
} }
private ConcurrentLinkedDeque<FaweChunk> toUpdate = new ConcurrentLinkedDeque<>();
private int dispatched = 0;
@Override @Override
public void clear() { public void clear() {
map.clear(); map.clear();
@ -254,66 +266,78 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
map.add(chunk); map.add(chunk);
} }
public int lastChunkX = Integer.MIN_VALUE; public SECTION getCachedSection(CHUNKSECTIONS chunk, int cy) {
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) {
return (SECTION) lastChunkSections; return (SECTION) lastChunkSections;
} }
public abstract int getCombinedId4Data(SECTION section, int x, int y, int z); public abstract int getCombinedId4Data(SECTION section, int x, int y, int z);
public final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() { public abstract int getBiome(CHUNK chunk, int x, int z);
@Override
public void run(IntegerPair coord) { public abstract CompoundTag getTileEntity(CHUNK chunk, int x, int y, int z);
loadChunk(getWorld(), coord.x, coord.z, true);
// 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;
} }
};
long average = 0;
public boolean ensureChunkLoaded(int cx, int cz) throws FaweException.FaweChunkLoadException {
if (!isChunkLoaded(cx, cz)) {
boolean sync = Thread.currentThread() == Fawe.get().getMainThread(); boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
if (sync) { if (sync) {
loadChunk(getWorld(), cx, cz, true); return loadChunk(getWorld(), cx, cz, true);
} else if (Settings.IMP.HISTORY.CHUNK_WAIT_MS > 0) { } else if (Settings.IMP.HISTORY.CHUNK_WAIT_MS > 0) {
loadChunk.value = new IntegerPair(cx, cz); cachedLoadChunk = null;
loadChunk.value.x = cx;
loadChunk.value.z = cz;
TaskManager.IMP.syncWhenFree(loadChunk, Settings.IMP.HISTORY.CHUNK_WAIT_MS); TaskManager.IMP.syncWhenFree(loadChunk, Settings.IMP.HISTORY.CHUNK_WAIT_MS);
if (!isChunkLoaded(cx, cz)) { return cachedLoadChunk;
throw new FaweException.FaweChunkLoadException();
}
} else { } else {
return false; return null;
} }
} }
return true;
}
@Override @Override
public boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException { public boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return false; return false;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return false; return false;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return false; return false;
} }
@ -368,21 +392,24 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return 0; return 0;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return 0; return 0;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return 0; return 0;
} }
@ -394,24 +421,38 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (y >= FaweChunk.HEIGHT) { if (cx != lastSectionX || cz != lastSectionZ) {
return 15; lastSectionX = cx;
} lastSectionZ = cz;
if (cx != lastChunkX || cz != lastChunkZ) { lastChunk = ensureChunkLoaded(cx, cz);
lastChunkX = cx; if (lastChunk != null) {
lastChunkZ = cz; lastChunkSections = getSections(lastChunk);
if (!ensureChunkLoaded(cx, cz)) { lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return 0; return 0;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) { return 0;
return getSkyLight(x, y + 16, z);
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { 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(x, y + 16, z);
} }
return getSkyLight(lastSection, x, y, z); return getSkyLight(lastSection, x, y, z);
@ -422,19 +463,23 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return 0; return 0;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return 0; return 0;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return 0; return 0;
@ -447,21 +492,24 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return 0; return 0;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return 0; return 0;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return 0; return 0;
} }
@ -473,21 +521,24 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return 0; return 0;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return 0; return 0;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return 0; return 0;
} }
@ -499,21 +550,24 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return 0; return 0;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return 0; return 0;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return 0; return 0;
} }
@ -537,24 +591,69 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return 0; return 0;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return 0; return 0;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return 0; return 0;
} }
return getCombinedId4Data(lastSection, x, y, z); 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);
}
} }

View File

@ -3,17 +3,15 @@ package com.boydti.fawe.example;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> extends MappedFaweQueue<WORLD, CHUNKSECTION, SECTION> { public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> extends MappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> {
private final int maxY; private final int maxY;
@ -60,10 +58,13 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
@Override @Override
public void end(FaweChunk chunk) { public void end(FaweChunk chunk) {
super.end(chunk); super.end(chunk);
if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) { if (Settings.IMP.LIGHTING.MODE == 0) {
sendChunk(chunk); sendChunk(chunk);
return; return;
} }
if (!Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
sendChunk(chunk);
}
if (Settings.IMP.LIGHTING.MODE == 2) { if (Settings.IMP.LIGHTING.MODE == 2) {
relighter.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask()); relighter.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask());
return; return;
@ -90,7 +91,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
} }
if (relight) { if (relight) {
relighter.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask()); relighter.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask());
} else { } else if (Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
sendChunk(chunk); sendChunk(chunk);
} }
} }
@ -148,19 +149,23 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return; return;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return; return;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return; return;
@ -172,19 +177,23 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
int cx = x >> 4; int cx = x >> 4;
int cz = z >> 4; int cz = z >> 4;
int cy = y >> 4; int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) { if (cx != lastSectionX || cz != lastSectionZ) {
lastChunkX = cx; lastSectionX = cx;
lastChunkZ = cz; lastSectionZ = cz;
if (!ensureChunkLoaded(cx, cz)) { lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return; return;
} }
lastChunkSections = getCachedSections(getWorld(), cx, cz); } else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy); lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) { } else {
if (lastChunkSections == null) {
return; return;
} }
lastSection = getCachedSection(lastChunkSections, cy);
} }
if (lastSection == null) { if (lastSection == null) {
return; return;
@ -199,24 +208,4 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
public abstract void refreshChunk(FaweChunk fs); public abstract void refreshChunk(FaweChunk fs);
public abstract CharFaweChunk getPrevious(CharFaweChunk fs, CHUNKSECTION sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception; public abstract CharFaweChunk getPrevious(CharFaweChunk fs, CHUNKSECTION sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> 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);
}
} }

View File

@ -5,6 +5,8 @@ import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.IntegerTrio; import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.util.MathMan; 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.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -14,15 +16,14 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
public class NMSRelighter implements Relighter{ public class NMSRelighter implements Relighter{
private final NMSMappedFaweQueue queue; private final NMSMappedFaweQueue queue;
private final Map<Long, RelightSkyEntry> skyToRelight; private final Map<Long, RelightSkyEntry> skyToRelight;
private final Map<Long, Map<Short, Object>> lightQueue; private final Map<Long, Map<Integer, Object>> lightQueue;
private final Object present = new Object(); private final Object present = new Object();
private final HashMap<Long, Integer> chunksToSend; private final Map<Long, Integer> chunksToSend;
private final int maxY; private final int maxY;
private volatile boolean relighting = false; private volatile boolean relighting = false;
@ -33,9 +34,9 @@ public class NMSRelighter implements Relighter{
public NMSRelighter(NMSMappedFaweQueue queue) { public NMSRelighter(NMSMappedFaweQueue queue) {
this.queue = queue; this.queue = queue;
this.skyToRelight = new ConcurrentHashMap<>(); this.skyToRelight = new Long2ObjectOpenHashMap<>();
this.lightQueue = new ConcurrentHashMap<>(); this.lightQueue = new Long2ObjectOpenHashMap<>();
chunksToSend = new HashMap<>(); this.chunksToSend = new Long2ObjectOpenHashMap<>();
this.maxY = queue.getMaxY(); this.maxY = queue.getMaxY();
} }
@ -63,7 +64,6 @@ public class NMSRelighter implements Relighter{
Iterator<Map.Entry<Long, RelightSkyEntry>> iter = skyToRelight.entrySet().iterator(); Iterator<Map.Entry<Long, RelightSkyEntry>> iter = skyToRelight.entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
Map.Entry<Long, RelightSkyEntry> entry = iter.next(); Map.Entry<Long, RelightSkyEntry> entry = iter.next();
iter.remove();
RelightSkyEntry chunk = entry.getValue(); RelightSkyEntry chunk = entry.getValue();
long pair = entry.getKey(); long pair = entry.getKey();
Integer existing = chunksToSend.get(pair); Integer existing = chunksToSend.get(pair);
@ -71,10 +71,11 @@ public class NMSRelighter implements Relighter{
queue.ensureChunkLoaded(chunk.x, chunk.z); queue.ensureChunkLoaded(chunk.x, chunk.z);
Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z); Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z);
queue.removeLighting(sections, FaweQueue.RelightMode.ALL, queue.hasSky()); queue.removeLighting(sections, FaweQueue.RelightMode.ALL, queue.hasSky());
iter.remove();
} }
} }
public void updateBlockLight(Map<Long, Map<Short, Object>> map) { public void updateBlockLight(Map<Long, Map<Integer, Object>> map) {
int size = map.size(); int size = map.size();
if (size == 0) { if (size == 0) {
return; return;
@ -84,17 +85,16 @@ public class NMSRelighter implements Relighter{
Map<IntegerTrio, Object> visited = new HashMap<>(); Map<IntegerTrio, Object> visited = new HashMap<>();
Map<IntegerTrio, Object> removalVisited = new HashMap<>(); Map<IntegerTrio, Object> removalVisited = new HashMap<>();
Iterator<Map.Entry<Long, Map<Short, Object>>> iter = map.entrySet().iterator(); Iterator<Map.Entry<Long, Map<Integer, Object>>> iter = map.entrySet().iterator();
while (iter.hasNext() && size-- > 0) { while (iter.hasNext() && size-- > 0) {
Map.Entry<Long, Map<Short, Object>> entry = iter.next(); Map.Entry<Long, Map<Integer, Object>> entry = iter.next();
iter.remove();
long index = entry.getKey(); long index = entry.getKey();
Map<Short, Object> blocks = entry.getValue(); Map<Integer, Object> blocks = entry.getValue();
int chunkX = MathMan.unpairIntX(index); int chunkX = MathMan.unpairIntX(index);
int chunkZ = MathMan.unpairIntY(index); int chunkZ = MathMan.unpairIntY(index);
int bx = chunkX << 4; int bx = chunkX << 4;
int bz = chunkZ << 4; int bz = chunkZ << 4;
for (short blockHash : blocks.keySet()) { for (int blockHash : blocks.keySet()) {
int x = (blockHash >> 12 & 0xF) + bx; int x = (blockHash >> 12 & 0xF) + bx;
int y = (blockHash & 0xFF); int y = (blockHash & 0xFF);
int z = (blockHash >> 8 & 0xF) + bz; int z = (blockHash >> 8 & 0xF) + bz;
@ -114,6 +114,7 @@ public class NMSRelighter implements Relighter{
} }
} }
} }
iter.remove();
} }
while (!lightRemovalQueue.isEmpty()) { while (!lightRemovalQueue.isEmpty()) {
@ -192,12 +193,12 @@ public class NMSRelighter implements Relighter{
public void addLightUpdate(int x, int y, int z) { public void addLightUpdate(int x, int y, int z) {
long index = MathMan.pairInt((int) x >> 4, (int) z >> 4); long index = MathMan.pairInt((int) x >> 4, (int) z >> 4);
Map<Short, Object> currentMap = lightQueue.get(index); Map<Integer, Object> currentMap = lightQueue.get(index);
if (currentMap == null) { if (currentMap == null) {
currentMap = new ConcurrentHashMap<>(8, 0.9f, 1); currentMap = new Int2ObjectOpenHashMap<>();
this.lightQueue.put(index, currentMap); 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) { public synchronized void fixLightingSafe(boolean sky) {
@ -222,10 +223,10 @@ public class NMSRelighter implements Relighter{
Map.Entry<Long, Integer> entry = iter.next(); Map.Entry<Long, Integer> entry = iter.next();
long pair = entry.getKey(); long pair = entry.getKey();
int bitMask = entry.getValue(); int bitMask = entry.getValue();
iter.remove();
int x = MathMan.unpairIntX(pair); int x = MathMan.unpairIntX(pair);
int z = MathMan.unpairIntY(pair); int z = MathMan.unpairIntY(pair);
queue.sendChunk(x, z, bitMask); queue.sendChunk(x, z, bitMask);
iter.remove();
} }
} }
@ -239,9 +240,9 @@ public class NMSRelighter implements Relighter{
Iterator<Map.Entry<Long, RelightSkyEntry>> iter = skyToRelight.entrySet().iterator(); Iterator<Map.Entry<Long, RelightSkyEntry>> iter = skyToRelight.entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
Map.Entry<Long, RelightSkyEntry> entry = iter.next(); Map.Entry<Long, RelightSkyEntry> entry = iter.next();
iter.remove();
chunksToSend.put(entry.getKey(), entry.getValue().bitmask); chunksToSend.put(entry.getKey(), entry.getValue().bitmask);
chunksList.add(entry.getValue()); chunksList.add(entry.getValue());
iter.remove();
} }
Collections.sort(chunksList); Collections.sort(chunksList);
int size = chunksList.size(); int size = chunksList.size();
@ -312,7 +313,6 @@ public class NMSRelighter implements Relighter{
int brightness = MathMan.unpair16y(pair); int brightness = MathMan.unpair16y(pair);
if (brightness > 1 && (brightness != 15 || opacity != 15)) { if (brightness > 1 && (brightness != 15 || opacity != 15)) {
addLightUpdate(bx + x, y, bz + z); addLightUpdate(bx + x, y, bz + z);
// lightBlock(bx + x, y, bz + z, brightness);
} }
switch (value) { switch (value) {
case 0: case 0:

View File

@ -11,6 +11,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class NullFaweChunk extends FaweChunk<Void> { public class NullFaweChunk extends FaweChunk<Void> {
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. * 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<Void> {
return null; return null;
} }
@Override
public byte[] getBiomeArray() {
return new byte[256];
}
@Override @Override
public int getBitMask() { public int getBitMask() {
return 0; return 0;
@ -92,6 +98,11 @@ public class NullFaweChunk extends FaweChunk<Void> {
} }
@Override
public void setBiome(int x, int z, byte biome) {
}
@Override @Override
public FaweChunk<Void> copy(boolean shallow) { public FaweChunk<Void> copy(boolean shallow) {
return this; return this;

View File

@ -6,13 +6,13 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.SetQueue;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.lang.ref.Reference; import java.lang.ref.Reference;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorCompletionService;
public class WeakFaweQueueMap implements IFaweQueueMap { public class WeakFaweQueueMap implements IFaweQueueMap {
@ -23,12 +23,14 @@ public class WeakFaweQueueMap implements IFaweQueueMap {
this.parent = parent; this.parent = parent;
} }
/** public final Long2ObjectOpenHashMap<Reference<FaweChunk>> blocks = new Long2ObjectOpenHashMap<Reference<FaweChunk>>() {
* Map of chunks in the queue
*/
public ConcurrentHashMap<Long, Reference<FaweChunk>> blocks = new ConcurrentHashMap<Long, Reference<FaweChunk>>(8, 0.9f, 1) {
@Override @Override
public Reference<FaweChunk> put(Long key, Reference<FaweChunk> value) { public Reference<FaweChunk> put(Long key, Reference<FaweChunk> value) {
return put((long) key, value);
}
@Override
public Reference<FaweChunk> put(long key, Reference<FaweChunk> value) {
if (parent.getProgressTask() != null) { if (parent.getProgressTask() != null) {
try { try {
parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1); parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1);
@ -36,8 +38,10 @@ public class WeakFaweQueueMap implements IFaweQueueMap {
e.printStackTrace(); e.printStackTrace();
} }
} }
synchronized (this) {
return super.put(key, value); return super.put(key, value);
} }
}
}; };
@Override @Override
@ -142,6 +146,7 @@ public class WeakFaweQueueMap implements IFaweQueueMap {
@Override @Override
public boolean next(int amount, ExecutorCompletionService pool, long time) { public boolean next(int amount, ExecutorCompletionService pool, long time) {
synchronized (blocks) {
try { try {
boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE; boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE;
int added = 0; int added = 0;
@ -172,23 +177,21 @@ public class WeakFaweQueueMap implements IFaweQueueMap {
} }
boolean result = true; boolean result = true;
// amount = 8; // amount = 8;
for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) { for (int i = 0; i < amount && (result = iter.hasNext());) {
Map.Entry<Long, Reference<FaweChunk>> item = iter.next(); Map.Entry<Long, Reference<FaweChunk>> item = iter.next();
Reference<FaweChunk> chunkReference = item.getValue(); Reference<FaweChunk> chunkReference = item.getValue();
FaweChunk chunk = chunkReference.get(); FaweChunk chunk = chunkReference.get();
if (skip && chunk == lastWrappedChunk) { if (skip && chunk == lastWrappedChunk) {
i--;
added--;
continue; continue;
} }
iter.remove(); iter.remove();
if (chunk != null) { if (chunk != null) {
parent.start(chunk); parent.start(chunk);
pool.submit(chunk); pool.submit(chunk);
added++;
i++;
} else { } else {
Fawe.debug("Skipped modifying chunk due to low memory (4)"); Fawe.debug("Skipped modifying chunk due to low memory (4)");
i--;
added--;
} }
} }
// if result, then submitted = amount // if result, then submitted = amount
@ -221,4 +224,5 @@ public class WeakFaweQueueMap implements IFaweQueueMap {
} }
return !blocks.isEmpty(); return !blocks.isEmpty();
} }
}
} }

View File

@ -10,7 +10,6 @@ import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -241,9 +240,9 @@ public class MCAChunk extends FaweChunk<Void> {
} }
@Override @Override
public void setBiome(int x, int z, BaseBiome biome) { public void setBiome(int x, int z, byte biome) {
modified = true; modified = true;
biomes[x + (z << 4)] = (byte) biome.getId();; biomes[x + (z << 4)] = biome;
} }
@Override @Override
@ -292,6 +291,11 @@ public class MCAChunk extends FaweChunk<Void> {
return id << 4; return id << 4;
} }
@Override
public byte[] getBiomeArray() {
return this.biomes;
}
@Override @Override
public Set<UUID> getEntityRemoves() { public Set<UUID> getEntityRemoves() {
return new HashSet<>(); return new HashSet<>();

View File

@ -41,6 +41,32 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
this.hasSky = hasSky; this.hasSky = hasSky;
} }
@Override
public FaweChunk loadChunk(FaweQueue faweQueue, int x, int z, boolean generate) {
return getFaweChunk(x, z);
}
@Override
public FaweChunk getSections(FaweChunk faweChunk) {
return faweChunk;
}
@Override
public FaweChunk getCachedChunk(FaweQueue faweQueue, int cx, int cz) {
return getFaweChunk(cx, cz);
}
@Override
public int getBiome(FaweChunk faweChunk, int x, int z) {
if (faweChunk instanceof MCAChunk) {
return ((MCAChunk) faweChunk).getBiomeArray()[((z & 0xF) << 4 | x & 0xF)];
} else if (parent != null){
return parent.getBiomeId(x, z);
} else {
return 0;
}
}
public void filterWorld(final MCAFilter filter) { public void filterWorld(final MCAFilter filter) {
File folder = getSaveFolder(); File folder = getSaveFolder();
final ForkJoinPool pool = new ForkJoinPool(); final ForkJoinPool pool = new ForkJoinPool();
@ -154,11 +180,6 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
throw new UnsupportedOperationException("Not supported"); throw new UnsupportedOperationException("Not supported");
} }
@Override
public MCAChunk getChunk(FaweQueue faweQueue, int x, int z) {
return (MCAChunk) getFaweChunk(x, z);
}
@Override @Override
public FaweQueue getImpWorld() { public FaweQueue getImpWorld() {
return parent; return parent;
@ -254,11 +275,6 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
} }
} }
@Override
public boolean isChunkLoaded(FaweQueue faweQueue, int x, int z) {
return true;
}
@Override @Override
public FaweChunk getFaweChunk(int cx, int cz) { public FaweChunk getFaweChunk(int cx, int cz) {
return getFaweQueueMap().getFaweChunk(cx, cz); return getFaweQueueMap().getFaweChunk(cx, cz);
@ -274,11 +290,6 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
return hasSky; return hasSky;
} }
@Override
public boolean loadChunk(FaweQueue faweQueue, int x, int z, boolean generate) {
return true;
}
@Override @Override
public MCAChunk getCachedSections(FaweQueue faweQueue, int cx, int cz) { public MCAChunk getCachedSections(FaweQueue faweQueue, int cx, int cz) {
return (MCAChunk) getFaweQueueMap().getFaweChunk(cx, cz); return (MCAChunk) getFaweQueueMap().getFaweChunk(cx, cz);

View File

@ -41,8 +41,14 @@ public class ChangeSetFaweQueue extends DelegateFaweQueue {
@Override @Override
public boolean setBiome(int x, int z, BaseBiome biome) { public boolean setBiome(int x, int z, BaseBiome biome) {
// TODO undo biome change if (super.setBiome(x, z, biome)) {
return super.setBiome(x, z, biome); int oldBiome = getParent().getBiomeId(x, z);
if (oldBiome != biome.getId()) {
set.addBiomeChange(x, z, FaweCache.getBiome(oldBiome), biome);
return true;
}
}
return false;
} }
@Override @Override

View File

@ -144,6 +144,8 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
return ids; return ids;
} }
public abstract byte[] getBiomeArray();
public char[][] getCombinedIdArrays() { public char[][] getCombinedIdArrays() {
char[][] ids = new char[HEIGHT >> 4][]; char[][] ids = new char[HEIGHT >> 4][];
for (int y = 0; y < HEIGHT >> 4; y++) { for (int y = 0; y < HEIGHT >> 4; y++) {
@ -272,7 +274,11 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
*/ */
public abstract CompoundTag getTile(int x, int y, int z); 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<br> * Spend time now so that the chunk can be more efficiently dispatched later<br>

View File

@ -281,8 +281,6 @@ public abstract class FaweQueue {
} }
} }
public abstract boolean isChunkLoaded(final int x, final int z);
@Deprecated @Deprecated
public boolean regenerateChunk(int x, int z) { public boolean regenerateChunk(int x, int z) {
return regenerateChunk(x, z, null, null); return regenerateChunk(x, z, null, null);
@ -349,6 +347,8 @@ public abstract class FaweQueue {
return getCombinedId4Data(x, y, z) != 0; 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 getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
public abstract int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException; public abstract int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity; 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.history.changeset.ChangeSet;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -133,6 +135,17 @@ public class HistoryExtent extends AbstractDelegateExtent {
return newList; 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 class TrackedEntity implements Entity {
private final Entity entity; private final Entity entity;

View File

@ -5,6 +5,7 @@ import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; 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 @Override
public void addChangeTask(FaweQueue queue) { public void addChangeTask(FaweQueue queue) {

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.extent.ResettableExtent;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
@ -176,7 +177,7 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool {
target = player.getBlockTrace(getRange(), true); target = player.getBlockTrace(getRange(), true);
if (target == null) { if (target == null) {
player.printError("No block in sight!"); BBC.NO_BLOCK.send(player);
return true; return true;
} }
@ -216,7 +217,7 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool {
try { try {
brush.build(action, editSession, target, material, size); brush.build(action, editSession, target, material, size);
} catch (MaxChangedBlocksException e) { } catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached."); player.printError("Max blocks change limit reached."); // Never happens
} finally { } finally {
if (bag != null) { if (bag != null) {
bag.flushChanges(); bag.flushChanges();

View File

@ -12,6 +12,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.Map; import java.util.Map;
public class ErodeBrush implements DoubleActionBrush { 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) { private void erosionIteration(int brushSize, int brushSizeSquared, int erodeFaces, FaweClipboard current, FaweClipboard target) {
Map<Integer, Integer> frequency = Maps.newHashMap(); Int2ObjectOpenHashMap<Integer> frequency = new Int2ObjectOpenHashMap<>();
for (int x = -brushSize; x <= brushSize; x++) { for (int x = -brushSize; x <= brushSize; x++) {
for (int y = -brushSize; y <= brushSize; y++) { for (int y = -brushSize; y <= brushSize; y++) {

View File

@ -42,12 +42,12 @@ public class HeightBrush implements DoubleActionBrush {
@Override @Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { 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(); Mask mask = tool.getMask();
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null; mask = null;
} }
heightMap.setSize(size); 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);
} }
} }

View File

@ -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);
}
}

View File

@ -12,6 +12,7 @@ import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.history.change.EntityCreate; import com.sk89q.worldedit.history.change.EntityCreate;
import com.sk89q.worldedit.history.change.EntityRemove; import com.sk89q.worldedit.history.change.EntityRemove;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Iterator; import java.util.Iterator;
public class AbstractDelegateChangeSet extends FaweChangeSet { public class AbstractDelegateChangeSet extends FaweChangeSet {
@ -71,6 +72,11 @@ public class AbstractDelegateChangeSet extends FaweChangeSet {
return parent.size(); return parent.size();
} }
@Override
public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) {
parent.addBiomeChange(x, z, from, to);
}
@Override @Override
public void addTileCreate(CompoundTag tag) { public void addTileCreate(CompoundTag tag) {
parent.addTileCreate(tag); parent.addTileCreate(tag);

View File

@ -8,6 +8,7 @@ import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -56,6 +57,11 @@ public class CPUOptimizedChangeSet extends FaweChangeSet {
throw new UnsupportedOperationException("Invalid mode"); throw new UnsupportedOperationException("Invalid mode");
} }
@Override
public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) {
throw new UnsupportedOperationException("Invalid mode");
}
@Override @Override
public void addTileCreate(CompoundTag tag) { public void addTileCreate(CompoundTag tag) {
throw new UnsupportedOperationException("Invalid mode"); throw new UnsupportedOperationException("Invalid mode");

View File

@ -13,13 +13,13 @@ import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -34,6 +34,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
private UUID uuid; private UUID uuid;
private File bdFile; private File bdFile;
private File bioFile;
private File nbtfFile; private File nbtfFile;
private File nbttFile; private File nbttFile;
private File entfFile; 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 } * { short rel x, short rel z, unsigned byte y, short combinedFrom, short combinedTo }
*/ */
private OutputStream osBD; private OutputStream osBD;
// biome
private OutputStream osBIO;
// NBT From // NBT From
private NBTOutputStream osNBTF; private NBTOutputStream osNBTF;
// NBT To // NBT To
@ -117,6 +120,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
entfFile = new File(folder, index + ".entf"); entfFile = new File(folder, index + ".entf");
enttFile = new File(folder, index + ".entt"); enttFile = new File(folder, index + ".entt");
bdFile = new File(folder, index + ".bd"); bdFile = new File(folder, index + ".bd");
bioFile = new File(folder, index + ".bio");
} }
private void init(UUID uuid, int i) { private void init(UUID uuid, int i) {
@ -165,12 +169,16 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
public boolean flush() { public boolean flush() {
super.flush(); super.flush();
synchronized (this) { 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 { try {
if (osBD != null) { if (osBD != null) {
osBD.close(); osBD.close();
osBD = null; osBD = null;
} }
if (osBIO != null) {
osBIO.close();
osBIO = null;
}
if (osNBTF != null) { if (osNBTF != null) {
osNBTF.close(); osNBTF.close();
osNBTF = null; osNBTF = null;
@ -210,6 +218,9 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
if (bdFile.exists()) { if (bdFile.exists()) {
total += bdFile.length(); total += bdFile.length();
} }
if (bioFile.exists()) {
total += bioFile.length();
}
if (nbtfFile.exists()) { if (nbtfFile.exists()) {
total += entfFile.length(); 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 @Override
public NBTOutputStream getEntityCreateOS() throws IOException { public NBTOutputStream getEntityCreateOS() throws IOException {
if (osENTCT != null) { if (osENTCT != null) {
@ -293,6 +317,15 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
return is; return is;
} }
@Override
public InputStream getBiomeIS() throws IOException {
if (!bioFile.exists()) {
return null;
}
InputStream is = MainUtil.getCompressedIS(new FileInputStream(bioFile));
return is;
}
@Override @Override
public NBTInputStream getEntityCreateIS() throws IOException { public NBTInputStream getEntityCreateIS() throws IOException {
if (!enttFile.exists()) { if (!enttFile.exists()) {
@ -426,25 +459,25 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
} }
} }
public HashMap<Integer, Integer> getBlocks() { public Map<Integer, Integer> getBlocks() {
HashMap<Integer, Integer> map = new HashMap<>(); Int2ObjectOpenHashMap<Integer> map = new Int2ObjectOpenHashMap<>();
for (int i = 0; i < blocks.length; i++) { for (int i = 0; i < blocks.length; i++) {
if (blocks[i] != 0) { if (blocks[i] != 0) {
map.put(i, blocks[i]); map.put(i, (Integer) blocks[i]);
} }
} }
return map; return map;
} }
public Map<Integer, Double> getPercents() { public Map<Integer, Double> getPercents() {
HashMap<Integer, Integer> map = getBlocks(); Map<Integer, Integer> map = getBlocks();
int count = getSize(); int count = getSize();
HashMap<Integer, Double> newMap = new HashMap<Integer, Double>(); Int2ObjectOpenHashMap<Double> newMap = new Int2ObjectOpenHashMap<Double>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) { for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int id = entry.getKey(); int id = entry.getKey();
int changes = entry.getValue(); int changes = entry.getValue();
double percent = ((changes * 1000l) / count) / 10d; double percent = ((changes * 1000l) / count) / 10d;
newMap.put(id, percent); newMap.put(id, (Double) percent);
} }
return newMap; return newMap;
} }

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.history.change.EntityCreate;
import com.sk89q.worldedit.history.change.EntityRemove; import com.sk89q.worldedit.history.change.EntityRemove;
import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -119,6 +120,7 @@ public abstract class FaweChangeSet implements ChangeSet {
public abstract void addTileRemove(CompoundTag tag); public abstract void addTileRemove(CompoundTag tag);
public abstract void addEntityRemove(CompoundTag tag); public abstract void addEntityRemove(CompoundTag tag);
public abstract void addEntityCreate(CompoundTag tag); public abstract void addEntityCreate(CompoundTag tag);
public abstract void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to);
public Iterator<Change> getIterator(BlockBag blockBag, int mode, boolean redo) { public Iterator<Change> getIterator(BlockBag blockBag, int mode, boolean redo) {
return getIterator(redo); return getIterator(redo);
} }
@ -227,15 +229,26 @@ public abstract class FaweChangeSet implements ChangeSet {
int cz = previous.getZ(); int cz = previous.getZ();
int bx = cx << 4; int bx = cx << 4;
int bz = cz << 4; int bz = cz << 4;
synchronized (FaweChangeSet.this) {
// Biome changes // 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 = bz + z;
for (int x = 0; x < 16; x++) {
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 // TODO
} }
// Block changes // 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++) { for (int layer = 0; layer < layers; layer++) {
char[] currentLayer = next.getIdArray(layer); char[] currentLayer = next.getIdArray(layer);
char[] previousLayer = previous.getIdArray(layer); char[] previousLayer = previous.getIdArray(layer);
@ -261,7 +274,6 @@ public abstract class FaweChangeSet implements ChangeSet {
default: default:
char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0; char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0;
if (combinedIdCurrent != combinedIdPrevious) { if (combinedIdCurrent != combinedIdPrevious) {
synchronized (FaweChangeSet.this) {
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent); add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
} }
} }
@ -269,37 +281,29 @@ public abstract class FaweChangeSet implements ChangeSet {
} }
} }
} }
}
// Tile changes // Tile changes
{ {
// Tiles created // Tiles created
Map<Short, CompoundTag> tiles = next.getTiles(); Map<Short, CompoundTag> tiles = next.getTiles();
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) { for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
synchronized (FaweChangeSet.this) {
addTileCreate(entry.getValue()); addTileCreate(entry.getValue());
} }
}
// Tiles removed // Tiles removed
tiles = previous.getTiles(); tiles = previous.getTiles();
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) { for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
synchronized (FaweChangeSet.this) {
addTileRemove(entry.getValue()); addTileRemove(entry.getValue());
} }
} }
}
// Entity changes // Entity changes
{ {
// Entities created // Entities created
Set<CompoundTag> entities = next.getEntities(); Set<CompoundTag> entities = next.getEntities();
for (CompoundTag entityTag : entities) { for (CompoundTag entityTag : entities) {
synchronized (FaweChangeSet.this) {
addEntityCreate(entityTag); addEntityCreate(entityTag);
} }
}
// Entities removed // Entities removed
entities = previous.getEntities(); entities = previous.getEntities();
for (CompoundTag entityTag : entities) { for (CompoundTag entityTag : entities) {
synchronized (FaweChangeSet.this) {
addEntityRemove(entityTag); addEntityRemove(entityTag);
} }
} }

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.object.changeset;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweInputStream; import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream; 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.MutableBlockChange;
import com.boydti.fawe.object.change.MutableEntityChange; import com.boydti.fawe.object.change.MutableEntityChange;
import com.boydti.fawe.object.change.MutableFullBlockChange; 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.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.NoSuchElementException;
public abstract class FaweStreamChangeSet extends FaweChangeSet { 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 getBlockOS(int x, int y, int z) throws IOException;
public abstract OutputStream getBiomeOS() throws IOException;
public abstract NBTOutputStream getEntityCreateOS() throws IOException; public abstract NBTOutputStream getEntityCreateOS() throws IOException;
public abstract NBTOutputStream getEntityRemoveOS() throws IOException; public abstract NBTOutputStream getEntityRemoveOS() throws IOException;
public abstract NBTOutputStream getTileCreateOS() throws IOException; public abstract NBTOutputStream getTileCreateOS() throws IOException;
public abstract NBTOutputStream getTileRemoveOS() throws IOException; public abstract NBTOutputStream getTileRemoveOS() throws IOException;
public abstract InputStream getBlockIS() throws IOException; public abstract InputStream getBlockIS() throws IOException;
public abstract InputStream getBiomeIS() throws IOException;
public abstract NBTInputStream getEntityCreateIS() throws IOException; public abstract NBTInputStream getEntityCreateIS() throws IOException;
public abstract NBTInputStream getEntityRemoveIS() throws IOException; public abstract NBTInputStream getEntityRemoveIS() throws IOException;
public abstract NBTInputStream getTileCreateIS() 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) { public void addTileCreate(CompoundTag tag) {
if (tag == null) { if (tag == null) {
return; return;
} }
blockSize++;
try { try {
NBTOutputStream nbtos = getTileCreateOS(); NBTOutputStream nbtos = getTileCreateOS();
nbtos.writeTag(tag); nbtos.writeTag(tag);
@ -328,6 +355,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
if (tag == null) { if (tag == null) {
return; return;
} }
blockSize++;
try { try {
NBTOutputStream nbtos = getTileRemoveOS(); NBTOutputStream nbtos = getTileRemoveOS();
nbtos.writeTag(tag); nbtos.writeTag(tag);
@ -340,6 +368,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
if (tag == null) { if (tag == null) {
return; return;
} }
blockSize++;
try { try {
NBTOutputStream nbtos = getEntityRemoveOS(); NBTOutputStream nbtos = getEntityRemoveOS();
nbtos.writeTag(tag); nbtos.writeTag(tag);
@ -352,6 +381,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
if (tag == null) { if (tag == null) {
return; return;
} }
blockSize++;
try { try {
NBTOutputStream nbtos = getEntityCreateOS(); NBTOutputStream nbtos = getEntityCreateOS();
nbtos.writeTag(tag); nbtos.writeTag(tag);
@ -376,32 +406,83 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
idDel.readCombined(is, change, dir); idDel.readCombined(is, change, dir);
return change; return change;
} catch (EOFException ignoreOEF) { } catch (EOFException ignoreOEF) {
return null;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
MainUtil.handleError(e); MainUtil.handleError(e);
} }
try {
is.close();
} catch (IOException e) {
MainUtil.handleError(e);
}
return null; return null;
} }
@Override @Override
public boolean hasNext() { public boolean hasNext() {
if (last != null) { return last != null || ((last = read()) != null);
return true; }
} else if ((last = read()) != null) {
return true; @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<MutableBiomeChange> getBiomeIterator(final boolean dir) throws IOException {
final InputStream is = getBiomeIS();
if (is == null) {
return new ArrayList<MutableBiomeChange>().iterator();
}
final MutableBiomeChange change = new MutableBiomeChange();
return new Iterator<MutableBiomeChange>() {
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 { try {
is.close(); is.close();
} catch (IOException e) { } catch (IOException e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
return false; return null;
} }
@Override @Override
public MutableBlockChange next() { public boolean hasNext() {
MutableBlockChange tmp = last; return last != null || ((last = read()) != null);
}
@Override
public MutableBiomeChange next() {
MutableBiomeChange tmp = last;
if (tmp == null) {
tmp = read();
}
last = null; last = null;
return tmp; return tmp;
} }
@ -441,8 +522,13 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
idDel.readCombined(is, change, dir); idDel.readCombined(is, change, dir);
return change; return change;
} catch (EOFException ignoreOEF) { } catch (EOFException ignoreOEF) {
return null;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
MainUtil.handleError(e);
}
try {
is.close();
} catch (IOException e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
return null; return null;
@ -450,23 +536,15 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
@Override @Override
public boolean hasNext() { public boolean hasNext() {
if (last == null) { return last != null || ((last = read()) != null);
last = read();
}
if (last != null) {
return true;
}
try {
is.close();
} catch (IOException e) {
MainUtil.handleError(e);
}
return false;
} }
@Override @Override
public MutableFullBlockChange next() { public MutableFullBlockChange next() {
MutableFullBlockChange tmp = last; MutableFullBlockChange tmp = last;
if (tmp == null) {
tmp = read();
}
last = null; last = null;
return tmp; return tmp;
} }
@ -485,36 +563,35 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
final MutableEntityChange change = new MutableEntityChange(null, create); final MutableEntityChange change = new MutableEntityChange(null, create);
try { try {
return new Iterator<MutableEntityChange>() { return new Iterator<MutableEntityChange>() {
private CompoundTag last = read(); private MutableEntityChange last = read();
public CompoundTag read() { public MutableEntityChange read() {
try { try {
return (CompoundTag) is.readTag(); CompoundTag tag = (CompoundTag) is.readTag();
} catch (Exception ignoreEOS) {} change.tag = tag;
return null; return change;
} } catch (Exception ignoreOEF) {}
@Override
public boolean hasNext() {
if (last == null) {
last = read();
}
if (last != null) {
return true;
}
try { try {
is.close(); is.close();
} catch (IOException e) { } catch (IOException e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
return false; return null;
}
@Override
public boolean hasNext() {
return last != null || ((last = read()) != null);
} }
@Override @Override
public MutableEntityChange next() { public MutableEntityChange next() {
change.tag = last; MutableEntityChange tmp = last;
if (tmp == null) {
tmp = read();
}
last = null; last = null;
return change; return tmp;
} }
@Override @Override
@ -535,36 +612,35 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
final MutableTileChange change = new MutableTileChange(null, create); final MutableTileChange change = new MutableTileChange(null, create);
try { try {
return new Iterator<MutableTileChange>() { return new Iterator<MutableTileChange>() {
private CompoundTag last = read(); private MutableTileChange last = read();
public CompoundTag read() { public MutableTileChange read() {
try { try {
return (CompoundTag) is.readTag(); CompoundTag tag = (CompoundTag) is.readTag();
} catch (Exception ignoreEOS) {} change.tag = tag;
return null; return change;
} } catch (Exception ignoreOEF) {}
@Override
public boolean hasNext() {
if (last == null) {
last = read();
}
if (last != null) {
return true;
}
try { try {
is.close(); is.close();
} catch (IOException e) { } catch (IOException e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
return false; return null;
}
@Override
public boolean hasNext() {
return last != null || ((last = read()) != null);
} }
@Override @Override
public MutableTileChange next() { public MutableTileChange next() {
change.tag = last; MutableTileChange tmp = last;
if (tmp == null) {
tmp = read();
}
last = null; last = null;
return change; return tmp;
} }
@Override @Override
@ -589,8 +665,10 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
final Iterator<MutableBlockChange> blockChange = getBlockIterator(dir); final Iterator<MutableBlockChange> blockChange = getBlockIterator(dir);
final Iterator<MutableBiomeChange> biomeChange = getBiomeIterator(dir);
return new Iterator<Change>() { return new Iterator<Change>() {
Iterator<Change>[] iterators = new Iterator[]{tileCreate, tileRemove, entityCreate, entityRemove, blockChange}; Iterator<Change>[] iterators = new Iterator[]{tileCreate, tileRemove, entityCreate, entityRemove, blockChange, biomeChange};
int i = 0; int i = 0;
Iterator<Change> current = iterators[0]; Iterator<Change> current = iterators[0];
@ -613,7 +691,15 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
@Override @Override
public Change next() { public Change next() {
try {
return current.next(); 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) { } catch (Exception e) {

View File

@ -21,11 +21,14 @@ import java.io.OutputStream;
*/ */
public class MemoryOptimizedHistory extends FaweStreamChangeSet { public class MemoryOptimizedHistory extends FaweStreamChangeSet {
private int size = 0;
private byte[][] ids; private byte[][] ids;
private FastByteArrayOutputStream idsStream; private FastByteArrayOutputStream idsStream;
private FaweOutputStream idsStreamZip; private FaweOutputStream idsStreamZip;
private byte[][] biomes;
private FastByteArrayOutputStream biomeStream;
private FaweOutputStream biomeStreamZip;
private byte[][] entC; private byte[][] entC;
private FastByteArrayOutputStream entCStream; private FastByteArrayOutputStream entCStream;
private NBTOutputStream entCStreamZip; private NBTOutputStream entCStreamZip;
@ -57,11 +60,16 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
try { try {
if (idsStream != null) { if (idsStream != null) {
idsStreamZip.close(); idsStreamZip.close();
size = idsStream.getSize();
ids = idsStream.toByteArrays(); ids = idsStream.toByteArrays();
idsStream = null; idsStream = null;
idsStreamZip = null; idsStreamZip = null;
} }
if (biomeStream != null) {
biomeStreamZip.close();
biomes = biomeStream.toByteArrays();
biomeStream = null;
biomeStreamZip = null;
}
if (entCStream != null) { if (entCStream != null) {
entCStreamZip.close(); entCStreamZip.close();
entC = entCStream.toByteArrays(); 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 @Override
public InputStream getBlockIS() throws IOException { public InputStream getBlockIS() throws IOException {
if (ids == null) { if (ids == null) {

View File

@ -10,7 +10,6 @@ import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
@ -85,10 +84,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent implements HasFa
@Override @Override
public BaseBiome getBiome(final Vector2D position) { public BaseBiome getBiome(final Vector2D position) {
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) { return FaweCache.CACHE_BIOME[queue.getBiomeId(position.getBlockX(), position.getBlockZ())];
return EditSession.nullBiome;
}
return super.getBiome(position);
} }
@Override @Override

View File

@ -53,12 +53,11 @@ public class FuzzyRegion extends AbstractRegion {
public Iterator<BlockVector> iterator() { public Iterator<BlockVector> iterator() {
return new Iterator<BlockVector>() { return new Iterator<BlockVector>() {
private int index = -1; private int index = set.nextSetBit(0);
private BlockVector pos = new BlockVector(0, 0, 0); private BlockVector pos = new BlockVector(0, 0, 0);
@Override @Override
public boolean hasNext() { public boolean hasNext() {
index = set.nextSetBit(index + 1);
return 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.mutX(offsetX + (((b3 + ((MathMan.unpair8x(b2)) << 8)) << 21) >> 21));
pos.mutY(offsetY + b1); pos.mutY(offsetY + b1);
pos.mutZ(offsetZ + (((b4 + ((MathMan.unpair8y(b2)) << 8)) << 21) >> 21)); pos.mutZ(offsetZ + (((b4 + ((MathMan.unpair8y(b2)) << 8)) << 21) >> 21));
index = set.nextSetBit(index + 1);
return pos; return pos;
} }

View File

@ -56,7 +56,7 @@ public class PlotTrim implements Listener {
} }
public void setChunk(int x, int z) { public void setChunk(int x, int z) {
this.ids = originalQueue.getChunk(originalQueue, x, z).ids; this.ids = ((MCAChunk) originalQueue.getFaweChunk(x, z)).ids;
} }
@EventHandler @EventHandler

View File

@ -1,5 +1,7 @@
package com.boydti.fawe.util; 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.FaweChunk;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue; 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.boydti.fawe.object.exception.FaweException;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession; 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 com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.File; import java.io.File;
import java.util.Collection; import java.util.Collection;
@ -49,6 +55,11 @@ public class DelegateFaweQueue extends FaweQueue {
parent.addEditSession(session); parent.addEditSession(session);
} }
@Override
public World getWEWorld() {
return parent.getWEWorld();
}
@Override @Override
public void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) { public void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) {
parent.setProgressTracker(progressTask); parent.setProgressTracker(progressTask);
@ -89,6 +100,11 @@ public class DelegateFaweQueue extends FaweQueue {
parent.setProgressTask(progressTask); parent.setProgressTask(progressTask);
} }
@Override
public int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException {
return parent.getBiomeId(x, z);
}
@Override @Override
public void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask) { public void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask) {
parent.setChangeTask(changeTask); parent.setChangeTask(changeTask);
@ -104,11 +120,26 @@ public class DelegateFaweQueue extends FaweQueue {
parent.optimize(); parent.optimize();
} }
@Override
public int setBlocks(CuboidRegion cuboid, int id, int data) {
return parent.setBlocks(cuboid, id, data);
}
@Override @Override
public boolean setBlock(int x, int y, int z, int id, int data) { public boolean setBlock(int x, int y, int z, int id, int data) {
return parent.setBlock(x, y, z, id, 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 @Override
public void setTile(int x, int y, int z, CompoundTag tag) { public void setTile(int x, int y, int z, CompoundTag tag) {
parent.setTile(x, y, z, tag); parent.setTile(x, y, z, tag);
@ -150,8 +181,24 @@ public class DelegateFaweQueue extends FaweQueue {
} }
@Override @Override
public boolean isChunkLoaded(int x, int z) { public int getMaxY() {
return parent.isChunkLoaded(x, z); return parent.getMaxY();
}
@Override
public void forEachBlockInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
parent.forEachBlockInChunk(cx, cz, onEach);
}
@Override
public void forEachTileInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
parent.forEachTileInChunk(cx, cz, onEach);
}
@Override
@Deprecated
public boolean regenerateChunk(int x, int z) {
return parent.regenerateChunk(x, z);
} }
@Override @Override
@ -179,6 +226,7 @@ public class DelegateFaweQueue extends FaweQueue {
parent.sendBlockUpdate(blockMap, players); parent.sendBlockUpdate(blockMap, players);
} }
@Deprecated
@Override @Override
public boolean next() { public boolean next() {
return parent.next(); return parent.next();
@ -209,6 +257,11 @@ public class DelegateFaweQueue extends FaweQueue {
parent.addNotifyTask(x, z, runnable); 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 @Override
public void addNotifyTask(Runnable runnable) { public void addNotifyTask(Runnable runnable) {
parent.addNotifyTask(runnable); parent.addNotifyTask(runnable);
@ -224,6 +277,11 @@ public class DelegateFaweQueue extends FaweQueue {
return parent.getCachedCombinedId4Data(x, y, z); return parent.getCachedCombinedId4Data(x, y, z);
} }
@Override
public int getAdjacentLight(int x, int y, int z) {
return parent.getAdjacentLight(x, y, z);
}
@Override @Override
public boolean hasSky() { public boolean hasSky() {
return parent.hasSky(); return parent.hasSky();
@ -234,6 +292,11 @@ public class DelegateFaweQueue extends FaweQueue {
return parent.getSkyLight(x, y, z); return parent.getSkyLight(x, y, z);
} }
@Override
public int getLight(int x, int y, int z) {
return parent.getLight(x, y, z);
}
@Override @Override
public int getEmmittedLight(int x, int y, int z) { public int getEmmittedLight(int x, int y, int z) {
return parent.getEmmittedLight(x, y, z); return parent.getEmmittedLight(x, y, z);
@ -249,23 +312,98 @@ public class DelegateFaweQueue extends FaweQueue {
return parent.getCombinedId4Data(x, y, z, def); 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 @Override
public int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) { public int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) {
return parent.getCombinedId4DataDebug(x, y, z, def, 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 @Override
public int size() { public int size() {
return parent.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 @Override
public void runTasks() { public void runTasks() {
parent.runTasks(); parent.runTasks();
} }
@Override
public void addTask(Runnable whenFree) {
parent.addTask(whenFree);
}
@Override @Override
public boolean enqueue() { public boolean enqueue() {
return parent.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);
}
} }

View File

@ -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) {}
}

View File

@ -72,7 +72,6 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.ChangeSetExtent; import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.MaskingExtent; 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.inventory.BlockBag;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent; import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
import com.sk89q.worldedit.function.GroundFunction; 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.ChangeSetExecutor;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation; 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.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Patterns; 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) { public boolean canBypassAll(Region region, boolean get, boolean set) {
if (wrapped) return false; if (wrapped) return false;
FaweRegionExtent regionExtent = getRegionExtent(); FaweRegionExtent regionExtent = getRegionExtent();
if (!(region instanceof CuboidRegion)) return false;
if (regionExtent != null) { if (regionExtent != null) {
if (!(region instanceof CuboidRegion)) return false; if (!(region instanceof CuboidRegion)) return false;
Vector pos1 = region.getMinimumPoint(); Vector pos1 = region.getMinimumPoint();
@ -1950,7 +1949,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
checkNotNull(dir); checkNotNull(dir);
checkArgument(distance >= 1, "distance >= 1 required"); checkArgument(distance >= 1, "distance >= 1 required");
final Vector displace = dir.multiply(distance); 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 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) { final BlockReplace remove = new BlockReplace(EditSession.this, pattern) {
@Override @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 copy.setSourceFunction(remove);
final ForgetfulExtentBuffer buffer = new ForgetfulExtentBuffer(EditSession.this, new RegionMask(region)); copy.setRepetitions(1);
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, buffer, region.getMinimumPoint());
copy.setTransform(new AffineTransform().translate(dir.multiply(distance))); copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
copy.setSourceFunction(remove); // Remove
copy.setRemovingEntities(true);
Mask sourceMask = getSourceMask(); Mask sourceMask = getSourceMask();
if (sourceMask != null) { if (sourceMask != null) {
new MaskTraverser(sourceMask).reset(EditSession.this); new MaskTraverser(sourceMask).reset(EditSession.this);
@ -1981,13 +1981,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
if (!copyAir) { if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this)); copy.setSourceMask(new ExistingBlockMask(EditSession.this));
} }
Operations.completeSmart(copy, new Runnable() {
// 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() {
@Override @Override
public void run() { public void run() {
EditSession.this.flushQueue(); EditSession.this.flushQueue();

View File

@ -0,0 +1,670 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
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.
*
* <p>One can also refer to a static {@link #ZERO}.</p>
*/
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.
*
* <p>Components &lt; 0.5 are rounded down, otherwise up.</p>
*
* @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;
}
}

View File

@ -94,7 +94,7 @@ public class BiomeCommands {
BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry(); BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry();
List<BaseBiome> biomes = biomeRegistry.getBiomes(); List<BaseBiome> biomes = biomeRegistry.getBiomes();
int totalPages = biomes.size() / 19 + 1; 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) { for (BaseBiome biome : biomes) {
if (offset > 0) { if (offset > 0) {
offset--; offset--;
@ -106,7 +106,7 @@ public class BiomeCommands {
break; break;
} }
} else { } else {
player.print(BBC.getPrefix() + " <unknown #" + biome.getId() + ">"); player.print(BBC.getPrefix() + " <? #" + biome.getId() + ">");
} }
} }
} }
@ -132,19 +132,15 @@ public class BiomeCommands {
if (args.hasFlag('t')) { if (args.hasFlag('t')) {
Vector blockPosition = player.getBlockTrace(300); Vector blockPosition = player.getBlockTrace(300);
if (blockPosition == null) { if (blockPosition == null) {
player.printError("No block in sight!"); BBC.NO_BLOCK.send(player);
return; return;
} }
BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D()); BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D());
biomes.add(biome); biomes.add(biome);
qualifier = "at line of sight point";
} else if (args.hasFlag('p')) { } else if (args.hasFlag('p')) {
BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D()); BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D());
biomes.add(biome); biomes.add(biome);
qualifier = "at your position";
} else { } else {
World world = player.getWorld(); World world = player.getWorld();
Region region = session.getSelection(world); Region region = session.getSelection(world);
@ -158,17 +154,15 @@ public class BiomeCommands {
biomes.add(world.getBiome(pt.toVector2D())); 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) { for (BaseBiome biome : biomes) {
BiomeData data = biomeRegistry.getData(biome); BiomeData data = biomeRegistry.getData(biome);
if (data != null) { if (data != null) {
player.print(BBC.getPrefix() + " " + data.getName()); player.print(BBC.getPrefix() + " " + data.getName());
} else { } else {
player.print(BBC.getPrefix() + " <unknown #" + biome.getId() + ">"); player.print(BBC.getPrefix() + " <? #" + biome.getId() + ">");
} }
} }
} }
@ -204,7 +198,7 @@ public class BiomeCommands {
FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace); FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace);
Operations.completeLegacy(visitor); 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<BiomeCommands> inject() { public static Class<BiomeCommands> inject() {

View File

@ -438,7 +438,7 @@ public class BrushCommands {
maxRadius = Math.max(config.maxBrushRadius, config.butcherMaxRadius); maxRadius = Math.max(config.maxBrushRadius, config.butcherMaxRadius);
} }
if (radius > maxRadius) { if (radius > maxRadius) {
player.printError("Maximum allowed brush radius: " + maxRadius); BBC.TOOL_RADIUS_ERROR.send(player, maxRadius);
return; return;
} }

View File

@ -42,7 +42,6 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player; 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.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; 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 { public void download(final Player player, final LocalSession session, @Optional("schematic") final String formatName) throws CommandException, WorldEditException {
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName); final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (format == null) { if (format == null) {
player.printError("Unknown schematic format: " + formatName); BBC.CLIPBOARD_INVALID_FORMAT.send(player, formatName);
return; return;
} }
ClipboardHolder holder = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
@ -467,32 +466,6 @@ public class ClipboardCommands {
BBC.COMMAND_FLIPPED.send(player); BBC.COMMAND_FLIPPED.send(player);
} }
@Command(
aliases = { "/load" },
usage = "<filename>",
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 = "<filename>",
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( @Command(
aliases = { "clearclipboard" }, aliases = { "clearclipboard" },
usage = "", usage = "",

View File

@ -8,7 +8,6 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
@ -55,36 +54,6 @@ public class GeneralCommands {
} }
} }
@Command(
aliases = { "/limit" },
usage = "<limit>",
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( @Command(
aliases = { "/fast" }, aliases = { "/fast" },
usage = "[on|off]", usage = "[on|off]",
@ -98,20 +67,20 @@ public class GeneralCommands {
String newState = args.getString(0, null); String newState = args.getString(0, null);
if (session.hasFastMode()) { if (session.hasFastMode()) {
if ("on".equals(newState)) { if ("on".equals(newState)) {
player.printError("Fast mode already enabled."); BBC.FAST_ENABLED.send(player);
return; return;
} }
session.setFastMode(false); session.setFastMode(false);
player.print(BBC.getPrefix() + "Fast mode disabled."); BBC.FAST_DISABLED.send(player);
} else { } else {
if ("off".equals(newState)) { if ("off".equals(newState)) {
player.printError("Fast mode already disabled."); BBC.FAST_DISABLED.send(player);
return; return;
} }
session.setFastMode(true); 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 { public void togglePlace(Player player, LocalSession session, CommandContext args) throws WorldEditException {
if (session.togglePlacementPosition()) { if (session.togglePlacementPosition()) {
player.print(BBC.getPrefix() + "Now placing at pos #1."); BBC.PLACE_ENABLED.send(player);
} else { } else {
player.print(BBC.getPrefix() + "Now placing at the block you stand in."); BBC.PLACE_DISABLED.send(player);
} }
} }

View File

@ -119,7 +119,7 @@ public class GenerationCommands {
Vector pos = session.getPlacementPosition(player); Vector pos = session.getPlacementPosition(player);
int affected = editSession.makeCylinder(pos, Patterns.wrap(pattern), radiusX, radiusZ, height, !hollow); 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( @Command(
@ -185,7 +185,7 @@ public class GenerationCommands {
int affected = editSession.makeSphere(pos, Patterns.wrap(pattern), radiusX, radiusY, radiusZ, !hollow); int affected = editSession.makeSphere(pos, Patterns.wrap(pattern), radiusX, radiusY, radiusZ, !hollow);
player.findFreePosition(); player.findFreePosition();
player.print(BBC.getPrefix() + affected + " block(s) have been created."); BBC.VISITOR_BLOCK.send(player, affected);
} }
@Command( @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 { 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; density = density / 100;
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, new TreeGenerator(type)); 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( @Command(
@ -215,7 +215,7 @@ public class GenerationCommands {
@Logging(POSITION) @Logging(POSITION)
public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException { public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException {
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem); int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem);
player.print(BBC.getPrefix() + affected + " pumpkin patches created."); BBC.COMMAND_PUMPKIN.send(player, affected);
} }
@Command( @Command(
@ -246,7 +246,7 @@ public class GenerationCommands {
worldEdit.checkMaxRadius(size); worldEdit.checkMaxRadius(size);
int affected = editSession.makePyramid(pos, Patterns.wrap(pattern), size, !hollow); int affected = editSession.makePyramid(pos, Patterns.wrap(pattern), size, !hollow);
player.findFreePosition(); player.findFreePosition();
player.print(BBC.getPrefix() + affected + " block(s) have been created."); BBC.VISITOR_BLOCK.send(player, affected);
} }
@Command( @Command(
@ -309,7 +309,7 @@ public class GenerationCommands {
try { try {
final int affected = editSession.makeShape(region, zero, unit, Patterns.wrap(pattern), expression, hollow); final int affected = editSession.makeShape(region, zero, unit, Patterns.wrap(pattern), expression, hollow);
player.findFreePosition(); player.findFreePosition();
player.print(BBC.getPrefix() + affected + " block(s) have been created."); BBC.VISITOR_BLOCK.send(player, affected);
} catch (ExpressionException e) { } catch (ExpressionException e) {
player.printError(e.getMessage()); player.printError(e.getMessage());
} }
@ -374,7 +374,7 @@ public class GenerationCommands {
try { try {
final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow); final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow);
player.findFreePosition(); player.findFreePosition();
player.print(BBC.getPrefix() + "" + affected + " columns affected."); BBC.VISITOR_FLAT.send(player, affected);
} catch (ExpressionException e) { } catch (ExpressionException e) {
player.printError(e.getMessage()); player.printError(e.getMessage());
} }

View File

@ -222,7 +222,7 @@ public class HistoryCommands {
player.checkPermission("worldedit.history.undo.other"); player.checkPermission("worldedit.history.undo.other");
LocalSession sess = worldEdit.getSession(args.getString(1)); LocalSession sess = worldEdit.getSession(args.getString(1));
if (sess == null) { if (sess == null) {
player.printError("Unable to find session for " + args.getString(1)); BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, args.getString(1));
break; break;
} }
undone = sess.undo(session.getBlockBag(player), player); undone = sess.undo(session.getBlockBag(player), player);
@ -257,7 +257,7 @@ public class HistoryCommands {
player.checkPermission("worldedit.history.redo.other"); player.checkPermission("worldedit.history.redo.other");
LocalSession sess = worldEdit.getSession(args.getString(1)); LocalSession sess = worldEdit.getSession(args.getString(1));
if (sess == null) { if (sess == null) {
player.printError("Unable to find session for " + args.getString(1)); BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, args.getString(1));
break; break;
} }
redone = sess.redo(session.getBlockBag(player), player); redone = sess.redo(session.getBlockBag(player), player);

View File

@ -185,7 +185,7 @@ public class NavigationCommands {
player.findFreePosition(pos); player.findFreePosition(pos);
BBC.POOF.send(player); BBC.POOF.send(player);
} else { } else {
BBC.JUMPTO_FAIL.send(player); BBC.NO_BLOCK.send(player);
} }
} }

View File

@ -789,7 +789,7 @@ public class SelectionCommands {
if (found != null) { if (found != null) {
session.setDefaultRegionSelector(found); session.setDefaultRegionSelector(found);
player.print(BBC.getPrefix() + "Your default region selector is now " + found.name() + "."); BBC.SELECTOR_SET_DEFAULT.send(player, found.name());
} else { } else {
throw new RuntimeException("Something unexpected happened. Please report this."); throw new RuntimeException("Something unexpected happened. Please report this.");
} }

View File

@ -77,12 +77,12 @@ public class SnapshotCommands {
int num = args.argsLength() > 0 ? Math.min(40, Math.max(5, args.getInteger(0))) : 5; 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++) { 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() + (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 { } else {
player.printError("No snapshots are available. See console for details."); player.printError("No snapshots are available. See console for details.");
@ -129,7 +129,7 @@ public class SnapshotCommands {
if (snapshot != null) { if (snapshot != null) {
session.setSnapshot(null); session.setSnapshot(null);
player.print(BBC.getPrefix() + "Now using newest snapshot."); BBC.SNAPSHOT_NEWEST.send(player);
} else { } else {
player.printError("No snapshots were found."); player.printError("No snapshots were found.");
} }
@ -139,7 +139,7 @@ public class SnapshotCommands {
} else { } else {
try { try {
session.setSnapshot(config.snapshotRepo.getSnapshot(name)); session.setSnapshot(config.snapshotRepo.getSnapshot(name));
player.print(BBC.getPrefix() + "Snapshot set to: " + name); BBC.SNAPSHOT_SET.send(player, name);
} catch (InvalidSnapshotException e) { } catch (InvalidSnapshotException e) {
player.printError("That snapshot does not exist or is not available."); player.printError("That snapshot does not exist or is not available.");
} }
@ -187,7 +187,7 @@ public class SnapshotCommands {
return; return;
} }
session.setSnapshot(snapshot); session.setSnapshot(snapshot);
player.print(BBC.getPrefix() + "Snapshot set to: " + snapshot.getName()); BBC.SNAPSHOT_SET.send(player, snapshot.getName());
} catch (MissingWorldException e) { } catch (MissingWorldException e) {
player.printError("No snapshots were found for this world."); player.printError("No snapshots were found for this world.");
} }
@ -224,7 +224,7 @@ public class SnapshotCommands {
+ dateFormat.format(date.getTime()) + "."); + dateFormat.format(date.getTime()) + ".");
} else { } else {
session.setSnapshot(snapshot); session.setSnapshot(snapshot);
player.print(BBC.getPrefix() + "Snapshot set to: " + snapshot.getName()); BBC.SNAPSHOT_SET.send(player, snapshot.getName());
} }
} catch (MissingWorldException ex) { } catch (MissingWorldException ex) {
player.printError("No snapshots were found for this world."); 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()); Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName());
if (snapshot == null) { if (snapshot == null) {
dateFormat.setTimeZone(session.getTimeZone()); dateFormat.setTimeZone(session.getTimeZone());
player.printError("Couldn't find a snapshot after " player.printError("Couldn't find a snapshot after " + dateFormat.format(date.getTime()) + ".");
+ dateFormat.format(date.getTime()) + ".");
} else { } else {
session.setSnapshot(snapshot); session.setSnapshot(snapshot);
player.print(BBC.getPrefix() + "Snapshot set to: " + snapshot.getName()); BBC.SNAPSHOT_SET.send(player, snapshot.getName());
} }
} catch (MissingWorldException ex) { } catch (MissingWorldException ex) {
player.printError("No snapshots were found for this world."); player.printError("No snapshots were found for this world.");

View File

@ -115,7 +115,7 @@ public class SnapshotUtilCommands {
// Load chunk store // Load chunk store
try { try {
chunkStore = snapshot.getChunkStore(); chunkStore = snapshot.getChunkStore();
player.print(BBC.getPrefix() + "Snapshot '" + snapshot.getName() + "' loaded; now restoring..."); BBC.SNAPSHOT_LOADED.send(player, snapshot.getName());
} catch (DataException e) { } catch (DataException e) {
player.printError("Failed to load snapshot: " + e.getMessage()); player.printError("Failed to load snapshot: " + e.getMessage());
return; return;

View File

@ -48,7 +48,7 @@ public class SuperPickaxeCommands {
session.setSuperPickaxe(new SinglePickaxe()); session.setSuperPickaxe(new SinglePickaxe());
session.enableSuperPickAxe(); session.enableSuperPickAxe();
player.print(BBC.getPrefix() + "Mode changed. Left click with a pickaxe. // to disable."); BBC.SUPERPICKAXE_AREA_ENABLED.send(player);
} }
@Command( @Command(
@ -65,13 +65,13 @@ public class SuperPickaxeCommands {
int range = args.getInteger(0); int range = args.getInteger(0);
if (range > config.maxSuperPickaxeSize) { if (range > config.maxSuperPickaxeSize) {
player.printError("Maximum range: " + config.maxSuperPickaxeSize); BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize);
return; return;
} }
session.setSuperPickaxe(new AreaPickaxe(range)); session.setSuperPickaxe(new AreaPickaxe(range));
session.enableSuperPickAxe(); session.enableSuperPickAxe();
player.print(BBC.getPrefix() + "Mode changed. Left click with a pickaxe. // to disable."); BBC.SUPERPICKAXE_AREA_ENABLED.send(player);
} }
@Command( @Command(
@ -88,13 +88,13 @@ public class SuperPickaxeCommands {
double range = args.getDouble(0); double range = args.getDouble(0);
if (range > config.maxSuperPickaxeSize) { if (range > config.maxSuperPickaxeSize) {
player.printError("Maximum range: " + config.maxSuperPickaxeSize); BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize);
return; return;
} }
session.setSuperPickaxe(new RecursivePickaxe(range)); session.setSuperPickaxe(new RecursivePickaxe(range));
session.enableSuperPickAxe(); session.enableSuperPickAxe();
player.print(BBC.getPrefix() + "Mode changed. Left click with a pickaxe. // to disable."); BBC.SUPERPICKAXE_AREA_ENABLED.send(player);
} }
public static Class<SuperPickaxeCommands> inject() { public static Class<SuperPickaxeCommands> inject() {

View File

@ -155,7 +155,7 @@ public class ToolCommands {
int range = args.getInteger(1); int range = args.getInteger(1);
if (range > config.maxSuperPickaxeSize) { if (range > config.maxSuperPickaxeSize) {
BBC.TOOL_FLOOD_FILL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize);
return; return;
} }

View File

@ -442,7 +442,7 @@ public class UtilityCommands {
killed += visitor.getAffected(); 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) { if (editSession != null) {
session.remember(editSession); session.remember(editSession);
@ -502,7 +502,7 @@ public class UtilityCommands {
removed += visitor.getAffected(); removed += visitor.getAffected();
} }
actor.print(BBC.getPrefix() + "Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal."); BBC.KILL_SUCCESS.send(removed, radius);
if (editSession != null) { if (editSession != null) {
session.remember(editSession); session.remember(editSession);

View File

@ -107,9 +107,8 @@ public class WorldEditCommands {
public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException { public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException {
TimeZone tz = TimeZone.getTimeZone(args.getString(0)); TimeZone tz = TimeZone.getTimeZone(args.getString(0));
session.setTimezone(tz); session.setTimezone(tz);
player.print(BBC.getPrefix() + "Timezone set for this session to: " + tz.getDisplayName()); BBC.TIMEZONE_SET.send(player, tz.getDisplayName());
player.print(BBC.getPrefix() + "The current time in that timezone is: " BBC.TIMEZONE_DISPLAY.send(player, dateFormat.format(Calendar.getInstance(tz).getTime()));
+ dateFormat.format(Calendar.getInstance(tz).getTime()));
} }
@Command( @Command(

View File

@ -1,5 +1,6 @@
package com.sk89q.worldedit.command.tool; package com.sk89q.worldedit.command.tool;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.extent.ResettableExtent;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
@ -176,7 +177,7 @@ public class BrushTool implements TraceTool {
target = player.getBlockTrace(getRange(), true); target = player.getBlockTrace(getRange(), true);
if (target == null) { if (target == null) {
player.printError("No block in sight!"); BBC.NO_BLOCK.send(player);
return true; return true;
} }
@ -216,7 +217,7 @@ public class BrushTool implements TraceTool {
try { try {
brush.build(editSession, target, material, size); brush.build(editSession, target, material, size);
} catch (MaxChangedBlocksException e) { } catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached."); player.printError("Max blocks change limit reached."); // Never happens
} finally { } finally {
if (bag != null) { if (bag != null) {
bag.flushChanges(); bag.flushChanges();

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.command.tool; package com.sk89q.worldedit.command.tool;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
@ -82,7 +83,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
target = player.getBlockTraceFace(getRange(), true); target = player.getBlockTraceFace(getRange(), true);
if (target == null) { if (target == null) {
player.printError("No block in sight!"); BBC.NO_BLOCK.send(player);
return null; return null;
} }

View File

@ -22,7 +22,7 @@ package com.sk89q.worldedit.extension.factory;
import com.boydti.fawe.jnbt.JSON2NBT; import com.boydti.fawe.jnbt.JSON2NBT;
import com.boydti.fawe.jnbt.NBTException; import com.boydti.fawe.jnbt.NBTException;
import com.boydti.fawe.util.MathMan; 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.CompoundTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;

View File

@ -282,19 +282,19 @@ public class DefaultMaskParser extends FaweParser<Mask> {
int requiredMin = 1; int requiredMin = 1;
int requiredMax = 8; int requiredMax = 8;
if (split.length == 2) { if (split.length == 2) {
String[] split2 = split[1].split(":"); String[] split2 = split[1].split("[:|,]");
requiredMin = (int) Math.abs(Expression.compile(split2[0]).evaluate()); 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()); requiredMax = (int) Math.abs(Expression.compile(split2[1]).evaluate());
} }
} }
if (firstChar == '~') { 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 { } else {
return new WallMask(extent, worldEdit.getBlockFactory().parseFromListInput(input.substring(1), tempContext), requiredMin, requiredMax); return new WallMask(extent, worldEdit.getBlockFactory().parseFromListInput(input.substring(1), tempContext), requiredMin, requiredMax);
} }
} catch (NumberFormatException | ExpressionException e) { } catch (NumberFormatException | ExpressionException e) {
throw new SuggestInputParseException(input, "~<blocks>=<amount>"); throw new SuggestInputParseException(input, "~<blocks>=<min>:<max>");
} }
} }
case '>': case '>':

View File

@ -482,7 +482,7 @@ public class PlatformManager {
if (pos != null) { if (pos != null) {
player.findFreePosition(pos); player.findFreePosition(pos);
} else { } else {
player.printError("No block in sight (or too far)!"); BBC.NO_BLOCK.send(player);
} }
event.setCancelled(true); event.setCancelled(true);

View File

@ -28,8 +28,8 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.ChunkStore;
import java.util.AbstractSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
@ -315,18 +315,60 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
@Override @Override
public Set<Vector2D> getChunks() { public Set<Vector2D> getChunks() {
Set<Vector2D> chunks = new LinkedHashSet<Vector2D>();
Vector min = getMinimumPoint(); Vector min = getMinimumPoint();
Vector max = getMaximumPoint(); 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) { return new AbstractSet<Vector2D>() {
for (int z = max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; z >= min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; --z) { @Override
chunks.add(new Vector2D(x, z)); public Iterator<Vector2D> iterator() {
} return new Iterator<Vector2D>() {
private Vector2D pos = new Vector2D(minX, minZ);
@Override
public boolean hasNext() {
return pos != null;
} }
return chunks; @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.");
}
};
}
@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 @Override

View File

@ -58,6 +58,7 @@ shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -58,6 +58,7 @@ shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -49,6 +49,7 @@ shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -58,6 +58,7 @@ shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -57,6 +57,7 @@ shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -23,6 +23,7 @@ jar.enabled = false
shadowJar { shadowJar {
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) 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(name: 'worldedit-core-6.1.4-SNAPSHOT-dist'))
include(dependency('com.google.code.gson:gson:2.2.4')) include(dependency('com.google.code.gson:gson:2.2.4'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))

View File

@ -28,9 +28,6 @@ public class FaweNukkit implements IFawe, Listener {
private final NukkitWorldEdit plugin; private final NukkitWorldEdit plugin;
public FaweNukkit(NukkitWorldEdit mod) { 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; this.plugin = mod;
FaweChunk.HEIGHT = 128; FaweChunk.HEIGHT = 128;
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);

View File

@ -14,7 +14,6 @@ import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
@ -80,28 +79,18 @@ public class NukkitChunk extends CharFaweChunk<BaseFullChunk, NukkitQueue> {
final BaseFullChunk chunk = getChunk(); final BaseFullChunk chunk = getChunk();
getParent().setHeightMap(this, heightMap); getParent().setHeightMap(this, heightMap);
char[][] sections = getCombinedIdArrays(); char[][] sections = getCombinedIdArrays();
final int[][] biomes = getBiomeArray();
final int X = getX() << 4; final int X = getX() << 4;
final int Z = getZ() << 4; final int Z = getZ() << 4;
if (biomes != null) { if (biomes != null) {
final LocalWorld lw = NukkitUtil.getLocalWorld(world); final LocalWorld lw = NukkitUtil.getLocalWorld(world);
final BaseBiome bb = new BaseBiome(0); final byte[] biomes = getBiomeArray();
int last = 0; int index = 0;
for (int x = 0; x < 16; x++) { Vector2D mutable = new Vector2D();
final int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
final int biome = array[z]; mutable.z = Z + z;
if (biome == 0) { for (int x = 0; x < 16; x++) {
continue; mutable.x = X + x;
} lw.setBiome(mutable, FaweCache.getBiome(biomes[index++] & 0xFF));
if (last != biome) {
last = biome;
bb.setId(biome);
}
lw.setBiome(new Vector2D(X + x, Z + z), bb);
} }
} }
} }

View File

@ -236,21 +236,11 @@ public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFu
return NBTConverter.fromNative(nbt); return NBTConverter.fromNative(nbt);
} }
@Override
public BaseFullChunk getChunk(Level level, int x, int z) {
return (BaseFullChunk) level.getChunk(x, z);
}
@Override @Override
public Level getImpWorld() { public Level getImpWorld() {
return world; return world;
} }
@Override
public boolean isChunkLoaded(Level level, int x, int z) {
return level.isChunkLoaded(x, z);
}
@Override @Override
public boolean regenerateChunk(Level level, int x, int z, BaseBiome biome, Long seed) { public boolean regenerateChunk(Level level, int x, int z, BaseBiome biome, Long seed) {
level.regenerateChunk(x, z); level.regenerateChunk(x, z);
@ -263,8 +253,18 @@ public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFu
} }
@Override @Override
public boolean loadChunk(Level level, int x, int z, boolean generate) { public BaseFullChunk loadChunk(Level level, int x, int z, boolean generate) {
return level.loadChunk(x, z, generate); return level.getChunk(x, z, generate);
}
@Override
public BaseFullChunk getSections(BaseFullChunk baseFullChunk) {
return baseFullChunk;
}
@Override
public BaseFullChunk getCachedChunk(Level level, int cx, int cz) {
return level.getProvider().getChunk(cx, cz);
} }
@Override @Override
@ -273,6 +273,11 @@ public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFu
return chunk; return chunk;
} }
@Override
public int getBiome(BaseFullChunk baseFullChunk, int x, int z) {
return baseFullChunk.getBiomeId(x & 15, z & 15);
}
@Override @Override
public BaseFullChunk getCachedSection(BaseFullChunk baseFullChunk, int cy) { public BaseFullChunk getCachedSection(BaseFullChunk baseFullChunk, int cy) {
return baseFullChunk; return baseFullChunk;

View File

@ -72,6 +72,7 @@ shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1')) include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -1,7 +1,7 @@
package com.boydti.fawe.sponge; package com.boydti.fawe.sponge;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.spongepowered.api.Sponge; import org.spongepowered.api.Sponge;
import org.spongepowered.api.scheduler.Task; import org.spongepowered.api.scheduler.Task;
@ -16,7 +16,7 @@ public class SpongeTaskMan extends TaskManager {
private final AtomicInteger i = new AtomicInteger(); private final AtomicInteger i = new AtomicInteger();
private final HashMap<Integer, Task> tasks = new HashMap<>(); private final ConcurrentHashMap<Integer, Task> tasks = new ConcurrentHashMap<>();
@Override @Override
public int repeat(Runnable runnable, int interval) { public int repeat(Runnable runnable, int interval) {