[Bleeding] Lighting changes + broken

This commit is contained in:
Jesse Boyd 2016-07-26 10:04:19 +10:00
parent 4bde477206
commit 06275e8d3d
19 changed files with 778 additions and 227 deletions

View File

@ -12,6 +12,7 @@ import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
@ -43,6 +44,21 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
}
}
@Override
public void forEachMCA(RunnableVal<File> onEach) {
File folder = new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region");
File[] regionFiles = folder.listFiles();
if (regionFiles == null) {
throw new RuntimeException("Could not find worlds folder: " + folder + " ? (no read access?)");
}
for (File file : regionFiles) {
String name = file.getName();
if (name.endsWith("mca")) {
onEach.run(file);
}
}
}
@Override
public void setFullbright(CHUNKSECTIONS sections) {}

View File

@ -25,13 +25,13 @@ public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
}
@Override
public void setSkyLight(int x, int y, int z, int value) {
public void setSkyLight(Chunk chunk, int x, int y, int z, int value) {
}
@Override
public void setBlockLight(int x, int y, int z, int value) {
public void setBlockLight(Chunk chunk, int x, int y, int z, int value) {
// chunk.getBlock(x & 15, y, z & 15);
}
public int getCombinedId4Data(Chunk section, int x, int y, int z) {

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
@ -76,7 +77,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[], DataPaletteBlock> {
public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
private static IBlockData air;
private static Field fieldBits;
@ -103,32 +104,12 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
}
@Override
public void setSkyLight(int x, int y, int z, int value) {
int cx = x >> 4;
int cz = z >> 4;
if (!ensureChunkLoaded(cx, cz)) {
return;
}
ChunkSection[] sections = getCachedSections(getWorld(), cx, cz);
ChunkSection section = sections[y >> 4];
if (section == null) {
return;
}
public void setSkyLight(ChunkSection section, int x, int y, int z, int value) {
section.getSkyLightArray().a(x & 15, y & 15, z & 15, value);
}
@Override
public void setBlockLight(int x, int y, int z, int value) {
int cx = x >> 4;
int cz = z >> 4;
if (!ensureChunkLoaded(cx, cz)) {
return;
}
ChunkSection[] sections = getCachedSections(getWorld(), cx, cz);
ChunkSection section = sections[y >> 4];
if (section == null) {
return;
}
public void setBlockLight(ChunkSection section, int x, int y, int z, int value) {
section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value);
}
@ -136,7 +117,8 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
private DataPaletteBlock lastBlocks;
@Override
public boolean hasBlock(DataPaletteBlock dataPaletteBlock, int x, int y, int z) {
public boolean hasBlock(ChunkSection section, int x, int y, int z) {
DataPaletteBlock dataPaletteBlock = section.getBlocks();
try {
if (lastBlocks != dataPaletteBlock) {
lastBits = (DataBits) fieldBits.get(dataPaletteBlock);
@ -223,14 +205,14 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
}
@Override
public DataPaletteBlock getCachedSection(ChunkSection[] chunkSections, int cy) {
ChunkSection nibble = chunkSections[cy];
return nibble != null ? nibble.getBlocks() : null;
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
}
@Override
public int getCombinedId4Data(DataPaletteBlock lastSection, int x, int y, int z) {
IBlockData ibd = lastSection.a(x & 15, y & 15, z & 15);
public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) {
DataPaletteBlock dataPalette = lastSection.getBlocks();
IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15);
Block block = ibd.getBlock();
int id = Block.getId(block);
if (FaweCache.hasData(id)) {
@ -322,12 +304,13 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
@Override
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
if (mode == RelightMode.ALL) {
if (mode.ordinal() > 4) {
for (int i = 0; i < sections.length; i++) {
ChunkSection section = sections[i];
if (section != null) {
section.a(new NibbleArray()); // Emitted
if (sky) {
System.out.println("REMOVE SKY");
section.b(new NibbleArray()); // Skylight
}
}
@ -339,33 +322,134 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
@Override
public boolean initLighting(Chunk chunk, ChunkSection[] sections, RelightMode mode) {
net.minecraft.server.v1_10_R1.Chunk c = ((CraftChunk) chunk).getHandle();
if (mode == RelightMode.ALL) {
c.initLighting();
} else {
final int i = c.g();
final int i2 = i + 15;
int l;
int opacity;
int y;
for (int x = 0; x < 16; ++x) {
for (int z = 0; z < 16; ++z) {
y = i2;
l = 15;
do {
opacity = c.a(x, y, z).c();
if (opacity == 0 && l != 15) {
opacity = 1;
}
l -= opacity;
if (l > 0) {
ChunkSection section = sections[y >> 4];
if (section != null) {
section.a(x, y & 15, z, l);
// Optimizations
// If it's all air, use the above light values
// If it's all solid, use no light values
World world = getWorld();
byte[] mask = new byte[256];
byte[] smoothArray = new byte[256];
Arrays.fill(mask, (byte) 15);
int bx = chunk.getX() << 4;
int bz = chunk.getZ() << 4;
section:
for (int y2 = 15; y2 >= 0; y2--) {
ChunkSection section = sections[y2];
if (section == null) {
continue;
}
int y = 16 + (y2 << 4);
DataPaletteBlock dataPalette = section.getBlocks();
layer:
for (int y1 = 15; y1 >= 0; y1--) {
y--;
boolean smooth = false;
index:
for (int j = 0; j < 256; j++) {
byte value = mask[j];
smoothArray[j] = 0;
int x = FaweCache.CACHE_X[y1][j];
int z = FaweCache.CACHE_Z[y1][j];
IBlockData ibd = dataPalette.a(x, y1, z);
int opacity = ibd.c();
if (x == 0 && z == 0) {
System.out.println(y + ": " + value + "," + opacity + " | " + getCombinedId4Data(bx + x, y, bz + z));
}
if (opacity != 0 && opacity >= value) {
mask[j] = 0;
continue index;
}
switch (value) {
case 0:
if (opacity != 0) {
continue index;
}
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
if (opacity == 0) {
mask[j] = --value;
if (x == 0 && z == 0) System.out.println(" - " + value);
} else {
mask[j] = value = (byte) Math.max(0, value - opacity);
if (x == 0 && z == 0) System.out.println(" - " + value);
}
break;
case 15:
if (opacity == 0) {
section.a(x, y1, z, value);
} else {
value -= opacity;
mask[j] = value;
section.a(x, y1, z, value);
if (x == 0 && z == 0) {
System.out.println(" - " + value);
}
}
continue index;
}
// Smooth
smooth = true;
smoothArray[j] = 1;
int adjacent = getAdjacentLight(bx + x, y, bz + z) - 1;
if (adjacent > value) {
if (x == 0 && z == 0) {
if (getSkyLight(bx + x - 1, y, bz + z) == 15) System.out.println("x-1");
if (getSkyLight(bx + x + 1, y, bz + z) == 15) System.out.println("x+1");
if (getSkyLight(bx + x, y, bz + z - 1) == 15) System.out.println("z-1");
if (getSkyLight(bx + x, y, bz + z + 1) == 15) System.out.println("z+1");
System.out.println("VALUE IS GREATER: " + getAdjacentLight(bx + x, y, bz + z));
}
--y;
} while (y > 0 && l > 0);
value = (byte) adjacent;
mask[j] = value;
}
section.a(x, y1, z, value);
}
// if (smooth) {
// short[][] cache1 = FaweCache.CACHE_J[0];
// for (int x = 0; x < 16; x++) {
// int xx = bx + x;
// short[] cache2 = cache1[x];
// for (int z = 0; z < 16; z++) {
// int zz = bz + z;
// int j = cache2[z];
// if (smoothArray[j] == 0) {
// continue;
// }
// byte value = mask[j];
// int adjacent = getAdjacentLight(xx, y, zz) - 1;
// if (adjacent > value) {
// section.a(x, y1, z, mask[j] = (byte) adjacent);
// }
// }
// }
// for (int z = 15; z >=0; z--) {
// for (int x = 15; x >= 0; x--) {
// int xx = bx + x;
// int zz = bz + z;
// int j = cache1[x][z];
// if (smoothArray[j] == 0) {
// continue;
// }
// byte value = mask[j];
// int adjacent = getAdjacentLight(xx, y, zz) - 1;
// if (adjacent > value) {
// section.a(x, y1, z, mask[j] = (byte) adjacent);
// }
// }
// }
// }
}
}
return true;
@ -383,21 +467,16 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], DataP
}
@Override
public int getSkyLight(ChunkSection[] sections, int x, int y, int z) {
ChunkSection section = sections[FaweCache.CACHE_I[y][x][z]];
if (section == null) {
return 15;
public int getSkyLight(ChunkSection section, int x, int y, int z) {
if (x == 15 && z == 0) {
System.out.println(" \\ " + x + "," + z + " | " + section.b(x & 15, y & 15, z & 15) + " | " + section.b(0, 0, 0));
}
return section.b(x, y & 15, z);
return section.b(x & 15, y & 15, z & 15);
}
@Override
public int getEmmittedLight(ChunkSection[] sections, int x, int y, int z) {
ChunkSection section = sections[FaweCache.CACHE_I[y][x][z]];
if (section == null) {
return 0;
}
return section.c(x, y & 15, z);
public int getEmmittedLight(ChunkSection section, int x, int y, int z) {
return section.c(x & 15, y & 15, z & 15);
}
@Override

View File

@ -12,9 +12,6 @@ commands:
description: (FAWE) Bypass WorldEdit processing and area restrictions
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
fixlighting:
description: (FAWE) Fix the lighting in your current chunk
aliases: [/fixlighting]
stream:
description: (FAWE) Stream a schematic into the world
aliases: [/stream]
@ -43,8 +40,6 @@ permissions:
default: false
fawe.stream:
default: false
fawe.fixlighting:
default: false
fawe.reload:
default: false
fawe.voxelbrush:

View File

@ -12,9 +12,6 @@ commands:
description: (FAWE) Bypass WorldEdit processing and area restrictions
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
fixlighting:
description: (FAWE) Fix the lighting in your current chunk
aliases: [/fixlighting]
stream:
description: (FAWE) Stream a schematic into the world
aliases: [/stream]
@ -43,8 +40,6 @@ permissions:
default: false
fawe.stream:
default: false
fawe.fixlighting:
default: false
fawe.reload:
default: false
fawe.voxelbrush:

View File

@ -12,9 +12,6 @@ commands:
description: (FAWE) Bypass WorldEdit processing and area restrictions
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
fixlighting:
description: (FAWE) Fix the lighting in your current chunk
aliases: [/fixlighting]
stream:
description: (FAWE) Stream a schematic into the world
aliases: [/stream]
@ -43,8 +40,6 @@ permissions:
default: false
fawe.stream:
default: false
fawe.fixlighting:
default: false
fawe.reload:
default: false
fawe.voxelbrush:

View File

@ -1,7 +1,6 @@
package com.boydti.fawe;
import com.boydti.fawe.command.Cancel;
import com.boydti.fawe.command.FixLighting;
import com.boydti.fawe.command.Reload;
import com.boydti.fawe.command.Rollback;
import com.boydti.fawe.command.Stream;
@ -225,7 +224,6 @@ public class Fawe {
private void setupCommands() {
this.IMP.setupCommand("wea", new Wea());
this.IMP.setupCommand("fixlighting", new FixLighting());
this.IMP.setupCommand("stream", new Stream());
this.IMP.setupCommand("select", new WorldEditRegion());
this.IMP.setupCommand("fawe", new Reload());

View File

@ -3,7 +3,7 @@ package com.boydti.fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.example.NMSRelighter;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
@ -378,6 +378,10 @@ public class FaweAPI {
queue.fixLighting(queue.getFaweChunk(chunk.getX(), chunk.getZ()), mode);
}
public static int fixLighting(String world, Region selection) {
return fixLighting(world, selection, FaweQueue.RelightMode.ALL);
}
/**
* Fix the lighting in a selection<br>
* - First removes all lighting, then relights
@ -387,7 +391,7 @@ public class FaweAPI {
* @param selection (assumes cuboid)
* @return
*/
public static int fixLighting(String world, Region selection) {
public static int fixLighting(String world, Region selection, final FaweQueue.RelightMode mode) {
final Vector bot = selection.getMinimumPoint();
final Vector top = selection.getMaximumPoint();
@ -402,59 +406,51 @@ public class FaweAPI {
// Remove existing lighting first
if (queue instanceof NMSMappedFaweQueue) {
final NMSMappedFaweQueue nmsQueue = (NMSMappedFaweQueue) queue;
boolean sky = nmsQueue.hasSky();
NMSRelighter relighter = new NMSRelighter(nmsQueue);
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z ++) {
if (!nmsQueue.isChunkLoaded(x, z)) {
final int xf = x;
final int zf = z;
if (!TaskManager.IMP.syncWhenFree(new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
this.value = nmsQueue.loadChunk(nmsQueue.getWorld(), xf, zf, false);
}
})) {
continue;
}
}
Object sections = nmsQueue.getCachedSections(nmsQueue.getWorld(), x, z);
nmsQueue.removeLighting(sections, FaweQueue.RelightMode.ALL, sky);
relighter.addChunk(x, z);
}
}
}
ArrayList<Thread> threads = new ArrayList<>();
for (int X = 0; X < 2; X++) {
for (int Z = 0; Z < 2; Z++) {
for (int x = minX + X; x <= maxX; x += 2) {
for (int z = minZ + Z; z <= maxZ; z += 2) {
final FaweChunk<?> chunk = queue.getFaweChunk(x, z);
if (Settings.LIGHTING.ASYNC) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
queue.fixLightingSafe(chunk, FaweQueue.RelightMode.ALL);
queue.sendChunk(chunk, FaweQueue.RelightMode.NONE);
}
});
thread.start();
threads.add(thread);
} else {
queue.fixLightingSafe(chunk, FaweQueue.RelightMode.ALL);
queue.sendChunk(chunk, FaweQueue.RelightMode.NONE);
}
count++;
}
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
threads.clear();
boolean sky = nmsQueue.hasSky();
if (sky) {
relighter.fixSkyLighting();
}
relighter.fixBlockLighting();
}
// ArrayList<Thread> threads = new ArrayList<>();
// for (int X = 0; X < 2; X++) {
// for (int Z = 0; Z < 2; Z++) {
// for (int x = minX + X; x <= maxX; x += 2) {
// for (int z = minZ + Z; z <= maxZ; z += 2) {
// final FaweChunk<?> chunk = queue.getFaweChunk(x, z);
// if (Settings.LIGHTING.ASYNC) {
// Thread thread = new Thread(new Runnable() {
// @Override
// public void run() {
// queue.fixLightingSafe(chunk, mode);
// queue.sendChunk(chunk, FaweQueue.RelightMode.NONE);
// }
// });
// thread.start();
// threads.add(thread);
// } else {
// queue.fixLightingSafe(chunk, mode);
// queue.sendChunk(chunk, FaweQueue.RelightMode.NONE);
// }
// count++;
// }
// }
// for (Thread thread : threads) {
// try {
// thread.join();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// threads.clear();
// }
// }
return count;
}

View File

@ -1,35 +0,0 @@
package com.boydti.fawe.command;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
public class FixLighting extends FaweCommand {
public FixLighting() {
super("fawe.fixlighting");
}
@Override
public boolean execute(final FawePlayer player, final String... args) {
if (player == null) {
return false;
}
final FaweLocation loc = player.getLocation();
final int cx = loc.x >> 4;
final int cz = loc.z >> 4;
Region selection = player.getSelection();
if (selection == null) {
selection = new CuboidRegion(new Vector(cx - 8, 0, cz - 8).multiply(16), new Vector(cx + 8, 0, cz + 8).multiply(16));
}
int count = FaweAPI.fixLighting(loc.world, selection);
BBC.FIX_LIGHTING_SELECTION.send(player, count);
return true;
}
}

View File

@ -21,8 +21,6 @@ import java.util.Map;
public class Config {
// TODO
/**
* Get the value for a node<br>
* Probably throws some error if you try to get a non existent key

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.example;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
@ -11,7 +12,9 @@ import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.UUID;
@ -434,6 +437,131 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
return getCombinedId4Data(lastSection, x, y, z) != 0;
}
public int getOpacity(SECTION section, int x, int y, int z) {
int combined = getCombinedId4Data(section, x, y, z);
if (combined == 0) {
return 0;
}
BlockMaterial block = BundledBlockData.getInstance().getMaterialById(FaweCache.getId(combined));
if (block == null) {
return 255;
}
return block.getLightOpacity();
}
public abstract int getSkyLight(SECTION sections, int x, int y, int z);
public abstract int getEmmittedLight(SECTION sections, int x, int y, int z);
public int getLight(SECTION sections, int x, int y, int z) {
if (!hasSky()) {
return getEmmittedLight(sections, x, y, z);
}
return Math.max(getSkyLight(sections, x, y, z), getEmmittedLight(sections, x, y, z));
}
@Override
public int getLight(int x, int y, int z) {
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)) {
return 0;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
return 0;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
if (lastSection == null) {
return 0;
}
return getLight(lastSection, x, y, z);
}
@Override
public int getSkyLight(int x, int y, int z) {
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)) {
return 0;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
return 0;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
if (lastSection == null) {
return 0;
}
return getSkyLight(lastSection, x, y, z);
}
@Override
public int getEmmittedLight(int x, int y, int z) {
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)) {
return 0;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
return 0;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
if (lastSection == null) {
return 0;
}
return getEmmittedLight(lastSection, x, y, z);
}
@Override
public int getOpacity(int x, int y, int z) {
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)) {
return 0;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
return 0;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
if (lastSection == null) {
return 0;
}
return getOpacity(lastSection, x, y, z);
}
@Override
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
int cx = x >> 4;

View File

@ -59,8 +59,6 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
}, Settings.LIGHTING.ASYNC);
}
public abstract boolean hasSky();
public abstract void setFullbright(CHUNKSECTION sections);
public abstract boolean removeLighting(CHUNKSECTION sections, RelightMode mode, boolean hasSky);
@ -97,21 +95,58 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
public abstract void relight(int x, int y, int z);
public abstract void setSkyLight(int x, int y, int z, int value);
public abstract void setBlockLight(int x, int y, int z, int value);
public abstract int getSkyLight(CHUNKSECTION sections, int x, int y, int z);
public abstract int getEmmittedLight(CHUNKSECTION sections, int x, int y, int z);
public int getLight(CHUNKSECTION sections, int x, int y, int z) {
if (!hasSky()) {
return getEmmittedLight(sections, x, y, z);
public void setSkyLight(int x, int y, int z, int value) {
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)) {
return;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
return;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
return Math.max(getSkyLight(sections, x, y, z), getEmmittedLight(sections, x, y, z));
if (lastSection == null) {
return;
}
setSkyLight(lastSection, x, y, z, value);
}
public void setBlockLight(int x, int y, int z, int value) {
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)) {
return;
}
lastChunkSections = getCachedSections(getWorld(), cx, cz);
lastSection = getCachedSection(lastChunkSections, cy);
} else if (cy != lastChunkY) {
if (lastChunkSections == null) {
return;
}
lastSection = getCachedSection(lastChunkSections, cy);
}
if (lastSection == null) {
return;
}
setBlockLight(lastSection, x, y, z, value);
}
public abstract void setSkyLight(SECTION section, int x, int y, int z, int value);
public abstract void setBlockLight(SECTION section, int x, int y, int z, int value);
@Override
public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
if (mode == RelightMode.NONE) {
@ -182,41 +217,43 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
}
switch (mode) {
case ALL: {
for (int k = 4095; k >= 0; k--) {
final int x = FaweCache.CACHE_X[j][k];
final int y = FaweCache.CACHE_Y[j][k];
if (y == 0) {
continue;
}
final int z = FaweCache.CACHE_Z[j][k];
final int i = array[k];
final short id = (short) (i >> 4);
switch (FaweCache.getLight(id)) {
case OCCLUDING:
if (y == 0 || !FaweCache.isTransparent(bc.getCombinedId(x, y - 1, z) >> 4)) {
continue;
}
break;
case TRANSPARENT_EMIT:
case SOLID_EMIT:
if (this.isSurrounded(bc.getCombinedIdArrays(), x, y, z)) {
continue;
}
break;
case TRANSPARENT:
if (y >= 255) {
continue;
}
int light = getSkyLight(sections, x, y, z);
if (light != 0) {
continue;
}
break;
}
relight(X + x, y, Z + z);
}
break;
}
// for (int k = 4095; k >= 0; k--) {
// final int x = FaweCache.CACHE_X[j][k];
// final int y = FaweCache.CACHE_Y[j][k];
// if (y == 0) {
// continue;
// }
// final int z = FaweCache.CACHE_Z[j][k];
// final int i = array[k];
// final short id = (short) (i >> 4);
// switch (FaweCache.getLight(id)) {
// case OCCLUDING:
// if (y == 0 || !FaweCache.isTransparent(bc.getCombinedId(x, y - 1, z) >> 4)) {
// continue;
// }
// break;
// case TRANSPARENT_EMIT:
// case SOLID_EMIT:
// if (this.isSurrounded(bc.getCombinedIdArrays(), x, y, z)) {
// continue;
// }
// break;
// case TRANSPARENT:
// if (y >= 255) {
// continue;
// }
// int light = getSkyLight(sections, x, y, z);
// if (light != 0) {
// continue;
// }
// break;
// }
// relight(X + x, y, Z + z);
// }
// break;
// }
case OPTIMAL: {
for (int k = 4095; k >= 0; k--) {
final int x = FaweCache.CACHE_X[j][k];
@ -272,7 +309,9 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
}
}
return true;
} catch (Throwable ignore) {}
} catch (Throwable ignore) {
ignore.printStackTrace();
}
return false;
}

View File

@ -0,0 +1,194 @@
package com.boydti.fawe.example;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.util.MathMan;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
public class NMSRelighter {
private final NMSMappedFaweQueue queue;
private final HashMap<Long, RelightChunk> toRelight;
public NMSRelighter(NMSMappedFaweQueue queue) {
this.queue = queue;
toRelight = new HashMap<>();
}
public boolean addChunk(int cx, int cz) {
long pair = MathMan.pairInt(cx, cz);
if (toRelight.containsKey(pair)) {
return false;
}
toRelight.put(pair, new RelightChunk(cx, cz));
return true;
}
public void fixBlockLighting() {
}
public void fixSkyLighting() {
// Order chunks
ArrayList<RelightChunk> chunksList = new ArrayList<>(toRelight.values());
Collections.sort(chunksList);
RelightChunk[] chunks = chunksList.toArray(new RelightChunk[chunksList.size()]);
byte[] cacheX = FaweCache.CACHE_X[0];
byte[] cacheZ = FaweCache.CACHE_Z[0];
for (int y = 255; y >= 0; y--) {
for (RelightChunk chunk : chunks) { // Propogate skylight
byte[] mask = chunk.mask;
Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z);
if (sections == null) continue;
Object section = queue.getCachedSection(sections, y >> 4);
if (section == null) continue;
chunk.smooth = false;
for (int j = 0; j < 256; j++) {
int x = cacheX[j];
int z = cacheZ[j];
byte value = mask[j];
int opacity = queue.getOpacity(section, x, y, z);
if (opacity != 0 && opacity >= value) {
mask[j] = 0;
continue;
}
switch (value) {
case 0:
if (opacity != 0) {
continue;
}
break;
case 2:
case 4:
case 6:
case 8:
case 10:
case 12:
case 14:
if (opacity == 0) {
mask[j] = --value;
} else {
mask[j] = (byte) Math.max(0, value - opacity);
}
queue.setSkyLight(section, x, y, z, value);
continue;
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 13:
if (opacity == 0) {
mask[j] = --value;
} else {
mask[j] = value = (byte) Math.max(0, value - opacity);
}
break;
case 15:
if (opacity != 0) {
value -= opacity;
mask[j] = value;
}
queue.setSkyLight(section, x, y, z, value);
continue;
}
chunk.smooth = true;
queue.setSkyLight(section, x, y, z, value);
}
}
for (RelightChunk chunk : chunks) { // Smooth forwards
if (chunk.smooth) {
smooth(chunk, y, true);
}
}
for (int i = chunks.length - 1; i>= 0; i--) { // Smooth backwards
RelightChunk chunk = chunks[i];
if (chunk.smooth) {
smooth(chunk, y, false);
}
}
}
}
public void smooth(RelightChunk chunk, int y, boolean direction) {
byte[] mask = chunk.mask;
int bx = chunk.x << 4;
int bz = chunk.z << 4;
Object sections = queue.getCachedSections(queue.getWorld(), chunk.x, chunk.z);
if (sections == null) return;
Object section = queue.getCachedSection(sections, y >> 4);
if (section == null) return;
if (direction) {
for (int j = 0; j < 256; j++) {
int x = j & 15;
int z = j >> 4;
if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 0)) {
continue;
}
byte value = mask[j];
if ((value = (byte) Math.max(queue.getSkyLight(bx + x - 1, y, bz + z) - 1, value)) >= 14);
else if ((value = (byte) Math.max(queue.getSkyLight(bx + x, y, bz + z - 1) - 1, value)) >= 14);
if (value > mask[j]) queue.setSkyLight(section, x, y, z, mask[j] = value);
}
} else {
for (int j = 255; j >= 0; j--) {
int x = j & 15;
int z = j >> 4;
if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 0)) {
continue;
}
byte value = mask[j];
if ((value = (byte) Math.max(queue.getSkyLight(bx + x + 1, y, bz + z) - 1, value)) >= 14);
else if ((value = (byte) Math.max(queue.getSkyLight(bx + x, y, bz + z + 1) - 1, value)) >= 14);
if (value > mask[j]) queue.setSkyLight(section, x, y, z, mask[j] = value);
}
}
}
public boolean isUnlit(byte[] array) {
for (byte val : array) {
if (val != 0) {
return false;
}
}
return true;
}
private class RelightChunk implements Comparable {
public final int x;
public final int z;
public final byte[] mask;
public boolean smooth;
public RelightChunk(int x, int z) {
this.x = x;
this.z = z;
byte[] array = new byte[256];
Arrays.fill(array, (byte) 15);
this.mask = array;
}
@Override
public int compareTo(Object o) {
RelightChunk other = (RelightChunk) o;
if (other.x < x) {
return -1;
}
if (other.x > x) {
return 1;
}
if (other.z < z) {
return -1;
}
if (other.z > z) {
return 1;
}
return 0;
}
}
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.exception.FaweException;
@ -10,7 +11,12 @@ import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
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.blocks.BlockMaterial;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@ -41,6 +47,7 @@ public abstract class FaweQueue {
MINIMAL,
FULLBRIGHT,
OPTIMAL,
FAST,
ALL,
}
@ -151,6 +158,64 @@ public abstract class FaweQueue {
});
}
public abstract void forEachMCA(RunnableVal<File> onEach);
public void forEachBlockInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
int bx = cx << 4;
int bz = cz << 4;
Vector mutable = new Vector(0, 0, 0);
for (int x = 0; x < 16; x++) {
int xx = x + bx;
mutable.x = xx;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
mutable.z = zz;
for (int y = 0; y < 256; y++) {
int combined = getCombinedId4Data(xx, y, zz);
if (combined == 0) {
continue;
}
int id = FaweCache.getId(combined);
mutable.y = y;
if (FaweCache.hasNBT(id)) {
CompoundTag tile = getTileEntity(x, y, z);
BaseBlock block = new BaseBlock(id, FaweCache.getData(combined), tile);
onEach.run(mutable, block);
} else {
onEach.run(mutable, FaweCache.CACHE_BLOCK[combined]);
}
}
}
}
}
public void forEachTileInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
int bx = cx << 4;
int bz = cz << 4;
Vector mutable = new Vector(0, 0, 0);
for (int x = 0; x < 16; x++) {
int xx = x + bx;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
for (int y = 0; y < 256; y++) {
int combined = getCombinedId4Data(xx, y, zz);
if (combined == 0) {
continue;
}
int id = FaweCache.getId(combined);
if (FaweCache.hasNBT(id)) {
mutable.x = xx;
mutable.z = zz;
mutable.y = y;
CompoundTag tile = getTileEntity(x, y, z);
BaseBlock block = new BaseBlock(id, FaweCache.getData(combined), tile);
onEach.run(mutable, block);
}
}
}
}
}
public abstract boolean fixLighting(final FaweChunk<?> chunk, RelightMode mode);
public abstract boolean isChunkLoaded(final int x, final int z);
@ -208,6 +273,33 @@ public abstract class FaweQueue {
public abstract int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
public int getAdjacentLight(int x, int y, int z) {
int light = 0;
if ((light = Math.max(light, getSkyLight(x - 1, y, z))) == 15) {
return light;
}
if ((light = Math.max(light, getSkyLight(x + 1, y, z))) == 15) {
return light;
}
if ((light = Math.max(light, getSkyLight(x, y, z - 1))) == 15) {
return light;
}
return Math.max(light, getSkyLight(x, y, z + 1));
}
public abstract boolean hasSky();
public abstract int getSkyLight(int x, int y, int z);
public int getLight(int x, int y, int z) {
if (!hasSky()) {
return getEmmittedLight(x, y, z);
}
return Math.max(getSkyLight(x, y, z), getEmmittedLight(x, y, z));
}
public abstract int getEmmittedLight(int x, int y, int z);
public abstract CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException;
public int getCombinedId4Data(int x, int y, int z, int def) {
@ -227,6 +319,18 @@ public abstract class FaweQueue {
}
}
public int getOpacity(int x, int y, int z) {
int combined = getCombinedId4Data(x, y, z);
if (combined == 0) {
return 0;
}
BlockMaterial block = BundledBlockData.getInstance().getMaterialById(FaweCache.getId(combined));
if (block == null) {
return 255;
}
return block.getLightOpacity();
}
public abstract int size();
/**

View File

@ -2,11 +2,13 @@ package com.boydti.fawe.util;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal;
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.world.biome.BaseBiome;
import java.io.File;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
@ -127,6 +129,11 @@ public class DelegateFaweQueue extends FaweQueue {
parent.setChunk(chunk);
}
@Override
public void forEachMCA(RunnableVal<File> onEach) {
parent.forEachMCA(onEach);
}
@Override
public boolean fixLighting(FaweChunk<?> chunk, RelightMode mode) {
return parent.fixLighting(chunk, mode);
@ -192,6 +199,21 @@ public class DelegateFaweQueue extends FaweQueue {
return parent.getCombinedId4Data(x, y, z);
}
@Override
public boolean hasSky() {
return parent.hasSky();
}
@Override
public int getSkyLight(int x, int y, int z) {
return parent.getSkyLight(x, y, z);
}
@Override
public int getEmmittedLight(int x, int y, int z) {
return parent.getEmmittedLight(x, y, z);
}
@Override
public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return parent.getTileEntity(x, y, z);

View File

@ -21,7 +21,7 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.intellectualcrafters.plot.util.MathMan;
import com.boydti.fawe.util.MathMan;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;

View File

@ -19,7 +19,11 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
@ -86,6 +90,27 @@ public class RegionCommands {
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/fixlighting" },
desc = "Get the light at a position",
min = 0,
max = 0
)
@CommandPermissions("worldedit.light.get")
public void fixlighting(Player player, EditSession editSession) throws WorldEditException {
FawePlayer fp = FawePlayer.wrap(player);
final FaweLocation loc = fp.getLocation();
final int cx = loc.x >> 4;
final int cz = loc.z >> 4;
Region selection = fp.getSelection();
if (selection == null) {
selection = new CuboidRegion(new Vector(cx - 8, 0, cz - 8).multiply(16), new Vector(cx + 8, 0, cz + 8).multiply(16));
}
int count = FaweAPI.fixLighting(loc.world, selection, FaweQueue.RelightMode.ALL);
BBC.FIX_LIGHTING_SELECTION.send(fp, count);
}
@Command(
aliases = { "/line" },
usage = "<block> [thickness]",

View File

@ -60,7 +60,9 @@ public class BundledBlockData {
private static final BundledBlockData INSTANCE = new BundledBlockData();
private final Map<String, BlockEntry> idMap = new HashMap<String, BlockEntry>();
private final Map<Integer, BlockEntry> legacyMap = new HashMap<Integer, BlockEntry>(); // Trove usage removed temporarily
private final BlockEntry[] legacyMap = new BlockEntry[4096];
/**
* Create a new instance.
@ -95,11 +97,11 @@ public class BundledBlockData {
public boolean add(BlockEntry entry, boolean overwrite) {
entry.postDeserialization();
if (!overwrite && (idMap.containsKey(entry.id) || legacyMap.containsKey(entry.legacyId))) {
if (!overwrite && (idMap.containsKey(entry.id) || legacyMap[entry.legacyId] != null)) {
return false;
}
idMap.put(entry.id, entry);
legacyMap.put(entry.legacyId, entry);
legacyMap[entry.legacyId] = entry;
return true;
}
@ -122,7 +124,7 @@ public class BundledBlockData {
*/
@Nullable
public BlockEntry findById(int id) {
return legacyMap.get(id);
return legacyMap[id];
}
/**

View File

@ -47,11 +47,11 @@ public class SpongeCommand implements CommandCallable {
@Override
public Optional<? extends Text> getHelp(final CommandSource cmd) {
return Optional.of(Text.of("/<fixlighting|stream|wea|select>"));
return Optional.of(Text.of("/<stream|wea|select>"));
}
@Override
public Text getUsage(final CommandSource cmd) {
return Text.of("/<fixlighting|stream|wea|select>");
return Text.of("/<stream|wea|select>");
}
}