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

View File

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

View File

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

View File

@ -161,11 +161,6 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
return getWorldName() != null ? Bukkit.getWorld(getWorldName()) : null;
}
@Override
public boolean isChunkLoaded(World world, int x, int z) {
return world.isChunkLoaded(x, z);
}
@Override
public void sendChunk(int x, int z, int bitMask) {}
@ -188,15 +183,6 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
return getWorld().getEnvironment() == World.Environment.NORMAL;
}
@Override
public boolean loadChunk(World impWorld, int x, int z, boolean generate) {
if (impWorld.loadChunk(x, z, generate)) {
keepLoaded.put(MathMan.pairInt(x, z), System.currentTimeMillis());
return true;
}
return false;
}
private volatile boolean timingsEnabled;
private static boolean alertTimingsChange = true;
private static Field fieldTimingsEnabled;

View File

@ -3,18 +3,18 @@ package com.boydti.fawe.bukkit.v0;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.Biome;
public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot, ChunkSnapshot> {
public static int ALLOCATE;
private static int LIGHT_MASK = 0x739C0;
@ -39,87 +39,108 @@ public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
@Override
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
// Do nothing
// Not supported
}
@Override
public void setSkyLight(Chunk chunk, int x, int y, int z, int value) {
public void setSkyLight(ChunkSnapshot chunk, int x, int y, int z, int value) {
// Not supported
}
@Override
public void setBlockLight(Chunk chunk, int x, int y, int z, int value) {
// chunk.getBlock(x & 15, y, z & 15);
public void setBlockLight(ChunkSnapshot chunk, int x, int y, int z, int value) {
// Not supported
}
public int getCombinedId4Data(Chunk section, int x, int y, int z) {
Block block = ((Chunk) section).getBlock(x & 15, y, z & 15);
int combined = block.getTypeId() << 4;
if (FaweCache.hasData(combined)) {
combined += block.getData();
@Override
public int getCombinedId4Data(ChunkSnapshot chunk, int x, int y, int z) {
if (chunk.isSectionEmpty(y >> 4)) {
return 0;
}
int id = chunk.getBlockTypeId(x & 15, y, z & 15);
if (FaweCache.hasData(id)) {
int data = chunk.getBlockData(x & 15, y, z & 15);
return (id << 4) + data;
} else {
return id << 4;
}
return combined;
}
@Override
public int getEmmittedLight(final Chunk chunk, int x, int y, int z) {
if (!chunk.isLoaded()) {
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
chunk.load(true);
public int getBiome(ChunkSnapshot chunkSnapshot, int x, int z) {
Biome biome = chunkSnapshot.getBiome(x & 15, z & 15);
return adapter.getBiomeId(biome);
}
@Override
public ChunkSnapshot getSections(ChunkSnapshot chunkSnapshot) {
return chunkSnapshot;
}
@Override
public ChunkSnapshot getCachedChunk(World world, int cx, int cz) {
if (world.isChunkLoaded(cx, cz)) {
long pair = MathMan.pairInt(cx, cz);
Long originalKeep = keepLoaded.get(pair);
keepLoaded.put(pair, Long.MAX_VALUE);
if (world.isChunkLoaded(cx, cz)) {
Chunk chunk = world.getChunkAt(cx, cz);
if (originalKeep != null) {
keepLoaded.put(pair, originalKeep);
} else {
keepLoaded.remove(pair);
}
});
return chunk.getChunkSnapshot(false, true, false);
} else {
keepLoaded.remove(pair);
return null;
}
} else {
return null;
}
return chunk.getBlock(x, y, z).getLightFromBlocks();
}
@Override
public int getSkyLight(final Chunk chunk, int x, int y, int z) {
if (!chunk.isLoaded()) {
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
chunk.load(true);
}
});
}
return chunk.getBlock(x, y, z).getLightFromSky();
public int getEmmittedLight(final ChunkSnapshot chunk, int x, int y, int z) {
return chunk.getBlockEmittedLight(x & 15, y, z & 15);
}
@Override
public int getLight(final Chunk chunk, int x, int y, int z) {
if (!chunk.isLoaded()) {
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
chunk.load(true);
}
});
}
return chunk.getBlock(x, y, z).getLightLevel();
public int getSkyLight(final ChunkSnapshot chunk, int x, int y, int z) {
return chunk.getBlockSkyLight(x & 15, y, z & 15);
}
@Override
public Chunk getCachedSections(World impWorld, int cx, int cz) {
return impWorld.getChunkAt(cx, cz);
public int getLight(final ChunkSnapshot chunk, int x, int y, int z) {
x = x & 15;
z = z & 15;
return Math.max(chunk.getBlockEmittedLight(x, y, z), chunk.getBlockSkyLight(x, y, z));
}
@Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
public ChunkSnapshot loadChunk(World world, int x, int z, boolean generate) {
Chunk chunk = world.getChunkAt(x, z);
chunk.load(generate);
return chunk.isLoaded() ? chunk.getChunkSnapshot(false, true, false) : null;
}
@Override
public ChunkSnapshot getCachedSections(World impWorld, int cx, int cz) {
return getCachedChunk(impWorld, cx, cz);
}
@Override
public CompoundTag getTileEntity(ChunkSnapshot chunk, int x, int y, int z) {
if (adapter == null) {
return null;
}
Location loc = new Location(getWorld(), x, y, z);
BaseBlock block = adapter.getBlock(loc);
System.out.println("Get tile " + x + "," + y + "," + z + " | " + (block != null ? block.getNbtData() : null) + " | done");
return block != null ? block.getNbtData() : null;
}
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Override
public FaweChunk getFaweChunk(int x, int z) {
return new BukkitChunk_All(this, x, z);

View File

@ -6,8 +6,9 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import java.util.HashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.HashSet;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
@ -46,11 +47,37 @@ public class ChunkListener implements Listener {
}
}
public static void main(String[] args) {
Map<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 itemFreeze = false;
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 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);
}
// Set biomes
int[][] biomes = this.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
if (this.biomes != null) {
byte[] currentBiomes = nmsChunk.getBiomeIndex();
for (int i = 0 ; i < this.biomes.length; i++) {
if (this.biomes[i] != 0) {
currentBiomes[i] = this.biomes[i];
}
}
}

View File

@ -64,7 +64,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue_1_10 extends BukkitQueue_0<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 Field fieldBits;
@ -304,13 +304,42 @@ public class BukkitQueue_1_10 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();
public int getBiome(net.minecraft.server.v1_10_R1.Chunk chunk, int x, int z) {
return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
@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];
}
@ -350,27 +379,21 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
@Override
public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) {
return;
net.minecraft.server.v1_10_R1.Chunk chunk = getCachedChunk(getWorld(), x, z);
if (chunk != null) {
sendChunk(chunk, bitMask);
}
sendChunk(getWorld().getChunkAt(x, z), bitMask);
}
@Override
public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_10 fs = (BukkitChunk_1_10) fc;
if (!isChunkLoaded(fc.getX(), fc.getZ())) {
return;
net.minecraft.server.v1_10_R1.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (chunk != null) {
sendChunk(chunk, fc.getBitMask());
}
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
}
public void sendChunk(Chunk chunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
public void sendChunk(net.minecraft.server.v1_10_R1.Chunk nmsChunk, int mask) {
WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
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);
@Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities();
public CompoundTag getTileEntity(net.minecraft.server.v1_10_R1.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z);
TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null;
@ -627,11 +650,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}
}
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Deprecated
public boolean unloadChunk(final String world, final Chunk chunk) {
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 java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
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);
}
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
public CharFaweChunk copy(boolean shallow) {
BukkitChunk_1_11 copy;
@ -174,6 +210,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
@Override
public FaweChunk call() {
try {
BukkitChunk_1_11_Copy copy = getParent().getChangeTask() != null ? new BukkitChunk_1_11_Copy(getParent(), getX(), getZ()) : null;
final Chunk chunk = this.getChunk();
final World world = chunk.getWorld();
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();
final Collection<Entity>[] entities = (Collection<Entity>[]) getParent().getEntitySlices.invoke(nmsChunk);
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
// copy
// BukkitChunk_1_11 copy = getParent().getFaweChunk(getX(), getZ()); // TODO
// Set heightmap
getParent().setHeightMap(this, heightMap);
// Remove entities
@ -198,6 +233,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entsToRemove.contains(entity.getUniqueID())) {
if (copy != null) {
copy.storeEntity(entity);
}
nmsWorld.removeEntity(entity);
}
}
@ -211,7 +249,11 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
} else if (count >= 4096) {
Collection<Entity> ents = entities[i];
if (!ents.isEmpty()) {
// copy.storeEntities(this, i);
if (copy != null) {
for (Entity entity : ents) {
copy.storeEntity(entity);
}
}
synchronized (BukkitQueue_0.adapter) {
ents.clear();
}
@ -220,8 +262,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
Collection<Entity> ents = entities[i];
if (!ents.isEmpty()) {
char[] array = this.getIdArray(i);
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
ents = new ArrayList<>(entities[i]);
if (array == null || ents == null || ents.isEmpty()) continue;
synchronized (BukkitQueue_0.adapter) {
for (Entity entity : ents) {
if (entity instanceof EntityPlayer) {
@ -232,7 +273,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
int y = (int) Math.round(entity.locY);
if (y < 0 || y > 255) continue;
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
// copy.storeEntity(this, entity);
if (copy != null) {
copy.storeEntity(entity);
}
nmsWorld.removeEntity(entity);
}
}
@ -291,11 +334,6 @@ public class BukkitChunk_1_11 extends CharFaweChunk<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
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
HashMap<BlockPosition, TileEntity> toRemove = null;
@ -315,11 +353,13 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
if (toRemove == null) {
toRemove = new HashMap<>();
}
if (copy != null) {
storeTile(tile.getValue(), tile.getKey());
}
toRemove.put(tile.getKey(), tile.getValue());
}
}
if (toRemove != null) {
// copy.storeTiles(this, toRemove);
for (Map.Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
BlockPosition bp = entry.getKey();
TileEntity tile = entry.getValue();
@ -342,7 +382,9 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
continue;
}
ChunkSection section = sections[j];
// copy.storeBlocks(this, section);
if (copy != null) {
copy.storeSection(section, j);
}
if (section == null) {
if (count == countAir) {
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);
}
// Set biomes
int[][] biomes = this.biomes;
if (biomes != null) {
// copy.storeBiomes(this);
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
if (this.biomes != null) {
if (copy != null) {
copy.storeBiomes(nmsChunk.getBiomeIndex());
}
byte[] currentBiomes = nmsChunk.getBiomeIndex();
for (int i = 0 ; i < this.biomes.length; i++) {
if (this.biomes[i] != 0) {
currentBiomes[i] = this.biomes[i];
}
}
}
@ -442,10 +478,10 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
tileEntity.a(tag); // ReadTagIntoTile
}
}
// Change task?
// if (getParent().getChangeTask() != null) { // TODO
// getParent().getChangeTask().run(copy, this);
// }
// Change task
if (copy != null) {
getParent().getChangeTask().run(copy, this);
}
} catch (Throwable e) {
MainUtil.handleError(e);
}

View File

@ -1,6 +1,9 @@
package com.boydti.fawe.bukkit.v1_11;
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 final byte[][] idsBytes;
@ -17,6 +20,21 @@ public class BukkitChunk_1_11_Copy extends BukkitChunk_1_11 {
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
public char[][] getCombinedIdArrays() {
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.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 Field fieldBits;
@ -150,6 +150,41 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
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
public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
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
public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) {
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
public int getOpacity(ChunkSection section, int x, int y, int z) {
DataPaletteBlock dataPalette = section.getBlocks();
@ -357,27 +386,21 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
@Override
public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) {
return;
net.minecraft.server.v1_11_R1.Chunk chunk = getCachedChunk(getWorld(), x, z);
if (chunk != null) {
sendChunk(chunk, bitMask);
}
sendChunk(getWorld().getChunkAt(x, z), bitMask);
}
@Override
public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_11 fs = (BukkitChunk_1_11) fc;
if (!isChunkLoaded(fc.getX(), fc.getZ())) {
return;
net.minecraft.server.v1_11_R1.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (chunk != null) {
sendChunk(chunk, fc.getBitMask());
}
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
}
public void sendChunk(Chunk chunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
net.minecraft.server.v1_11_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
public void sendChunk(net.minecraft.server.v1_11_R1.Chunk nmsChunk, int mask) {
WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
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()) {
return;
}
if (mask == 0) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65535);
for (EntityPlayer player : playerChunk.c) {
player.playerConnection.sendPacket(packet);
}
return;
}
// Send chunks
boolean empty = false;
ChunkSection[] sections = nmsChunk.getSections();
@ -396,7 +426,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
empty = true;
}
}
if (mask == 0 || mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280);
for (EntityPlayer player : playerChunk.c) {
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);
@Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities();
public CompoundTag getTileEntity(net.minecraft.server.v1_11_R1.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z);
TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null;
@ -618,11 +648,6 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}
}
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Deprecated
public boolean unloadChunk(final String world, final Chunk chunk) {
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
int[][] biomes = this.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.m()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; // Biome array
if (this.biomes != null) {
byte[] currentBiomes = nmsChunk.m();
for (int i = 0 ; i < this.biomes.length; i++) {
if (this.biomes[i] != 0) {
currentBiomes[i] = this.biomes[i];
}
}
}

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.WorldType;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.block.Biome;
@ -59,7 +58,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue17 extends BukkitQueue_0<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 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) {
return Bukkit.getWorld(world);
}
@Override
public boolean loadChunk(World world, int x, int z, boolean generate) {
return getCachedSections(world, x, z) != null;
public int getBiome(net.minecraft.server.v1_7_R4.Chunk chunk, int x, int z) {
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
@ -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
public int getCombinedId4Data(ChunkSection ls, int x, int y, int z) {
byte[] ids = ls.getIdArray();
@ -221,16 +238,6 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
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
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;
@ -307,19 +314,14 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
}
@Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
Map<ChunkPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().tileEntities;
public CompoundTag getTileEntity(net.minecraft.server.v1_7_R4.Chunk chunk, int x, int y, int z) {
Map<ChunkPosition, TileEntity> tiles = chunk.tileEntities;
ChunkPosition pos = new ChunkPosition(x, y, z);
TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null;
}
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
@ -331,28 +333,22 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
@Override
public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) {
return;
net.minecraft.server.v1_7_R4.Chunk chunk = getCachedChunk(getWorld(), x, z);
if (chunk != null) {
sendChunk(chunk, bitMask);
}
sendChunk(getWorld().getChunkAt(x, z), bitMask);
}
@Override
public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_7 fs = (BukkitChunk_1_7) fc;
if (!isChunkLoaded(fc.getX(), fc.getZ())) {
return;
net.minecraft.server.v1_7_R4.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (chunk != null) {
sendChunk(chunk, fc.getBitMask());
}
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
}
public void sendChunk(Chunk chunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
public void sendChunk(net.minecraft.server.v1_7_R4.Chunk nmsChunk, int mask) {
try {
net.minecraft.server.v1_7_R4.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
ChunkCoordIntPair pos = nmsChunk.l(); // getPosition()
WorldServer w = (WorldServer) nmsChunk.world;
PlayerChunkMap chunkMap = w.getPlayerChunkMap();

View File

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

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.WorldType;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.block.Biome;
@ -58,7 +57,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.Chunk, ChunkSection[], ChunkSection> {
public static Field isDirty;
@ -180,17 +179,43 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
}
@Override
public boolean isChunkLoaded(int x, int z) {
return getWorld().isChunkLoaded(x, z);
}
public World getWorld(String world) {
return Bukkit.getWorld(world);
public int getBiome(net.minecraft.server.v1_8_R3.Chunk chunk, int x, int z) {
return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
@Override
public boolean loadChunk(World world, int x, int z, boolean generate) {
return getCachedSections(world, x, z) != null;
public net.minecraft.server.v1_8_R3.ChunkSection[] getSections(net.minecraft.server.v1_8_R3.Chunk chunk) {
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
@ -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
public int getCombinedId4Data(ChunkSection section, int x, int y, int z) {
char[] ls = section.getIdArray();
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
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;
@ -309,19 +312,14 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
private BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
@Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities();
public CompoundTag getTileEntity(net.minecraft.server.v1_8_R3.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z);
TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null;
}
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
@ -333,28 +331,22 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
@Override
public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) {
return;
net.minecraft.server.v1_8_R3.Chunk chunk = getCachedChunk(getWorld(), x, z);
if (chunk != null) {
sendChunk(chunk, bitMask);
}
sendChunk(getWorld().getChunkAt(x, z), bitMask);
}
@Override
public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_8 fs = (BukkitChunk_1_8) fc;
if (!isChunkLoaded(fc.getX(), fc.getZ())) {
return;
net.minecraft.server.v1_8_R3.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (chunk != null) {
sendChunk(chunk, fc.getBitMask());
}
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
}
public void sendChunk(Chunk chunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
public void sendChunk(net.minecraft.server.v1_8_R3.Chunk nmsChunk, int mask) {
try {
net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
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 org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
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);
}
// Set biomes
int[][] biomes = this.biomes;
byte[] biomes = this.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
byte[] currentBiomes = nmsChunk.getBiomeIndex();
for (int i = 0; i < currentBiomes.length; i++) {
byte newBiome = biomes[i];
if (newBiome != 0) {
currentBiomes[i] = newBiome;
}
}
}
@ -437,23 +430,6 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
} catch (Throwable e) {
MainUtil.handleError(e);
}
final int[][] biomes = this.getBiomeArray();
final Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
final int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
final int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
return this;
}
}
}

View File

@ -62,7 +62,7 @@ import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<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 Field fieldBits;
@ -191,13 +191,42 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
}
@Override
public ChunkSection[] getCachedSections(World world, int cx, int cz) {
CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz);
return chunk.getHandle().getSections();
public int getBiome(net.minecraft.server.v1_9_R2.Chunk chunk, int x, int z) {
return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
@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];
}
@ -216,27 +245,21 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
@Override
public void sendChunk(int x, int z, int bitMask) {
if (!isChunkLoaded(x, z)) {
return;
net.minecraft.server.v1_9_R2.Chunk chunk = getCachedChunk(getWorld(), x, z);
if (chunk != null) {
sendChunk(chunk, bitMask);
}
sendChunk(getWorld().getChunkAt(x, z), bitMask);
}
@Override
public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_9 fs = (BukkitChunk_1_9) fc;
if (!isChunkLoaded(fc.getX(), fc.getZ())) {
return;
net.minecraft.server.v1_9_R2.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (chunk != null) {
sendChunk(chunk, fc.getBitMask());
}
Chunk chunk = fs.getChunk();
sendChunk(chunk, fs.getBitMask());
}
public void sendChunk(Chunk chunk, int mask) {
if (!chunk.isLoaded()) {
return;
}
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
public void sendChunk(net.minecraft.server.v1_9_R2.Chunk nmsChunk, int mask) {
WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
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);
@Override
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = ((CraftChunk) chunk).getHandle().getTileEntities();
public CompoundTag getTileEntity(net.minecraft.server.v1_9_R2.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z);
TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null;
@ -578,11 +601,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
}
}
@Override
public Chunk getChunk(World world, int x, int z) {
return world.getChunkAt(x, z);
}
@Deprecated
public boolean unloadChunk(final String world, final Chunk chunk) {
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
public Biome getBiome(int x, int z) {
throw new UnsupportedOperationException("NOT IMPLEMENTED");
return adapter.getBiome(queue.getBiomeId(x, z));
}
@Override

View File

@ -7,6 +7,7 @@ dependencies {
compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT'
compile 'org.primesoft:BlocksHub:2.0'
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') {
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.Updater;
import com.boydti.fawe.util.WEManager;
import com.boydti.fawe.util.WESubscriber;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.worldedit.BlockVector;
@ -25,6 +24,7 @@ import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BlockData;
import com.sk89q.worldedit.command.BiomeCommands;
@ -254,7 +254,6 @@ public class Fawe {
Fawe.debug("Plugin 'PlotSquared' found. Using it now.");
} catch (Throwable e) {}
Fawe.this.worldedit = WorldEdit.getInstance();
Fawe.this.setupEvents();
}
}, 0);
@ -298,10 +297,6 @@ public class Fawe {
return timer.getTPS();
}
private void setupEvents() {
WorldEdit.getInstance().getEventBus().register(new WESubscriber());
}
private void setupCommands() {
this.IMP.setupCommand("wea", new Wea());
this.IMP.setupCommand("select", new WorldEditRegion());
@ -417,6 +412,7 @@ public class Fawe {
BlockWorldVector.inject(); // Optimizations
BlockVector.inject(); // Optimizations
Vector.inject(); // Optimizations
Vector2D.inject(); // Optimizations
// Pattern
Patterns.inject(); // Optimizations (reduce object creation)
RandomPattern.inject(); // Optimizations
@ -538,6 +534,11 @@ public class Fawe {
ne.addNotificationListener(new NotificationListener() {
@Override
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();
}
}, null, null);

View File

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

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_2("Region regenerated.", "WorldEdit.Regen"),
COMMAND_TREE("%s0 trees created.", "WorldEdit.Tree"),
COMMAND_PUMPKIN("%s0 pumpkin patches created.", "WorldEdit.Tree"),
COMMAND_FLORA("%s0 flora created.", "WorldEdit.Flora"),
COMMAND_HISTORY_CLEAR("History cleared", "WorldEdit.History"),
COMMAND_REDO_ERROR("Nothing left to redo. (See also `/inspect` and `/frb`)", "WorldEdit.History"),
COMMAND_HISTORY_OTHER_ERROR("Unable to find session for %s0.", "WorldEdit.History"),
COMMAND_REDO_SUCCESS("Redo successful.", "WorldEdit.History"),
COMMAND_UNDO_ERROR("Nothing left to undo. (See also `/inspect` and `/frb`)", "WorldEdit.History"),
COMMAND_UNDO_SUCCESS("Undo successful.", "WorldEdit.History"),
@ -133,6 +135,7 @@ public enum BBC {
BRUSH_TRANSFORM("Brush transform set", "WorldEdit.Brush"),
BRUSH_MATERIAL("Brush material set", "WorldEdit.Brush"),
ROLLBACK_ELEMENT("Undoing %s0", "WorldEdit.Rollback"),
TOOL_INSPECT("Inspect tool bound to %s0.", "WorldEdit.Tool"),
@ -145,13 +148,32 @@ public enum BBC {
TOOL_REPL("Block replacer tool bound to %s0.", "WorldEdit.Tool"),
TOOL_CYCLER("Block data cycler tool bound to %s0.", "WorldEdit.Tool"),
TOOL_FLOOD_FILL("Block flood fill tool bound to %s0.", "WorldEdit.Tool"),
TOOL_FLOOD_FILL_RANGE_ERROR("Maximum range: %s0.", "WorldEdit.Tool"),
TOOL_RANGE_ERROR("Maximum range: %s0.", "WorldEdit.Tool"),
TOOL_RADIUS_ERROR("Maximum allowed brush radius: %s0.", "WorldEdit.Tool"),
TOOL_DELTREE("Floating tree remover tool bound to %s0.", "WorldEdit.Tool"),
TOOL_FARWAND("Far wand tool bound to %s0.", "WorldEdit.Tool"),
TOOL_LRBUILD_BOUND("Long-range building tool bound to %s0.", "WorldEdit.Tool"),
TOOL_LRBUILD_INFO("Left-click set to %s0; right-click set to %s1.", "WorldEdit.Tool"),
SUPERPICKAXE_ENABLED("Super Pickaxe enabled.", "WorldEdit.Tool"),
SUPERPICKAXE_DISABLED("Super Pickaxe disabled.", "WorldEdit.Tool"),
SUPERPICKAXE_AREA_ENABLED("Mode changed. Left click with a pickaxe. // to disable.", "WorldEdit.Tool"),
SNAPSHOT_LOADED("Snapshot '%s0' loaded; now restoring...", "WorldEdit.Snapshot"),
SNAPSHOT_SET("Snapshot set to: %s0", "WorldEdit.Snapshot"),
SNAPSHOT_NEWEST("Now using newest snapshot.", "WorldEdit.Snapshot"),
SNAPSHOT_LIST_HEADER("Snapshots for world (%s0):", "WorldEdit.Snapshot"),
SNAPSHOT_LIST_FOOTER("Use /snap use [snapshot] or /snap use latest.", "WorldEdit.Snapshot"),
BIOME_LIST_HEADER("Biomes (page %s0/%s1):", "WorldEdit.Biome"),
BIOME_CHANGED("Biomes were changed in %s0 columns.", "WorldEdit.Biome"),
FAST_ENABLED("Fast mode enabled. History and edit restrictions will be bypassed.", "WorldEdit.General"),
FAST_DISABLED("Fast mode disabled", "WorldEdit.General"),
PLACE_ENABLED("Now placing at pos #1.", "WorldEdit.General"),
PLACE_DISABLED("Now placing at the block you stand in.", "WorldEdit.General"),
KILL_SUCCESS("Killed %s0 entities in a radius of %s1.", "WorldEdit.Utility"),
SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"),
@ -163,6 +185,7 @@ public enum BBC {
SCHEMATIC_LIST("Available schematics (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"),
CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"),
CLIPBOARD_INVALID_FORMAT("Unknown clipboard format: %s0", "WorldEdit.Clipboard"),
VISITOR_BLOCK("%s0 blocks affected", "WorldEdit.Visitor"),
VISITOR_ENTITY("%s0 entities affected", "WorldEdit.Visitor"),
@ -174,6 +197,10 @@ public enum BBC {
SELECTOR_CUBOID_POS2("pos2 set to %s0 %s1.", "WorldEdit.Selector"),
SELECTOR_INVALID_COORDINATES("Invalid coordinates %s0", "WorldEdit.Selector"),
SELECTOR_ALREADY_SET("Position already set.", "WorldEdit.Selector"),
SELECTOR_SET_DEFAULT("Your default region selector is now %s0.", "WorldEdit.Selector"),
TIMEZONE_SET("Timezone set for this session to: %s0", "WorldEdit.Timezone"),
TIMEZONE_DISPLAY("The current time in that timezone is: %s0", "WorldEdit.Timezone"),
COMMAND_INVALID_SYNTAX("The command was not used properly (no more help available).", "WorldEdit.Command"),
@ -222,7 +249,7 @@ public enum BBC {
WHOOSH("Whoosh!", "Navigation"),
POOF("Poof!", "Navigation"),
THRU_FAIL("No free spot ahead of you found.", "Navigation"),
JUMPTO_FAIL("No block in sight!", "Navigation"),
NO_BLOCK("No block in sight! (or too far)", "Navigation"),
UP_FAIL("You would hit something above you.", "Navigation"),
SEL_CUBOID("Cuboid: left click for point 1, right click for point 2", "Selection"),

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.configuration.MemorySection;
import com.boydti.fawe.configuration.file.YamlConfiguration;
import com.boydti.fawe.util.StringMan;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintWriter;
import java.lang.annotation.ElementType;
@ -22,6 +23,10 @@ import java.util.Map;
public class Config {
public Config() {
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0);
}
/**
* Get the value for a node<br>
* Probably throws some error if you try to get a non existent key
@ -220,7 +225,7 @@ public class Config {
return value != null ? value.toString() : "null";
}
private void save(PrintWriter writer, Class clazz, Object instance, int indent) {
private void save(PrintWriter writer, Class clazz, final Object instance, int indent) {
try {
String CTRF = System.lineSeparator();
String spacing = StringMan.repeat(" ", indent);

View File

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

View File

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

View File

@ -5,11 +5,11 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.SetQueue;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorCompletionService;
public class DefaultFaweQueueMap implements IFaweQueueMap {
@ -20,12 +20,14 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
this.parent = parent;
}
/**
* Map of chunks in the queue
*/
public final ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<Long, FaweChunk>(8, 0.9f, 1) {
public final Long2ObjectOpenHashMap<FaweChunk> blocks = new Long2ObjectOpenHashMap<FaweChunk>() {
@Override
public FaweChunk put(Long key, FaweChunk value) {
return put((long) key, value);
}
@Override
public FaweChunk put(long key, FaweChunk value) {
if (parent.getProgressTask() != null) {
try {
parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1);
@ -33,7 +35,9 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
e.printStackTrace();
}
}
return super.put(key, value);
synchronized (this) {
return super.put(key, value);
}
}
};
@ -109,67 +113,69 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
@Override
public boolean next(int amount, ExecutorCompletionService pool, long time) {
try {
boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE;
int added = 0;
Iterator<Map.Entry<Long, FaweChunk>> iter = blocks.entrySet().iterator();
if (amount == 1) {
long start = System.currentTimeMillis();
do {
if (iter.hasNext()) {
FaweChunk chunk = iter.next().getValue();
if (skip && chunk == lastWrappedChunk) {
continue;
}
iter.remove();
parent.start(chunk);
chunk.call();
parent.end(chunk);
} else {
break;
}
} while (System.currentTimeMillis() - start < time);
} else {
boolean result = true;
// amount = 8;
for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) {
Map.Entry<Long, FaweChunk> item = iter.next();
FaweChunk chunk = item.getValue();
if (skip && chunk == lastWrappedChunk) {
i--;
added--;
continue;
}
iter.remove();
parent.start(chunk);
pool.submit(chunk);
}
// if result, then submitted = amount
if (result) {
synchronized (blocks) {
try {
boolean skip = parent.getStage() == SetQueue.QueueStage.INACTIVE;
int added = 0;
Iterator<Map.Entry<Long, FaweChunk>> iter = blocks.entrySet().iterator();
if (amount == 1) {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < time && result) {
if (result = iter.hasNext()) {
Map.Entry<Long, FaweChunk> item = iter.next();
FaweChunk chunk = item.getValue();
do {
if (iter.hasNext()) {
FaweChunk chunk = iter.next().getValue();
if (skip && chunk == lastWrappedChunk) {
continue;
}
iter.remove();
parent.start(chunk);
pool.submit(chunk);
FaweChunk fc = ((FaweChunk) pool.take().get());
parent.end(fc);
chunk.call();
parent.end(chunk);
} else {
break;
}
} while (System.currentTimeMillis() - start < time);
} else {
boolean result = true;
// amount = 8;
for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) {
Map.Entry<Long, FaweChunk> item = iter.next();
FaweChunk chunk = item.getValue();
if (skip && chunk == lastWrappedChunk) {
i--;
added--;
continue;
}
iter.remove();
parent.start(chunk);
pool.submit(chunk);
}
// if result, then submitted = amount
if (result) {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < time && result) {
if (result = iter.hasNext()) {
Map.Entry<Long, FaweChunk> item = iter.next();
FaweChunk chunk = item.getValue();
if (skip && chunk == lastWrappedChunk) {
continue;
}
iter.remove();
parent.start(chunk);
pool.submit(chunk);
FaweChunk fc = ((FaweChunk) pool.take().get());
parent.end(fc);
}
}
}
for (int i = 0; i < added; i++) {
FaweChunk fc = ((FaweChunk) pool.take().get());
parent.end(fc);
}
}
for (int i = 0; i < added; i++) {
FaweChunk fc = ((FaweChunk) pool.take().get());
parent.end(fc);
}
} catch (Throwable e) {
e.printStackTrace();
}
} catch (Throwable e) {
e.printStackTrace();
return !blocks.isEmpty();
}
return !blocks.isEmpty();
}
}

View File

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

View File

@ -3,17 +3,15 @@ package com.boydti.fawe.example;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.World;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public abstract class NMSMappedFaweQueue<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;
@ -60,10 +58,13 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
@Override
public void end(FaweChunk chunk) {
super.end(chunk);
if (Settings.IMP.LIGHTING.MODE == 0 || !Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
if (Settings.IMP.LIGHTING.MODE == 0) {
sendChunk(chunk);
return;
}
if (!Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
sendChunk(chunk);
}
if (Settings.IMP.LIGHTING.MODE == 2) {
relighter.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask());
return;
@ -90,7 +91,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
}
if (relight) {
relighter.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask());
} else {
} else if (Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) {
sendChunk(chunk);
}
}
@ -148,19 +149,23 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) {
lastChunkX = cx;
lastChunkZ = cz;
if (!ensureChunkLoaded(cx, cz)) {
if (cx != lastSectionX || cz != lastSectionZ) {
lastSectionX = cx;
lastSectionZ = cz;
lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
} else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy);
} else {
return;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
if (lastSection == null) {
return;
@ -172,19 +177,23 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
int cx = x >> 4;
int cz = z >> 4;
int cy = y >> 4;
if (cx != lastChunkX || cz != lastChunkZ) {
lastChunkX = cx;
lastChunkZ = cz;
if (!ensureChunkLoaded(cx, cz)) {
if (cx != lastSectionX || cz != lastSectionZ) {
lastSectionX = cx;
lastSectionZ = cz;
lastChunk = ensureChunkLoaded(cx, cz);
if (lastChunk != null) {
lastChunkSections = getSections(lastChunk);
lastSection = getCachedSection(lastChunkSections, cy);
} else {
lastChunkSections = null;
return;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
} else if (cy != lastSectionY) {
if (lastChunkSections != null) {
lastSection = getCachedSection(lastChunkSections, cy);
} else {
return;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
if (lastSection == null) {
return;
@ -199,24 +208,4 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
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 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.IntegerTrio;
import com.boydti.fawe.util.MathMan;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@ -14,15 +16,14 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
public class NMSRelighter implements Relighter{
private final NMSMappedFaweQueue queue;
private final Map<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 HashMap<Long, Integer> chunksToSend;
private final Map<Long, Integer> chunksToSend;
private final int maxY;
private volatile boolean relighting = false;
@ -33,9 +34,9 @@ public class NMSRelighter implements Relighter{
public NMSRelighter(NMSMappedFaweQueue queue) {
this.queue = queue;
this.skyToRelight = new ConcurrentHashMap<>();
this.lightQueue = new ConcurrentHashMap<>();
chunksToSend = new HashMap<>();
this.skyToRelight = new Long2ObjectOpenHashMap<>();
this.lightQueue = new Long2ObjectOpenHashMap<>();
this.chunksToSend = new Long2ObjectOpenHashMap<>();
this.maxY = queue.getMaxY();
}
@ -63,7 +64,6 @@ public class NMSRelighter implements Relighter{
Iterator<Map.Entry<Long, RelightSkyEntry>> iter = skyToRelight.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Long, RelightSkyEntry> entry = iter.next();
iter.remove();
RelightSkyEntry chunk = entry.getValue();
long pair = entry.getKey();
Integer existing = chunksToSend.get(pair);
@ -71,10 +71,11 @@ public class NMSRelighter implements Relighter{
queue.ensureChunkLoaded(chunk.x, chunk.z);
Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z);
queue.removeLighting(sections, FaweQueue.RelightMode.ALL, queue.hasSky());
iter.remove();
}
}
public void updateBlockLight(Map<Long, Map<Short, Object>> map) {
public void updateBlockLight(Map<Long, Map<Integer, Object>> map) {
int size = map.size();
if (size == 0) {
return;
@ -84,17 +85,16 @@ public class NMSRelighter implements Relighter{
Map<IntegerTrio, Object> visited = 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) {
Map.Entry<Long, Map<Short, Object>> entry = iter.next();
iter.remove();
Map.Entry<Long, Map<Integer, Object>> entry = iter.next();
long index = entry.getKey();
Map<Short, Object> blocks = entry.getValue();
Map<Integer, Object> blocks = entry.getValue();
int chunkX = MathMan.unpairIntX(index);
int chunkZ = MathMan.unpairIntY(index);
int bx = chunkX << 4;
int bz = chunkZ << 4;
for (short blockHash : blocks.keySet()) {
for (int blockHash : blocks.keySet()) {
int x = (blockHash >> 12 & 0xF) + bx;
int y = (blockHash & 0xFF);
int z = (blockHash >> 8 & 0xF) + bz;
@ -114,6 +114,7 @@ public class NMSRelighter implements Relighter{
}
}
}
iter.remove();
}
while (!lightRemovalQueue.isEmpty()) {
@ -192,12 +193,12 @@ public class NMSRelighter implements Relighter{
public void addLightUpdate(int x, int y, int z) {
long index = MathMan.pairInt((int) x >> 4, (int) z >> 4);
Map<Short, Object> currentMap = lightQueue.get(index);
Map<Integer, Object> currentMap = lightQueue.get(index);
if (currentMap == null) {
currentMap = new ConcurrentHashMap<>(8, 0.9f, 1);
currentMap = new Int2ObjectOpenHashMap<>();
this.lightQueue.put(index, currentMap);
}
currentMap.put(MathMan.tripleBlockCoord(x, y, z), present);
currentMap.put((int) MathMan.tripleBlockCoord(x, y, z), present);
}
public synchronized void fixLightingSafe(boolean sky) {
@ -222,10 +223,10 @@ public class NMSRelighter implements Relighter{
Map.Entry<Long, Integer> entry = iter.next();
long pair = entry.getKey();
int bitMask = entry.getValue();
iter.remove();
int x = MathMan.unpairIntX(pair);
int z = MathMan.unpairIntY(pair);
queue.sendChunk(x, z, bitMask);
iter.remove();
}
}
@ -239,9 +240,9 @@ public class NMSRelighter implements Relighter{
Iterator<Map.Entry<Long, RelightSkyEntry>> iter = skyToRelight.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Long, RelightSkyEntry> entry = iter.next();
iter.remove();
chunksToSend.put(entry.getKey(), entry.getValue().bitmask);
chunksList.add(entry.getValue());
iter.remove();
}
Collections.sort(chunksList);
int size = chunksList.size();
@ -312,7 +313,6 @@ public class NMSRelighter implements Relighter{
int brightness = MathMan.unpair16y(pair);
if (brightness > 1 && (brightness != 15 || opacity != 15)) {
addLightUpdate(bx + x, y, bz + z);
// lightBlock(bx + x, y, bz + z, brightness);
}
switch (value) {
case 0:

View File

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

View File

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

View File

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

View File

@ -41,6 +41,32 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
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) {
File folder = getSaveFolder();
final ForkJoinPool pool = new ForkJoinPool();
@ -154,11 +180,6 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
throw new UnsupportedOperationException("Not supported");
}
@Override
public MCAChunk getChunk(FaweQueue faweQueue, int x, int z) {
return (MCAChunk) getFaweChunk(x, z);
}
@Override
public FaweQueue getImpWorld() {
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
public FaweChunk getFaweChunk(int cx, int cz) {
return getFaweQueueMap().getFaweChunk(cx, cz);
@ -274,11 +290,6 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
return hasSky;
}
@Override
public boolean loadChunk(FaweQueue faweQueue, int x, int z, boolean generate) {
return true;
}
@Override
public MCAChunk getCachedSections(FaweQueue faweQueue, int cx, int cz) {
return (MCAChunk) getFaweQueueMap().getFaweChunk(cx, cz);

View File

@ -41,8 +41,14 @@ public class ChangeSetFaweQueue extends DelegateFaweQueue {
@Override
public boolean setBiome(int x, int z, BaseBiome biome) {
// TODO undo biome change
return super.setBiome(x, z, biome);
if (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

View File

@ -144,6 +144,8 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
return ids;
}
public abstract byte[] getBiomeArray();
public char[][] getCombinedIdArrays() {
char[][] ids = new char[HEIGHT >> 4][];
for (int y = 0; y < HEIGHT >> 4; y++) {
@ -272,7 +274,11 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
*/
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>

View File

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

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
@ -15,6 +16,7 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
@ -133,6 +135,17 @@ public class HistoryExtent extends AbstractDelegateExtent {
return newList;
}
@Override
public boolean setBiome(Vector2D position, BaseBiome newBiome) {
BaseBiome oldBiome = this.getBiome(position);
if (oldBiome.getId() != newBiome.getId()) {
this.changeSet.addBiomeChange(position.getBlockX(), position.getBlockZ(), oldBiome, newBiome);
return extent.setBiome(position, newBiome);
} else {
return false;
}
}
private class TrackedEntity implements Entity {
private final Entity entity;

View File

@ -5,6 +5,7 @@ import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.ArrayList;
import java.util.Iterator;
@ -47,6 +48,11 @@ public class NullChangeSet extends FaweChangeSet {
}
@Override
public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) {
}
@Override
public void addChangeTask(FaweQueue queue) {

View File

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

View File

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

View File

@ -42,12 +42,12 @@ public class HeightBrush implements DoubleActionBrush {
@Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
int size = (int) (action == DoubleActionBrushTool.BrushAction.PRIMARY ? sizeDouble : -sizeDouble);
int size = (int) sizeDouble;
Mask mask = tool.getMask();
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null;
}
heightMap.setSize(size);
heightMap.apply(editSession, mask, position, size, rotation, yscale, true);
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true);
}
}

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

View File

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

View File

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

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.changeset.ChangeSet;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@ -119,6 +120,7 @@ public abstract class FaweChangeSet implements ChangeSet {
public abstract void addTileRemove(CompoundTag tag);
public abstract void addEntityRemove(CompoundTag tag);
public abstract void addEntityCreate(CompoundTag tag);
public abstract void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to);
public Iterator<Change> getIterator(BlockBag blockBag, int mode, boolean redo) {
return getIterator(redo);
}
@ -227,79 +229,81 @@ public abstract class FaweChangeSet implements ChangeSet {
int cz = previous.getZ();
int bx = cx << 4;
int bz = cz << 4;
// Biome changes
{
// TODO
}
// Block changes
// Current blocks
// char[][] currentIds = next.getCombinedIdArrays();
// Previous blocks in modified sections (i.e. we skip sections that weren't modified)
// char[][] previousIds = previous.getCombinedIdArrays();
for (int layer = 0; layer < layers; layer++) {
char[] currentLayer = next.getIdArray(layer);
char[] previousLayer = previous.getIdArray(layer);
if (currentLayer == null) {
continue;
}
int startY = layer << 4;
for (int y = 0; y < 16; y++) {
short[][] i1 = FaweCache.CACHE_J[y];
int yy = y + startY;
synchronized (FaweChangeSet.this) {
// Biome changes
if (previous.getBiomeArray() != null) {
byte[] previousBiomes = previous.getBiomeArray();
byte[] nextBiomes = next.getBiomeArray();
int index = 0;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
short[] i2 = i1[z];
int zz = bz + z;
for (int x = 0; x < 16; x++) {
int xx = x + bx;
int index = i2[x];
int combinedIdCurrent = currentLayer[index];
switch (combinedIdCurrent) {
case 0:
continue;
case 1:
combinedIdCurrent = 0;
default:
char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0;
if (combinedIdCurrent != combinedIdPrevious) {
synchronized (FaweChangeSet.this) {
byte idFrom = previousBiomes[index];
byte idTo = nextBiomes[index];
if (idFrom != idTo && idTo != 0) {
addBiomeChange(bx + x, zz, FaweCache.getBiome(idFrom & 0xFF), FaweCache.getBiome(idTo & 0xFF));
}
index++;
}
}
// TODO
}
// Block changes
for (int layer = 0; layer < layers; layer++) {
char[] currentLayer = next.getIdArray(layer);
char[] previousLayer = previous.getIdArray(layer);
if (currentLayer == null) {
continue;
}
int startY = layer << 4;
for (int y = 0; y < 16; y++) {
short[][] i1 = FaweCache.CACHE_J[y];
int yy = y + startY;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
short[] i2 = i1[z];
for (int x = 0; x < 16; x++) {
int xx = x + bx;
int index = i2[x];
int combinedIdCurrent = currentLayer[index];
switch (combinedIdCurrent) {
case 0:
continue;
case 1:
combinedIdCurrent = 0;
default:
char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0;
if (combinedIdCurrent != combinedIdPrevious) {
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
}
}
}
}
}
}
}
}
// Tile changes
{
// Tiles created
Map<Short, CompoundTag> tiles = next.getTiles();
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
synchronized (FaweChangeSet.this) {
// Tile changes
{
// Tiles created
Map<Short, CompoundTag> tiles = next.getTiles();
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
addTileCreate(entry.getValue());
}
}
// Tiles removed
tiles = previous.getTiles();
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
synchronized (FaweChangeSet.this) {
// Tiles removed
tiles = previous.getTiles();
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
addTileRemove(entry.getValue());
}
}
}
// Entity changes
{
// Entities created
Set<CompoundTag> entities = next.getEntities();
for (CompoundTag entityTag : entities) {
synchronized (FaweChangeSet.this) {
// Entity changes
{
// Entities created
Set<CompoundTag> entities = next.getEntities();
for (CompoundTag entityTag : entities) {
addEntityCreate(entityTag);
}
}
// Entities removed
entities = previous.getEntities();
for (CompoundTag entityTag : entities) {
synchronized (FaweChangeSet.this) {
// Entities removed
entities = previous.getEntities();
for (CompoundTag entityTag : entities) {
addEntityRemove(entityTag);
}
}

View File

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

View File

@ -21,11 +21,14 @@ import java.io.OutputStream;
*/
public class MemoryOptimizedHistory extends FaweStreamChangeSet {
private int size = 0;
private byte[][] ids;
private FastByteArrayOutputStream idsStream;
private FaweOutputStream idsStreamZip;
private byte[][] biomes;
private FastByteArrayOutputStream biomeStream;
private FaweOutputStream biomeStreamZip;
private byte[][] entC;
private FastByteArrayOutputStream entCStream;
private NBTOutputStream entCStreamZip;
@ -57,11 +60,16 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
try {
if (idsStream != null) {
idsStreamZip.close();
size = idsStream.getSize();
ids = idsStream.toByteArrays();
idsStream = null;
idsStreamZip = null;
}
if (biomeStream != null) {
biomeStreamZip.close();
biomes = biomeStream.toByteArrays();
biomeStream = null;
biomeStreamZip = null;
}
if (entCStream != null) {
entCStreamZip.close();
entC = entCStream.toByteArrays();
@ -125,6 +133,27 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
}
}
@Override
public InputStream getBiomeIS() throws IOException {
if (biomes == null) {
return null;
}
FaweInputStream result = MainUtil.getCompressedIS(new FastByteArraysInputStream(biomes));
return result;
}
@Override
public OutputStream getBiomeOS() throws IOException {
if (biomeStreamZip != null) {
return biomeStreamZip;
}
synchronized (this) {
biomeStream = new FastByteArrayOutputStream(Settings.IMP.HISTORY.BUFFER_SIZE);
biomeStreamZip = getCompressedOS(biomeStream);
return biomeStreamZip;
}
}
@Override
public InputStream getBlockIS() throws IOException {
if (ids == null) {

View File

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

View File

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

View File

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

View File

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

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.Extent;
import com.sk89q.worldedit.extent.MaskingExtent;
import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
import com.sk89q.worldedit.function.GroundFunction;
@ -92,7 +91,6 @@ import com.sk89q.worldedit.function.mask.RegionMask;
import com.sk89q.worldedit.function.operation.ChangeSetExecutor;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Patterns;
@ -1543,6 +1541,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
public boolean canBypassAll(Region region, boolean get, boolean set) {
if (wrapped) return false;
FaweRegionExtent regionExtent = getRegionExtent();
if (!(region instanceof CuboidRegion)) return false;
if (regionExtent != null) {
if (!(region instanceof CuboidRegion)) return false;
Vector pos1 = region.getMinimumPoint();
@ -1950,7 +1949,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
checkNotNull(dir);
checkArgument(distance >= 1, "distance >= 1 required");
final Vector displace = dir.multiply(distance);
// Remove the original blocks
final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
final Vector to = region.getMinimumPoint();
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to);
final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? new BlockPattern(replacement) : new BlockPattern(new BaseBlock(BlockID.AIR));
final BlockReplace remove = new BlockReplace(EditSession.this, pattern) {
@Override
@ -1966,12 +1969,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
};
// Copy to a buffer so we don't destroy our original before we can copy all the blocks from it
final ForgetfulExtentBuffer buffer = new ForgetfulExtentBuffer(EditSession.this, new RegionMask(region));
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, buffer, region.getMinimumPoint());
copy.setSourceFunction(remove);
copy.setRepetitions(1);
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
copy.setSourceFunction(remove); // Remove
copy.setRemovingEntities(true);
Mask sourceMask = getSourceMask();
if (sourceMask != null) {
new MaskTraverser(sourceMask).reset(EditSession.this);
@ -1981,13 +1981,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this));
}
// Then we need to copy the buffer to the world
final BlockReplace replace = new BlockReplace(EditSession.this, buffer);
final RegionVisitor visitor = new RegionVisitor(buffer.asRegion(), replace);
final OperationQueue operation = new OperationQueue(copy, visitor);
Operations.completeSmart(operation, new Runnable() {
Operations.completeSmart(copy, new Runnable() {
@Override
public void run() {
EditSession.this.flushQueue();

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();
List<BaseBiome> biomes = biomeRegistry.getBiomes();
int totalPages = biomes.size() / 19 + 1;
player.print(BBC.getPrefix() + "Available Biomes (page " + page + "/" + totalPages + ") :");
BBC.BIOME_LIST_HEADER.send(player, page, totalPages);
for (BaseBiome biome : biomes) {
if (offset > 0) {
offset--;
@ -106,7 +106,7 @@ public class BiomeCommands {
break;
}
} else {
player.print(BBC.getPrefix() + " <unknown #" + biome.getId() + ">");
player.print(BBC.getPrefix() + " <? #" + biome.getId() + ">");
}
}
}
@ -132,19 +132,15 @@ public class BiomeCommands {
if (args.hasFlag('t')) {
Vector blockPosition = player.getBlockTrace(300);
if (blockPosition == null) {
player.printError("No block in sight!");
BBC.NO_BLOCK.send(player);
return;
}
BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D());
biomes.add(biome);
qualifier = "at line of sight point";
} else if (args.hasFlag('p')) {
BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D());
biomes.add(biome);
qualifier = "at your position";
} else {
World world = player.getWorld();
Region region = session.getSelection(world);
@ -158,17 +154,15 @@ public class BiomeCommands {
biomes.add(world.getBiome(pt.toVector2D()));
}
}
qualifier = "in your selection";
}
player.print(biomes.size() != 1 ? "Biomes " + qualifier + ":" : "Biome " + qualifier + ":");
BBC.BIOME_LIST_HEADER.send(player, 1, 1);
for (BaseBiome biome : biomes) {
BiomeData data = biomeRegistry.getData(biome);
if (data != null) {
player.print(BBC.getPrefix() + " " + data.getName());
} else {
player.print(BBC.getPrefix() + " <unknown #" + biome.getId() + ">");
player.print(BBC.getPrefix() + " <? #" + biome.getId() + ">");
}
}
}
@ -204,7 +198,7 @@ public class BiomeCommands {
FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace);
Operations.completeLegacy(visitor);
player.print(BBC.getPrefix() + "Biomes were changed in " + visitor.getAffected() + " columns. You may have to rejoin your game (or close and reopen your world) to see a change.");
BBC.BIOME_CHANGED.send(player, visitor.getAffected());
}
public static Class<BiomeCommands> inject() {

View File

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

View File

@ -42,7 +42,6 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
@ -233,7 +232,7 @@ public class ClipboardCommands {
public void download(final Player player, final LocalSession session, @Optional("schematic") final String formatName) throws CommandException, WorldEditException {
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (format == null) {
player.printError("Unknown schematic format: " + formatName);
BBC.CLIPBOARD_INVALID_FORMAT.send(player, formatName);
return;
}
ClipboardHolder holder = session.getClipboard();
@ -467,32 +466,6 @@ public class ClipboardCommands {
BBC.COMMAND_FLIPPED.send(player);
}
@Command(
aliases = { "/load" },
usage = "<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(
aliases = { "clearclipboard" },
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.CommandPermissions;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
@ -55,36 +54,6 @@ public class GeneralCommands {
}
}
@Command(
aliases = { "/limit" },
usage = "<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(
aliases = { "/fast" },
usage = "[on|off]",
@ -98,20 +67,20 @@ public class GeneralCommands {
String newState = args.getString(0, null);
if (session.hasFastMode()) {
if ("on".equals(newState)) {
player.printError("Fast mode already enabled.");
BBC.FAST_ENABLED.send(player);
return;
}
session.setFastMode(false);
player.print(BBC.getPrefix() + "Fast mode disabled.");
BBC.FAST_DISABLED.send(player);
} else {
if ("off".equals(newState)) {
player.printError("Fast mode already disabled.");
BBC.FAST_DISABLED.send(player);
return;
}
session.setFastMode(true);
player.print(BBC.getPrefix() + "Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.");
BBC.FAST_ENABLED.send(player);
}
}
@ -197,9 +166,9 @@ public class GeneralCommands {
public void togglePlace(Player player, LocalSession session, CommandContext args) throws WorldEditException {
if (session.togglePlacementPosition()) {
player.print(BBC.getPrefix() + "Now placing at pos #1.");
BBC.PLACE_ENABLED.send(player);
} else {
player.print(BBC.getPrefix() + "Now placing at the block you stand in.");
BBC.PLACE_DISABLED.send(player);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -442,7 +442,7 @@ public class UtilityCommands {
killed += visitor.getAffected();
}
actor.print(BBC.getPrefix() + "Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + ".");
BBC.KILL_SUCCESS.send(actor, killed, radius);
if (editSession != null) {
session.remember(editSession);
@ -502,7 +502,7 @@ public class UtilityCommands {
removed += visitor.getAffected();
}
actor.print(BBC.getPrefix() + "Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal.");
BBC.KILL_SUCCESS.send(removed, radius);
if (editSession != null) {
session.remember(editSession);

View File

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

View File

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

View File

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

View File

@ -22,7 +22,7 @@ package com.sk89q.worldedit.extension.factory;
import com.boydti.fawe.jnbt.JSON2NBT;
import com.boydti.fawe.jnbt.NBTException;
import com.boydti.fawe.util.MathMan;
import com.intellectualcrafters.plot.util.StringMan;
import com.boydti.fawe.util.StringMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.BlockVector;

View File

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

View File

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

View File

@ -28,8 +28,8 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
@ -315,18 +315,60 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
@Override
public Set<Vector2D> getChunks() {
Set<Vector2D> chunks = new LinkedHashSet<Vector2D>();
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
final int maxX = max.getBlockX() >> ChunkStore.CHUNK_SHIFTS;
final int minX = min.getBlockX() >> ChunkStore.CHUNK_SHIFTS;
final int maxZ = max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS;
final int minZ = min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS;
final int size = (maxX - minX + 1) * (maxZ - minZ + 1);
for (int x = max.getBlockX() >> ChunkStore.CHUNK_SHIFTS; x >= min.getBlockX() >> ChunkStore.CHUNK_SHIFTS; --x) {
for (int z = max.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; z >= min.getBlockZ() >> ChunkStore.CHUNK_SHIFTS; --z) {
chunks.add(new Vector2D(x, z));
return new AbstractSet<Vector2D>() {
@Override
public Iterator<Vector2D> iterator() {
return new Iterator<Vector2D>() {
private Vector2D pos = new Vector2D(minX, minZ);
@Override
public boolean hasNext() {
return pos != null;
}
@Override
public Vector2D next() {
Vector2D result = pos;
// calc next
if (pos.getX() < maxX) {
pos = new Vector2D(pos.getX() + 1, pos.getZ());
} else if (pos.getZ() < maxZ) {
pos = new Vector2D(minX, pos.getZ() + 1);
} else {
pos = null;
}
return result;
}
@Override
public void remove() {
throw new UnsupportedOperationException("This set is immutable.");
}
};
}
}
return chunks;
@Override
public int size() {
return size;
}
@Override
public boolean contains(Object o) {
if (o instanceof Vector2D) {
Vector2D cv = (Vector2D) o;
return cv.getX() >= minX && cv.getX() <= maxX && cv.getZ() >= minZ && cv.getZ() <= maxZ;
} else {
return false;
}
}
};
}
@Override

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,6 +23,7 @@ jar.enabled = false
shadowJar {
dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency('co.aikar:fastutil-lite:1.0'))
include(dependency(name: 'worldedit-core-6.1.4-SNAPSHOT-dist'))
include(dependency('com.google.code.gson:gson:2.2.4'))
include(dependency('org.yaml:snakeyaml:1.16'))

View File

@ -28,9 +28,6 @@ public class FaweNukkit implements IFawe, Listener {
private final NukkitWorldEdit plugin;
public FaweNukkit(NukkitWorldEdit mod) {
Settings.IMP.HISTORY.USE_DISK = true;
Settings.IMP.CLIPBOARD.USE_DISK = true;
Settings.IMP.HISTORY.COMPRESSION_LEVEL = 9;
this.plugin = mod;
FaweChunk.HEIGHT = 128;
plugin.getServer().getPluginManager().registerEvents(this, plugin);

View File

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

View File

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

View File

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

View File

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