Add simple lighting generation for migrated chunks with missing light

This commit is contained in:
Mike Primm 2021-12-15 23:34:53 -06:00
parent c2f0a35eb3
commit eff72aeef0
6 changed files with 67 additions and 59 deletions

View file

@ -106,6 +106,35 @@ public class GenericChunk {
this.z = sz;
return this;
}
// Generate simple sky lighting (must be after all sections have been added)
public Builder generateSky() {
int sky[] = new int[256]; // ZX array
Arrays.fill(sky, 15); // Start fully lit at top
GenericChunkSection.Builder bld = new GenericChunkSection.Builder();
// Make light array for each section, start from top
for (int i = (sections.length - 1); i >= 0; i--) {
if (sections[i] == null) continue;
byte[] ssky = new byte[2048];
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
int idx = (z << 4) + x;
for (int y = 15; y >= 0; y--) {
DynmapBlockState bs = sections[i].blocks.getBlock(x, y, z); // Get block
if (bs.isWater() || bs.isWaterlogged()) { // Drop light by 1 level for water
sky[idx] = sky[idx] < 1 ? 0 : sky[idx] - 1;
}
else if (bs.isLeaves()) { // Drop light by 2 levels for leaves
sky[idx] = sky[idx] < 2 ? 0 : sky[idx] - 2;
}
ssky[(y << 7) | (z << 3) | (x >> 1)] |= (sky[idx] << (4 * (x & 1)));
}
}
}
// Replace section with new one with new lighting
sections[i] = bld.buildFrom(sections[i], ssky);
}
return this;
}
// Build chunk
public GenericChunk build() {
return new GenericChunk(x, z, y_min, sections, inhabTicks);

View file

@ -238,6 +238,12 @@ public class GenericChunkSection {
empty = false;
return this;
}
// Build copy from existing section with new skylight (YZX nibble array)
public GenericChunkSection buildFrom(GenericChunkSection s, byte[] sky) {
LightingAccess skyA = new LightingAccess3D(sky);
return new GenericChunkSection(s.blocks, s.biomes, skyA, s.emitted, s.isEmpty);
}
// Build section based on current builder state
public GenericChunkSection build() {
// Process state access - see if we can reduce

View file

@ -7,6 +7,7 @@ import java.util.ListIterator;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapCore;
import org.dynmap.DynmapWorld;
import org.dynmap.Log;
import org.dynmap.common.BiomeMap;
import org.dynmap.common.chunk.GenericChunkCache.ChunkCacheRec;
import org.dynmap.hdmap.HDBlockModels;
@ -901,17 +902,25 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
return true;
}
private static final String litStates[] = { "light", "spawn", "heightmaps", "full" };
public GenericChunk parseChunkFromNBT(GenericNBTCompound nbt) {
if ((nbt != null) && nbt.contains("Level")) {
nbt = nbt.getCompound("Level");
}
if (nbt == null) return null;
String status = nbt.getString("Status");
boolean hasLight = false;
boolean isEmpty = nbt.getString("Status").equals("empty"); // Incomplete migration
if (status != null) {
for (int i = 0; i < litStates.length; i++) {
if (status.equals(litStates[i])) hasLight = true;
}
}
// Start generic chunk builder
GenericChunk.Builder bld = new GenericChunk.Builder(dw.minY, dw.worldheight);
int x = nbt.getInt("xPos");
int z = nbt.getInt("zPos");
bld.coords(x, z);
if (nbt.contains("InhabitedTime")) {
bld.inhabitedTicks(nbt.getLong("InhabitedTime"));
@ -946,6 +955,14 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
GenericChunkSection.Builder sbld = new GenericChunkSection.Builder();
/* Get sections */
GenericNBTList sect = nbt.contains("sections") ? nbt.getList("sections", 10) : nbt.getList("Sections", 10);
// Prescan sections to see if lit
for (int i = 0; i < sect.size(); i++) {
GenericNBTCompound sec = sect.getCompound(i);
if (sec.contains("BlockLight") || sec.contains("SkyLight")) {
hasLight = true;
}
}
// And process sections
for (int i = 0; i < sect.size(); i++) {
GenericNBTCompound sec = sect.getCompound(i);
int secnum = sec.getByte("Y");
@ -1054,11 +1071,12 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
}
if (sec.contains("BlockLight")) {
sbld.emittedLight(sec.getByteArray("BlockLight"));
hasLight = true;
}
if (sec.contains("SkyLight")) {
sbld.skyLight(sec.getByteArray("SkyLight"));
hasLight = true;
}
else if (!hasLight) {
sbld.singleSkyLight(15);
}
// If section biome palette
if (sec.contains("biomes")) {
@ -1092,8 +1110,11 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
bld.addSection(secnum, sbld.build());
sbld.reset();
}
// If isEmpty and has no light, drop it
return (isEmpty && (!hasLight)) ? null : bld.build();
// If no light, do simple generate
if (!hasLight) {
bld.generateSky();
}
return bld.build();
}
}