Fix removal of light sources

This commit is contained in:
Jesse Boyd 2016-11-28 14:34:12 +11:00
parent 951a6a88b9
commit 5b0ce58f6b
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
22 changed files with 13637 additions and 4737 deletions

17473
blocks.json

File diff suppressed because it is too large Load Diff

View File

@ -31,19 +31,19 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
super(parent, x, z);
}
public BukkitChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, short[] relight, byte[] heightMap) {
super(parent, x, z, ids, count, air, relight, heightMap);
public BukkitChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(parent, x, z, ids, count, air, heightMap);
}
@Override
public CharFaweChunk copy(boolean shallow) {
BukkitChunk_All copy;
if (shallow) {
copy = new BukkitChunk_All(getParent(), getX(), getZ(), ids, count, air, relight, heightMap);
copy = new BukkitChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new BukkitChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), relight.clone(), heightMap.clone());
copy = new BukkitChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
@ -130,7 +130,6 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
try {
// Efficiently merge sections
int changes = getCount(layer);
int lighting = getRelight(layer);
if (changes == 0) {
continue;
}
@ -141,7 +140,7 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
final byte[] cacheX = FaweCache.CACHE_X[layer];
final short[] cacheY = FaweCache.CACHE_Y[layer];
final byte[] cacheZ = FaweCache.CACHE_Z[layer];
boolean checkTime = !((getAir(layer) == 4096 || (getCount(layer) == 4096 && getAir(layer) == 0) || (getCount(layer) == getAir(layer))) && getRelight(layer) == 0);
boolean checkTime = !((getAir(layer) == 4096 || (getCount(layer) == 4096 && getAir(layer) == 0) || (getCount(layer) == getAir(layer))));
if (!checkTime) {
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int k = 0; k < 16; k++) {

View File

@ -76,7 +76,6 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
public static void checkVersion(String supported) {
String version = Bukkit.getServer().getClass().getPackage().getName();
if (!version.contains(supported)) {
Fawe.debug("This version of FAWE is for: " + supported);
throw new IllegalStateException("Unsupported version: " + version + " (supports: " + supported + ")");
}
}
@ -120,17 +119,17 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
return world;
}
public void setupAdapter(BukkitImplAdapter adapter) {
public static void setupAdapter(BukkitImplAdapter adapter) {
try {
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
fieldAdapter.setAccessible(true);
if ((this.adapter = adapter) != null) {
if ((BukkitQueue_0.adapter = adapter) != null) {
fieldAdapter.set(instance, adapter);
} else {
this.adapter = (BukkitImplAdapter) fieldAdapter.get(instance);
BukkitQueue_0.adapter = (BukkitImplAdapter) fieldAdapter.get(instance);
}
for (Method method : this.adapter.getClass().getDeclaredMethods()) {
for (Method method : BukkitQueue_0.adapter.getClass().getDeclaredMethods()) {
switch (method.getName()) {
case "toNative":
methodToNative = method;

View File

@ -59,19 +59,19 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
super(parent, x, z);
}
public BukkitChunk_1_10(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, short[] relight, byte[] heightMap) {
super(parent, x, z, ids, count, air, relight, heightMap);
public BukkitChunk_1_10(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(parent, x, z, ids, count, air, heightMap);
}
@Override
public CharFaweChunk copy(boolean shallow) {
BukkitChunk_1_10 copy;
if (shallow) {
copy = new BukkitChunk_1_10(getParent(), getX(), getZ(), ids, count, air, relight, heightMap);
copy = new BukkitChunk_1_10(getParent(), getX(), getZ(), ids, count, air, heightMap);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new BukkitChunk_1_10(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), relight.clone(), heightMap.clone());
copy = new BukkitChunk_1_10(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
@ -181,6 +181,8 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
try {
final Chunk chunk = this.getChunk();
final World world = chunk.getWorld();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
final boolean flag = world.getEnvironment() == World.Environment.NORMAL;
net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
nmsChunk.f(true); // Set Modified
@ -349,8 +351,10 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
}
continue;
}
int by = j << 4;
DataPaletteBlock nibble = section.getBlocks();
int nonEmptyBlockCount = 0;
IBlockData existing;
for (int y = 0; y < 16; y++) {
short[][] i1 = FaweCache.CACHE_J[y];
for (int z = 0; z < 16; z++) {
@ -359,22 +363,32 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
char combinedId = array[i2[x]];
switch (combinedId) {
case 0:
IBlockData existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_10.air) {
nonEmptyBlockCount++;
}
continue;
case 1:
existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_10.air) {
if (existing.d() > 0) {
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
}
nonEmptyBlockCount--;
}
nibble.setBlock(x, y, z, BukkitQueue_1_10.air);
continue;
default:
nonEmptyBlockCount++;
existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_10.air) {
if (existing.d() > 0) {
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
}
} else {
nonEmptyBlockCount++;
}
nibble.setBlock(x, y, z, getParent().IBD_CACHE[(int) combinedId]);
}
}
}
}
getParent().setCount(0, nonEmptyBlockCount, section);
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
}
// Set biomes
int[][] biomes = this.biomes;
@ -395,8 +409,6 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
}
// Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();

View File

@ -41,17 +41,49 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
protected static IBlockData air;
protected static Field fieldBits;
protected static Method getEntitySlices;
protected static Field fieldTickingBlockCount;
protected static Field fieldNonEmptyBlockCount;
protected static Field fieldSection;
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE];
static {
try {
fieldSection = ChunkSection.class.getDeclaredField("blockIds");
fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount");
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
fieldSection.setAccessible(true);
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
fieldBits = DataPaletteBlock.class.getDeclaredField("b");
fieldBits.setAccessible(true);
getEntitySlices = net.minecraft.server.v1_10_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
if (adapter == null) {
setupAdapter(new com.boydti.fawe.bukkit.v1_10.FaweAdapter_1_10());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
for (int i = 0; i < Character.MAX_VALUE; i++) {
try {
IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF);
} catch (Throwable ignore) {}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public BukkitQueue_1_10(final com.sk89q.worldedit.world.World world) {
super(world);
init();
getImpWorld();
}
public BukkitQueue_1_10(final String world) {
super(world);
init();
getImpWorld();
}
@Override
@ -68,34 +100,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}
}
private void init() {
checkVersion("v1_10_R1");
if (air == null) {
try {
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
fieldBits = DataPaletteBlock.class.getDeclaredField("b");
fieldBits.setAccessible(true);
getEntitySlices = net.minecraft.server.v1_10_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
if (adapter == null) {
setupAdapter(new com.boydti.fawe.bukkit.v1_10.FaweAdapter_1_10());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
for (int i = 0; i < Character.MAX_VALUE; i++) {
try {
IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF);
} catch (Throwable ignore) {}
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
getImpWorld();
}
@Override
public boolean next(int amount, ExecutorCompletionService pool, long time) {
return super.next(amount, pool, time);
@ -357,19 +361,18 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
Class<? extends ChunkSection> clazz = section.getClass();
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException {
Field fieldSection = ChunkSection.class.getDeclaredField("blockIds");
fieldSection.setAccessible(true);
fieldSection.set(section, palette);
Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0);
}
public ChunkSection newChunkSection(int y2, boolean flag, char[] array) {

View File

@ -62,19 +62,19 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
super(parent, x, z);
}
public BukkitChunk_1_11(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, short[] relight, byte[] heightMap) {
super(parent, x, z, ids, count, air, relight, heightMap);
public BukkitChunk_1_11(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(parent, x, z, ids, count, air, heightMap);
}
@Override
public CharFaweChunk copy(boolean shallow) {
BukkitChunk_1_11 copy;
if (shallow) {
copy = new BukkitChunk_1_11(getParent(), getX(), getZ(), ids, count, air, relight, heightMap);
copy = new BukkitChunk_1_11(getParent(), getX(), getZ(), ids, count, air, heightMap);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new BukkitChunk_1_11(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), relight.clone(), heightMap.clone());
copy = new BukkitChunk_1_11(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
@ -184,13 +184,14 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
try {
final Chunk chunk = this.getChunk();
final World world = chunk.getWorld();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
final boolean flag = world.getEnvironment() == World.Environment.NORMAL;
net.minecraft.server.v1_11_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
nmsChunk.f(true); // Set Modified
nmsChunk.mustSave = true;
net.minecraft.server.v1_11_R1.World nmsWorld = nmsChunk.world;
ChunkSection[] sections = nmsChunk.getSections();
Class<? extends net.minecraft.server.v1_11_R1.Chunk> clazzChunk = nmsChunk.getClass();
final Collection<Entity>[] entities = (Collection<Entity>[]) getParent().getEntitySlices.invoke(nmsChunk);
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
// Set heightmap
@ -363,8 +364,10 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
}
continue;
}
int by = j << 4;
DataPaletteBlock nibble = section.getBlocks();
int nonEmptyBlockCount = 0;
IBlockData existing;
for (int y = 0; y < 16; y++) {
short[][] i1 = FaweCache.CACHE_J[y];
for (int z = 0; z < 16; z++) {
@ -373,22 +376,32 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
char combinedId = array[i2[x]];
switch (combinedId) {
case 0:
IBlockData existing = nibble.a(x, y, z);
if (existing != com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.air) {
nonEmptyBlockCount++;
}
continue;
case 1:
nibble.setBlock(x, y, z, com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.air);
existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_11.air) {
if (existing.d() > 0) {
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
}
nonEmptyBlockCount--;
}
nibble.setBlock(x, y, z, BukkitQueue_1_11.air);
continue;
default:
nonEmptyBlockCount++;
existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_11.air) {
if (existing.d() > 0) {
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
}
} else {
nonEmptyBlockCount++;
}
nibble.setBlock(x, y, z, getParent().IBD_CACHE[(int) combinedId]);
}
}
}
}
getParent().setCount(0, nonEmptyBlockCount, section);
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
}
// Set biomes
int[][] biomes = this.biomes;
@ -409,9 +422,6 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
}
// Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey();

View File

@ -41,17 +41,51 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
protected static IBlockData air;
protected static Field fieldBits;
protected static Method getEntitySlices;
protected static Field fieldTickingBlockCount;
protected static Field fieldNonEmptyBlockCount;
protected static Field fieldSection;
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE];
static {
try {
fieldSection = ChunkSection.class.getDeclaredField("blockIds");
fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount");
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
fieldSection.setAccessible(true);
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
fieldBits = DataPaletteBlock.class.getDeclaredField("b");
fieldBits.setAccessible(true);
getEntitySlices = net.minecraft.server.v1_11_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
if (adapter == null) {
setupAdapter(new com.boydti.fawe.bukkit.v1_11.FaweAdapter_1_11());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
for (int i = 0; i < Character.MAX_VALUE; i++) {
try {
IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF);
} catch (Throwable ignore) {}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public BukkitQueue_1_11(final com.sk89q.worldedit.world.World world) {
super(world);
init();
getImpWorld();
}
public BukkitQueue_1_11(final String world) {
super(world);
init();
getImpWorld();
}
@Override
@ -68,34 +102,6 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}
}
private void init() {
checkVersion("v1_11_R1");
if (air == null) {
try {
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
fieldBits = DataPaletteBlock.class.getDeclaredField("b");
fieldBits.setAccessible(true);
getEntitySlices = net.minecraft.server.v1_11_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
if (adapter == null) {
setupAdapter(new com.boydti.fawe.bukkit.v1_11.FaweAdapter_1_11());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
for (int i = 0; i < Character.MAX_VALUE; i++) {
try {
IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF);
} catch (Throwable ignore) {}
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
getImpWorld();
}
@Override
public boolean next(int amount, ExecutorCompletionService pool, long time) {
return super.next(amount, pool, time);
@ -357,19 +363,17 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
Class<? extends ChunkSection> clazz = section.getClass();
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException {
Field fieldSection = ChunkSection.class.getDeclaredField("blockIds");
fieldSection.setAccessible(true);
fieldSection.set(section, palette);
Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0);
}
public ChunkSection newChunkSection(int y2, boolean flag, char[] array) {

View File

@ -52,8 +52,8 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk, BukkitQueue17> {
this.datas = new NibbleArray[16];
}
public BukkitChunk_1_7(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, short[] relight, byte[] heightMap, byte[][] byteIds, NibbleArray[] datas) {
super(parent, x, z, ids, count, air, relight, heightMap);
public BukkitChunk_1_7(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap, byte[][] byteIds, NibbleArray[] datas) {
super(parent, x, z, ids, count, air, heightMap);
this.byteIds = byteIds;
this.datas = datas;
}
@ -62,11 +62,11 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk, BukkitQueue17> {
public CharFaweChunk copy(boolean shallow) {
BukkitChunk_1_7 copy;
if (shallow) {
copy = new BukkitChunk_1_7(getParent(), getX(), getZ(), ids, count, air, relight, heightMap, byteIds, datas);
copy = new BukkitChunk_1_7(getParent(), getX(), getZ(), ids, count, air, heightMap, byteIds, datas);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new BukkitChunk_1_7(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), relight.clone(), heightMap.clone(), (byte[][]) MainUtil.copyNd(byteIds), datas.clone());
copy = new BukkitChunk_1_7(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone(), (byte[][]) MainUtil.copyNd(byteIds), datas.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
@ -122,7 +122,7 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk, BukkitQueue17> {
case 62:
case 50:
case 10:
this.relight[i]++;
getParent().getRelighter().addLightUpdate((getX() << 4) + x, y, (getZ() << 4) + z);
default:
vs2[j] = (char) ((id << 4) + data);
vs[j] = (byte) id;

View File

@ -38,29 +38,31 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
protected static Field fieldData;
protected static Field fieldIds;
protected static Field fieldTickingBlockCount;
protected static Field fieldNonEmptyBlockCount;
static {
try {
fieldData = ChunkSection.class.getDeclaredField("blockData");
fieldData.setAccessible(true);
fieldIds = ChunkSection.class.getDeclaredField("blockIds");
fieldIds.setAccessible(true);
fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount");
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
public BukkitQueue17(final com.sk89q.worldedit.world.World world) {
super(world);
init();
getImpWorld();
}
public BukkitQueue17(final String world) {
super(world);
init();
}
private void init() {
checkVersion("v1_7_R4");
if (fieldData == null) {
try {
fieldData = ChunkSection.class.getDeclaredField("blockData");
fieldData.setAccessible(true);
fieldIds = ChunkSection.class.getDeclaredField("blockIds");
fieldIds.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
getImpWorld();
}
@ -229,16 +231,13 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
Class<? extends ChunkSection> clazz = section.getClass();
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
@Override
public void refreshChunk(FaweChunk fc) {

View File

@ -46,19 +46,19 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
super(parent, x, z);
}
public BukkitChunk_1_8(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, short[] relight, byte[] heightMap) {
super(parent, x, z, ids, count, air, relight, heightMap);
public BukkitChunk_1_8(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(parent, x, z, ids, count, air, heightMap);
}
@Override
public CharFaweChunk copy(boolean shallow) {
BukkitChunk_1_8 copy;
if (shallow) {
copy = new BukkitChunk_1_8(getParent(), getX(), getZ(), ids, count, air, relight, heightMap);
copy = new BukkitChunk_1_8(getParent(), getX(), getZ(), ids, count, air, heightMap);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new BukkitChunk_1_8(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), relight.clone(), heightMap.clone());
copy = new BukkitChunk_1_8(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
@ -80,6 +80,8 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
@Override
public FaweChunk call() {
CraftChunk chunk = (CraftChunk) this.getChunk();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle();
nmsChunk.f(true); // Modified
nmsChunk.mustSave = true;
@ -233,26 +235,43 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
sections[j] = section;
continue;
}
int by = j << 4;
char[] currentArray = section.getIdArray();
int solid = 0;
int existingId;
for (int k = 0; k < newArray.length; k++) {
char n = newArray[k];
switch (n) {
case 0:
continue;
case 1:
if (currentArray[k] > 1) {
solid++;
existingId = currentArray[k];
if (existingId > 1) {
if (FaweCache.hasLight(existingId)) {
int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k];
getParent().getRelighter().addLightUpdate(bx + x, y, bz + z);
}
solid--;
currentArray[k] = 0;
}
continue;
default:
solid++;
existingId = currentArray[k];
if (existingId <= 1) {
solid++;
} else if (FaweCache.hasLight(existingId)) {
int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k];
getParent().getRelighter().addLightUpdate(bx + x, y, bz + z);
}
currentArray[k] = n;
continue;
}
}
getParent().setCount(0, solid, section);
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + solid, section);
}
// Set biomes
@ -274,9 +293,6 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
}
// Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey();

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.bukkit.v1_8;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.example.CharFaweChunk;
@ -13,7 +12,6 @@ import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Arrays;
@ -39,26 +37,35 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
public static Field isDirty;
protected static Field fieldTickingBlockCount;
protected static Field fieldNonEmptyBlockCount;
protected static Field fieldSection;
protected static Field fieldChunkMap;
static {
try {
fieldSection = ChunkSection.class.getDeclaredField("blockIds");
fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount");
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
fieldChunkMap = PlayerChunkMap.class.getDeclaredField("d");
isDirty = ChunkSection.class.getDeclaredField("isDirty");
fieldSection.setAccessible(true);
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldChunkMap.setAccessible(true);
isDirty.setAccessible(true);
} catch (Throwable e) {
e.printStackTrace();
}
}
public BukkitQueue18R3(final com.sk89q.worldedit.world.World world) {
super(world);
checkVersion("v1_8_R3");
getImpWorld();
}
public BukkitQueue18R3(final String world) {
super(world);
checkVersion("v1_8_R3");
}
@Override
public void setupAdapter(BukkitImplAdapter adapter) {
if (this.adapter == null) {
try {
isDirty = ChunkSection.class.getDeclaredField("isDirty");
isDirty.setAccessible(true);
Fawe.debug("isDirty found");
} catch (Throwable e) {}
}
super.setupAdapter(adapter);
getImpWorld();
}
@ -225,15 +232,14 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
Class<? extends ChunkSection> clazz = section.getClass();
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
@Override
public void refreshChunk(FaweChunk fc) {
BukkitChunk_1_8 fs = (BukkitChunk_1_8) fc;
@ -251,8 +257,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
if (!chunkMap.isChunkInUse(x, z)) {
return;
}
Field fieldChunkMap = chunkMap.getClass().getDeclaredField("d");
fieldChunkMap.setAccessible(true);
LongHashMap<Object> map = (LongHashMap<Object>) fieldChunkMap.get(chunkMap);
long pair = (long) x + 2147483647L | (long) z + 2147483647L << 32;
Object playerChunk = map.getEntry(pair);

View File

@ -28,7 +28,6 @@ import java.util.Set;
import java.util.UUID;
import net.minecraft.server.v1_9_R2.Block;
import net.minecraft.server.v1_9_R2.BlockPosition;
import net.minecraft.server.v1_9_R2.Blocks;
import net.minecraft.server.v1_9_R2.ChunkSection;
import net.minecraft.server.v1_9_R2.DataBits;
import net.minecraft.server.v1_9_R2.DataPalette;
@ -61,19 +60,19 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
super(parent, x, z);
}
public BukkitChunk_1_9(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, short[] relight, byte[] heightMap) {
super(parent, x, z, ids, count, air, relight, heightMap);
public BukkitChunk_1_9(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(parent, x, z, ids, count, air, heightMap);
}
@Override
public CharFaweChunk copy(boolean shallow) {
BukkitChunk_1_9 copy;
if (shallow) {
copy = new BukkitChunk_1_9(getParent(), getX(), getZ(), ids, count, air, relight, heightMap);
copy = new BukkitChunk_1_9(getParent(), getX(), getZ(), ids, count, air, heightMap);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new BukkitChunk_1_9(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), relight.clone(), heightMap.clone());
copy = new BukkitChunk_1_9(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
@ -182,6 +181,8 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
public FaweChunk call() {
final Chunk chunk = (Chunk) this.getChunk();
final World world = chunk.getWorld();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
try {
final boolean flag = world.getEnvironment() == World.Environment.NORMAL;
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
@ -361,28 +362,40 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
fieldPalette.setAccessible(true);
DataPalette palette = (DataPalette) fieldPalette.get(nibble);
int nonEmptyBlockCount = 0;
IBlockData existing;
int by = j << 4;
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
switch (combinedId) {
case 0:
IBlockData existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_9_R1.air) {
nonEmptyBlockCount++;
}
continue;
case 1:
nibble.setBlock(x, y, z, Blocks.AIR.getBlockData());
existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_9_R1.air) {
if (existing.d() > 0) {
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
}
nonEmptyBlockCount--;
}
nibble.setBlock(x, y, z, BukkitQueue_1_9_R1.air);
continue;
default:
nonEmptyBlockCount++;
existing = nibble.a(x, y, z);
if (existing != BukkitQueue_1_9_R1.air) {
if (existing.d() > 0) {
getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
}
} else {
nonEmptyBlockCount++;
}
nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
}
}
}
}
getParent().setCount(0, nonEmptyBlockCount, section);
getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
}
// Set biomes
int[][] biomes = this.biomes;
@ -403,9 +416,6 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
}
// Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey();

View File

@ -23,7 +23,32 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import net.minecraft.server.v1_9_R2.*;
import net.minecraft.server.v1_9_R2.Block;
import net.minecraft.server.v1_9_R2.BlockPosition;
import net.minecraft.server.v1_9_R2.ChunkSection;
import net.minecraft.server.v1_9_R2.DataBits;
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
import net.minecraft.server.v1_9_R2.Entity;
import net.minecraft.server.v1_9_R2.EntityPlayer;
import net.minecraft.server.v1_9_R2.EntityTracker;
import net.minecraft.server.v1_9_R2.EntityTypes;
import net.minecraft.server.v1_9_R2.EnumDifficulty;
import net.minecraft.server.v1_9_R2.EnumSkyBlock;
import net.minecraft.server.v1_9_R2.IBlockData;
import net.minecraft.server.v1_9_R2.IDataManager;
import net.minecraft.server.v1_9_R2.MinecraftServer;
import net.minecraft.server.v1_9_R2.NBTTagCompound;
import net.minecraft.server.v1_9_R2.NibbleArray;
import net.minecraft.server.v1_9_R2.PacketPlayOutMapChunk;
import net.minecraft.server.v1_9_R2.PlayerChunk;
import net.minecraft.server.v1_9_R2.PlayerChunkMap;
import net.minecraft.server.v1_9_R2.ServerNBTManager;
import net.minecraft.server.v1_9_R2.TileEntity;
import net.minecraft.server.v1_9_R2.WorldData;
import net.minecraft.server.v1_9_R2.WorldManager;
import net.minecraft.server.v1_9_R2.WorldServer;
import net.minecraft.server.v1_9_R2.WorldSettings;
import net.minecraft.server.v1_9_R2.WorldType;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
@ -39,35 +64,41 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
protected static IBlockData air;
protected static Field fieldBits;
protected static Field fieldTickingBlockCount;
protected static Field fieldNonEmptyBlockCount;
protected static Field fieldSection;
static {
try {
fieldSection = ChunkSection.class.getDeclaredField("blockIds");
fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount");
fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
fieldSection.setAccessible(true);
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
fieldBits = DataPaletteBlock.class.getDeclaredField("b");
fieldBits.setAccessible(true);
if (adapter == null) {
setupAdapter(new FaweAdapter_1_9());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public BukkitQueue_1_9_R1(final com.sk89q.worldedit.world.World world) {
super(world);
init();
getImpWorld();
}
public BukkitQueue_1_9_R1(final String world) {
super(world);
init();
}
private void init() {
checkVersion("v1_9_R2");
if (air == null) {
try {
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
fieldBits = DataPaletteBlock.class.getDeclaredField("b");
fieldBits.setAccessible(true);
if (adapter == null) {
setupAdapter(new FaweAdapter_1_9());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
getImpWorld();
}
@ -310,19 +341,17 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
Class<? extends ChunkSection> clazz = section.getClass();
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException {
Field fieldSection = ChunkSection.class.getDeclaredField("blockIds");
fieldSection.setAccessible(true);
fieldSection.set(section, palette);
Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0);
}
public ChunkSection newChunkSection(int y2, boolean flag, char[] array) {

View File

@ -285,7 +285,6 @@ public class Fawe {
}
public void setupConfigs() {
// Setting up config.yml
File file = new File(this.IMP.getDirectory(), "config.yml");
Settings.PLATFORM = IMP.getPlatform().replace("\"", "");

View File

@ -7,7 +7,6 @@ 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.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -19,7 +18,6 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
public final char[][] ids;
public final short[] count;
public final short[] air;
public final short[] relight;
public final byte[] heightMap;
public int[][] biomes;
@ -29,12 +27,11 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
public T chunk;
public CharFaweChunk(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, short[] relight, byte[] heightMap) {
public CharFaweChunk(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(parent, x, z);
this.ids = ids;
this.count = count;
this.air = air;
this.relight = relight;
this.heightMap = heightMap;
}
@ -50,7 +47,6 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
this.ids = new char[HEIGHT >> 4][];
this.count = new short[HEIGHT >> 4];
this.air = new short[HEIGHT >> 4];
this.relight = new short[HEIGHT >> 4];
this.heightMap = new byte[256];
}
@ -92,15 +88,6 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
this.count[i] = value;
}
/**
* Get the number of block changes in a specified section
* @param i
* @return
*/
public int getRelight(final int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < count.length; i++) {
@ -109,19 +96,6 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
return total;
}
public int getTotalRelight() {
if ((this.getTotalCount() == 0) && (this.biomes == null)) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < relight.length; i++) {
total += this.relight[i];
}
return total;
}
@Override
public int getBitMask() {
int bitMask = 0;
@ -245,7 +219,7 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
case 62:
case 50:
case 10:
this.relight[i]++;
getParent().getRelighter().addLightUpdate((getX() << 4) + x, y, (getZ() << 4) + z);
default:
vs[j] = (char) (id << 4);
heightMap[z << 4 | x] = (byte) y;
@ -280,7 +254,7 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
case 138:
case 169:
case 213:
this.relight[i]++;
getParent().getRelighter().addLightUpdate((getX() << 4) + x, y, (getZ() << 4) + z);
case 2:
case 4:
case 13:
@ -341,7 +315,7 @@ public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
case 62:
case 50:
case 10:
this.relight[i]++;
getParent().getRelighter().addLightUpdate((getX() << 4) + x, y, (getZ() << 4) + z);
case 54:
case 146:
case 61:

View File

@ -40,19 +40,22 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
@Override
public void runTasks() {
super.runTasks();
final NMSRelighter tmp = relighter;
relighter = null;
if (tmp != null) {
if (!relighter.isEmpty()) {
TaskManager.IMP.taskNowAsync(new Runnable() {
@Override
public void run() {
tmp.fixLightingSafe(hasSky());
relighter.fixLightingSafe(hasSky());
}
});
}
}
private NMSRelighter relighter;
private final Relighter relighter = Settings.LIGHTING.MODE > 0 ? new NMSRelighter(this) : NullRelighter.INSTANCE;
@Override
public Relighter getRelighter() {
return relighter;
}
@Override
public void end(FaweChunk chunk) {
@ -61,13 +64,8 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
sendChunk(chunk);
return;
}
NMSRelighter tmp = relighter;
if (tmp == null) {
relighter = tmp = new NMSRelighter(this);
}
if (Settings.LIGHTING.MODE == 2) {
tmp.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask());
relighter.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask());
return;
}
CharFaweChunk cfc = (CharFaweChunk) chunk;
@ -75,13 +73,13 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
boolean[] fix = new boolean[(maxY + 1) >> 4];
boolean sky = hasSky();
for (int i = 0; i < cfc.ids.length; i++) {
if ((sky && ((cfc.getAir(i) & 4095) != 0 || (cfc.getCount(i) & 4095) != 0)) || cfc.getRelight(i) != 0) {
if ((sky && ((cfc.getAir(i) & 4095) != 0 || (cfc.getCount(i) & 4095) != 0))) {
relight = true;
fix[i] = true;
}
}
if (relight) {
tmp.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask());
relighter.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask());
} else {
sendChunk(chunk);
}

View File

@ -3,24 +3,47 @@ package com.boydti.fawe.example;
import com.boydti.fawe.FaweCache;
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 java.util.*;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class NMSRelighter {
public class NMSRelighter implements Relighter{
private final NMSMappedFaweQueue queue;
private final Map<Long, RelightSkyEntry> skyToRelight;
private final Map<Long, RelightBlockEntry> blocksToRelight;
private final Map<Long, Map<Short, Object>> lightQueue;
private final Object present = new Object();
private final Set<Long> chunksToSend;
private final int maxY;
private volatile boolean relighting = false;
public final IntegerTrio mutableBlockPos = new IntegerTrio();
private static final int DISPATCH_SIZE = 64;
public NMSRelighter(NMSMappedFaweQueue queue) {
this.queue = queue;
skyToRelight = new ConcurrentHashMap<>();
blocksToRelight = new ConcurrentHashMap<>();
this.maxY = queue.getWEWorld().getMaxY();
this.skyToRelight = new ConcurrentHashMap<>();
this.lightQueue = new ConcurrentHashMap<>();
chunksToSend = new LinkedHashSet<>();
this.maxY = queue.getMaxY();
}
@Override
public boolean isEmpty() {
return skyToRelight.isEmpty() && lightQueue.isEmpty();
}
public boolean addChunk(int cx, int cz, boolean[] fix, int bitmask) {
@ -47,38 +70,135 @@ public class NMSRelighter {
}
}
public void addBlock(int x, int y, int z) {
if (y < 1) {
public void updateBlockLight(Map<Long, Map<Short, Object>> map) {
int size = map.size();
if (size == 0) {
return;
}
int cx = x >> 4;
int cz = z >> 4;
long pair = MathMan.pairInt(cx, cz);
RelightBlockEntry current = blocksToRelight.get(pair);
if (current == null) {
current = new RelightBlockEntry(pair);
blocksToRelight.put(pair, current);
}
current.addBlock(x, y, z);
}
Queue<IntegerTrio> lightPropagationQueue = new ArrayDeque<>();
Queue<Object[]> lightRemovalQueue = new ArrayDeque<>();
Map<IntegerTrio, Object> visited = new HashMap<>();
Map<IntegerTrio, Object> removalVisited = new HashMap<>();
public void smoothBlockLight(int emit, int x, int y, int z, int rx, int ry, int rz) {
int opacity = queue.getOpacity(rx, ry, rz);
if (opacity >= emit) {
return;
Iterator<Map.Entry<Long, Map<Short, Object>>> iter = map.entrySet().iterator();
while (iter.hasNext() && size-- > 0) {
Map.Entry<Long, Map<Short, Object>> entry = iter.next();
iter.remove();
long index = entry.getKey();
Map<Short, 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()) {
int hi = (byte) (blockHash >>> 8);
int lo = (byte) blockHash;
int y = lo & 0xFF;
int x = (hi & 0xF) + bx;
int z = ((hi >> 4) & 0xF) + bz;
int lcx = x & 0xF;
int lcz = z & 0xF;
int oldLevel = queue.getEmmittedLight(x, y, z);
int newLevel = queue.getBrightness(x, y, z);
if (oldLevel != newLevel) {
queue.setBlockLight(x, y, z, newLevel);
IntegerTrio node = new IntegerTrio(x, y, z);
if (newLevel < oldLevel) {
removalVisited.put(node, present);
lightRemovalQueue.add(new Object[] { node, oldLevel });
} else {
visited.put(node, present);
lightPropagationQueue.add(node);
}
}
}
}
int emitAdjacent = queue.getEmmittedLight(rx, ry, rz);
if (emit - emitAdjacent > 1) {
queue.setBlockLight(rx, ry, rz, emit - 1);
addBlock(rx, ry, rz);
while (!lightRemovalQueue.isEmpty()) {
Object[] val = lightRemovalQueue.poll();
IntegerTrio node = (IntegerTrio) val[0];
int lightLevel = (int) val[1];
this.computeRemoveBlockLight(node.x - 1, node.y, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
this.computeRemoveBlockLight(node.x + 1, node.y, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
if (node.y > 0) {
this.computeRemoveBlockLight(node.x, node.y - 1, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
}
if (node.y < 255) {
this.computeRemoveBlockLight(node.x, node.y + 1, node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
}
this.computeRemoveBlockLight(node.x, node.y, node.z - 1, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
this.computeRemoveBlockLight(node.x, node.y, node.z + 1, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
}
while (!lightPropagationQueue.isEmpty()) {
IntegerTrio node = lightPropagationQueue.poll();
int lightLevel = queue.getEmmittedLight(node.x, node.y, node.z);
if (lightLevel > 1) {
this.computeSpreadBlockLight(node.x - 1, node.y, node.z, lightLevel, lightPropagationQueue, visited);
this.computeSpreadBlockLight(node.x + 1, node.y, node.z, lightLevel, lightPropagationQueue, visited);
if (node.y > 0) {
this.computeSpreadBlockLight(node.x, node.y - 1, node.z, lightLevel, lightPropagationQueue, visited);
}
if (node.y < 255) {
this.computeSpreadBlockLight(node.x, node.y + 1, node.z, lightLevel, lightPropagationQueue, visited);
}
this.computeSpreadBlockLight(node.x, node.y, node.z - 1, lightLevel, lightPropagationQueue, visited);
this.computeSpreadBlockLight(node.x, node.y, node.z + 1, lightLevel, lightPropagationQueue, visited);
}
}
}
public void fixLightingSafe(boolean sky) {
if (relighting) {
return;
private void computeRemoveBlockLight(int x, int y, int z, int currentLight, Queue<Object[]> queue, Queue<IntegerTrio> spreadQueue, Map<IntegerTrio, Object> visited,
Map<IntegerTrio, Object> spreadVisited) {
int current = this.queue.getEmmittedLight(x, y, z);
if (current != 0 && current < currentLight) {
this.queue.setBlockLight(x, y, z, 0);
if (current > 1) {
if (!visited.containsKey(mutableBlockPos)) {
IntegerTrio index = new IntegerTrio(x, y, z);
visited.put(index, present);
queue.add(new Object[] { index, current });
}
}
} else if (current >= currentLight) {
mutableBlockPos.set(x, y, z);
if (!spreadVisited.containsKey(mutableBlockPos)) {
IntegerTrio index = new IntegerTrio(x, y, z);
spreadVisited.put(index, present);
spreadQueue.add(index);
}
}
relighting = true;
}
private void computeSpreadBlockLight(int x, int y, int z, int currentLight, Queue<IntegerTrio> queue, Map<IntegerTrio, Object> visited) {
currentLight = currentLight - Math.max(1, this.queue.getOpacity(x, y, z));
if (currentLight > 0) {
int current = this.queue.getEmmittedLight(x, y, z);
if (current < currentLight) {
this.queue.setBlockLight(x, y, z, currentLight);
mutableBlockPos.set(x, y, z);
if (!visited.containsKey(mutableBlockPos)) {
visited.put(new IntegerTrio(x, y, z), present);
if (currentLight > 1) {
queue.add(new IntegerTrio(x, y, z));
}
}
}
}
}
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);
if (currentMap == null) {
currentMap = new ConcurrentHashMap<>(8, 0.9f, 1);
this.lightQueue.put(index, currentMap);
}
currentMap.put(MathMan.tripleBlockCoord(x, y, z), present);
}
public synchronized void fixLightingSafe(boolean sky) {
try {
if (sky) {
fixSkyLighting();
@ -88,46 +208,20 @@ public class NMSRelighter {
} catch (Throwable e) {
e.printStackTrace();
}
relighting = false;
}
public void fixBlockLighting() {
while (!blocksToRelight.isEmpty()) {
RelightBlockEntry current = blocksToRelight.entrySet().iterator().next().getValue();
int bx = current.getX() << 4;
int bz = current.getZ() << 4;
while (!current.blocks.isEmpty()) {
short coord = current.blocks.pollFirst();
byte layer = MathMan.unpairShortX(coord);
int y = MathMan.unpairShortY(coord) & 0xFF;
int x = MathMan.unpair16x(layer);
int z = MathMan.unpair16y(layer);
int xx = bx + x;
int zz = bz + z;
int emit = queue.getEmmittedLight(xx, y, zz);
if (emit < 1) {
continue;
}
smoothBlockLight(emit, xx, y, zz, xx - 1, y, zz);
smoothBlockLight(emit, xx, y, zz, xx + 1, y, zz);
smoothBlockLight(emit, xx, y, zz, xx, y, zz - 1);
smoothBlockLight(emit, xx, y, zz, xx, y, zz + 1);
if (y > 0) {
smoothBlockLight(emit, xx, y, zz, xx, y - 1, zz);
}
if (y < maxY) {
smoothBlockLight(emit, xx, y, zz, xx, y + 1, zz);
}
}
blocksToRelight.remove(current.coord);
}
updateBlockLight(this.lightQueue);
}
public void sendChunks() {
final Map<FaweChunk, int[]> fcs = new HashMap<>(skyToRelight.size());
for (Map.Entry<Long, RelightSkyEntry> entry : skyToRelight.entrySet()) {
RelightSkyEntry chunk = entry.getValue();
CharFaweChunk fc = (CharFaweChunk) queue.getFaweChunk(chunk.x, chunk.z);
Iterator<Long> iter = chunksToSend.iterator();
while (iter.hasNext()) {
long pair = iter.next();
iter.remove();
int x = MathMan.unpairIntX(pair);
int z = MathMan.unpairIntY(pair);
CharFaweChunk fc = (CharFaweChunk) queue.getFaweChunk(x, z);
queue.sendChunk(fc);
}
}
@ -136,19 +230,16 @@ public class NMSRelighter {
return queue.getOpacity(x, y, z) < 15;
}
public void lightBlock(int x, int y, int z, int brightness) {
queue.setBlockLight(x, y, z, Math.max(15, brightness + 1));
if (isTransparent(x - 1, y, z)) { queue.setBlockLight(x - 1, y, z, brightness); addBlock(x - 1, y, z); }
if (isTransparent(x + 1, y, z)) { queue.setBlockLight(x + 1, y, z, brightness); addBlock(x + 1, y, z); }
if (isTransparent(x, y, z - 1)) { queue.setBlockLight(x, y, z - 1, brightness); addBlock(x, y, z - 1); }
if (isTransparent(x, y, z + 1)) { queue.setBlockLight(x, y, z + 1, brightness); addBlock(x, y, z + 1); }
if (y > 0 && isTransparent(x, y - 1, z)) { queue.setBlockLight(x, y - 1, z, brightness); addBlock(x, y - 1, z); }
if (y < maxY && isTransparent(x, y + 1, z)) { queue.setBlockLight(x, y + 1, z, brightness); addBlock(x, y + 1, z); }
}
public void fixSkyLighting() {
// Order chunks
ArrayList<RelightSkyEntry> chunksList = new ArrayList<>(skyToRelight.values());
ArrayList<RelightSkyEntry> chunksList = new ArrayList<>(skyToRelight.size());
Iterator<Map.Entry<Long, RelightSkyEntry>> iter = skyToRelight.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Long, RelightSkyEntry> entry = iter.next();
iter.remove();
chunksToSend.add(entry.getKey());
chunksList.add(entry.getValue());
}
Collections.sort(chunksList);
int size = chunksList.size();
if (size > DISPATCH_SIZE) {
@ -189,7 +280,8 @@ public class NMSRelighter {
int opacity = MathMan.unpair16x(pair);
int brightness = MathMan.unpair16y(pair);
if (brightness > 1 && (brightness != 15 || opacity != 15)) {
lightBlock(bx + x, y, bz + z, brightness);
addLightUpdate(bx + x, y, bz + z);
// lightBlock(bx + x, y, bz + z, brightness);
}
switch (value) {
case 0:
@ -305,17 +397,9 @@ public class NMSRelighter {
private class RelightBlockEntry {
public long coord;
public ArrayDeque<Short> blocks;
public RelightBlockEntry(long pair) {
this.coord = pair;
this.blocks = new ArrayDeque<>(1);
}
public void addBlock(int x, int y, int z) {
byte layer = MathMan.pair16(x & 15, z & 15);
short coord = MathMan.pairByte(layer, y);
blocks.add(coord);
}
public int getX() {

View File

@ -0,0 +1,38 @@
package com.boydti.fawe.example;
public class NullRelighter implements Relighter {
public static NullRelighter INSTANCE = new NullRelighter();
private NullRelighter() {}
@Override
public boolean addChunk(int cx, int cz, boolean[] fix, int bitmask) {
return false;
}
@Override
public void addLightUpdate(int x, int y, int z) {
}
@Override
public void fixLightingSafe(boolean sky) {
}
@Override
public void fixBlockLighting() {
}
@Override
public void fixSkyLighting() {
}
@Override
public boolean isEmpty() {
return true;
}
}

View File

@ -0,0 +1,15 @@
package com.boydti.fawe.example;
public interface Relighter {
boolean addChunk(int cx, int cz, boolean[] fix, int bitmask);
void addLightUpdate(int x, int y, int z);
void fixLightingSafe(boolean sky);
void fixBlockLighting();
void fixSkyLighting();
boolean isEmpty();
}

View File

@ -5,6 +5,8 @@ import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.NullRelighter;
import com.boydti.fawe.example.Relighter;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
@ -46,6 +48,10 @@ public abstract class FaweQueue {
}
}
public Relighter getRelighter() {
return NullRelighter.INSTANCE;
}
public enum ProgressType {
QUEUE,
DISPATCH,

View File

@ -64,6 +64,12 @@ public class MathMan {
return (((long)x) << 32) | (y & 0xffffffffL);
}
public static final short tripleBlockCoord(int x, int y, int z) {
byte hi = (byte) ((x & 15) + ((z & 15) << 4));
byte lo = (byte) y;
return (short) (((hi & 0xFF) << 8) | (lo & 0xFF));
}
public static final long chunkXZ2Int(int x, int z) {
return (long)x & 4294967295L | ((long)z & 4294967295L) << 32;
}

View File

@ -1,6 +1,5 @@
#org.gradle.java.home=C:/PROGRA~2/Java/jdk1.7.0_79
#org.gradle.java.home=C:/PROGRA~1/Java/jdk1.8.0_51
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.daemon=false
org.gradle.configureondemand=true
org.gradle.parallel=true