mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-24 03:05:28 +01:00
Add simple lighting generation for migrated chunks with missing light
This commit is contained in:
parent
c2f0a35eb3
commit
eff72aeef0
@ -106,6 +106,35 @@ public class GenericChunk {
|
|||||||
this.z = sz;
|
this.z = sz;
|
||||||
return this;
|
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
|
// Build chunk
|
||||||
public GenericChunk build() {
|
public GenericChunk build() {
|
||||||
return new GenericChunk(x, z, y_min, sections, inhabTicks);
|
return new GenericChunk(x, z, y_min, sections, inhabTicks);
|
||||||
|
@ -238,6 +238,12 @@ public class GenericChunkSection {
|
|||||||
empty = false;
|
empty = false;
|
||||||
return this;
|
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
|
// Build section based on current builder state
|
||||||
public GenericChunkSection build() {
|
public GenericChunkSection build() {
|
||||||
// Process state access - see if we can reduce
|
// Process state access - see if we can reduce
|
||||||
|
@ -7,6 +7,7 @@ import java.util.ListIterator;
|
|||||||
import org.dynmap.DynmapChunk;
|
import org.dynmap.DynmapChunk;
|
||||||
import org.dynmap.DynmapCore;
|
import org.dynmap.DynmapCore;
|
||||||
import org.dynmap.DynmapWorld;
|
import org.dynmap.DynmapWorld;
|
||||||
|
import org.dynmap.Log;
|
||||||
import org.dynmap.common.BiomeMap;
|
import org.dynmap.common.BiomeMap;
|
||||||
import org.dynmap.common.chunk.GenericChunkCache.ChunkCacheRec;
|
import org.dynmap.common.chunk.GenericChunkCache.ChunkCacheRec;
|
||||||
import org.dynmap.hdmap.HDBlockModels;
|
import org.dynmap.hdmap.HDBlockModels;
|
||||||
@ -901,17 +902,25 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String litStates[] = { "light", "spawn", "heightmaps", "full" };
|
||||||
|
|
||||||
public GenericChunk parseChunkFromNBT(GenericNBTCompound nbt) {
|
public GenericChunk parseChunkFromNBT(GenericNBTCompound nbt) {
|
||||||
if ((nbt != null) && nbt.contains("Level")) {
|
if ((nbt != null) && nbt.contains("Level")) {
|
||||||
nbt = nbt.getCompound("Level");
|
nbt = nbt.getCompound("Level");
|
||||||
}
|
}
|
||||||
if (nbt == null) return null;
|
if (nbt == null) return null;
|
||||||
|
String status = nbt.getString("Status");
|
||||||
boolean hasLight = false;
|
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
|
// Start generic chunk builder
|
||||||
GenericChunk.Builder bld = new GenericChunk.Builder(dw.minY, dw.worldheight);
|
GenericChunk.Builder bld = new GenericChunk.Builder(dw.minY, dw.worldheight);
|
||||||
int x = nbt.getInt("xPos");
|
int x = nbt.getInt("xPos");
|
||||||
int z = nbt.getInt("zPos");
|
int z = nbt.getInt("zPos");
|
||||||
|
|
||||||
bld.coords(x, z);
|
bld.coords(x, z);
|
||||||
if (nbt.contains("InhabitedTime")) {
|
if (nbt.contains("InhabitedTime")) {
|
||||||
bld.inhabitedTicks(nbt.getLong("InhabitedTime"));
|
bld.inhabitedTicks(nbt.getLong("InhabitedTime"));
|
||||||
@ -946,6 +955,14 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
|||||||
GenericChunkSection.Builder sbld = new GenericChunkSection.Builder();
|
GenericChunkSection.Builder sbld = new GenericChunkSection.Builder();
|
||||||
/* Get sections */
|
/* Get sections */
|
||||||
GenericNBTList sect = nbt.contains("sections") ? nbt.getList("sections", 10) : nbt.getList("Sections", 10);
|
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++) {
|
for (int i = 0; i < sect.size(); i++) {
|
||||||
GenericNBTCompound sec = sect.getCompound(i);
|
GenericNBTCompound sec = sect.getCompound(i);
|
||||||
int secnum = sec.getByte("Y");
|
int secnum = sec.getByte("Y");
|
||||||
@ -1054,11 +1071,12 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
|||||||
}
|
}
|
||||||
if (sec.contains("BlockLight")) {
|
if (sec.contains("BlockLight")) {
|
||||||
sbld.emittedLight(sec.getByteArray("BlockLight"));
|
sbld.emittedLight(sec.getByteArray("BlockLight"));
|
||||||
hasLight = true;
|
|
||||||
}
|
}
|
||||||
if (sec.contains("SkyLight")) {
|
if (sec.contains("SkyLight")) {
|
||||||
sbld.skyLight(sec.getByteArray("SkyLight"));
|
sbld.skyLight(sec.getByteArray("SkyLight"));
|
||||||
hasLight = true;
|
}
|
||||||
|
else if (!hasLight) {
|
||||||
|
sbld.singleSkyLight(15);
|
||||||
}
|
}
|
||||||
// If section biome palette
|
// If section biome palette
|
||||||
if (sec.contains("biomes")) {
|
if (sec.contains("biomes")) {
|
||||||
@ -1092,8 +1110,11 @@ public abstract class GenericMapChunkCache extends MapChunkCache {
|
|||||||
bld.addSection(secnum, sbld.build());
|
bld.addSection(secnum, sbld.build());
|
||||||
sbld.reset();
|
sbld.reset();
|
||||||
}
|
}
|
||||||
// If isEmpty and has no light, drop it
|
// If no light, do simple generate
|
||||||
return (isEmpty && (!hasLight)) ? null : bld.build();
|
if (!hasLight) {
|
||||||
|
bld.generateSky();
|
||||||
|
}
|
||||||
|
return bld.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,20 +50,6 @@ public class MapChunkCache118 extends GenericMapChunkCache {
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLitChunk(NBTTagCompound nbt) {
|
|
||||||
if ((nbt != null) && nbt.e("Level")) {
|
|
||||||
nbt = nbt.p("Level");
|
|
||||||
}
|
|
||||||
if (nbt != null) {
|
|
||||||
String stat = nbt.l("Status");
|
|
||||||
ChunkStatus cs = ChunkStatus.a(stat);
|
|
||||||
if ((stat != null) && (cs.b(ChunkStatus.l) || (cs == ChunkStatus.c))) { // ChunkStatus.LIGHT OR ChunkStatus.EMPTY (migrated use this for some reason)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load generic chunk from existing and already loaded chunk
|
// Load generic chunk from existing and already loaded chunk
|
||||||
protected GenericChunk getLoadedChunk(DynmapChunk chunk) {
|
protected GenericChunk getLoadedChunk(DynmapChunk chunk) {
|
||||||
CraftWorld cw = (CraftWorld) w;
|
CraftWorld cw = (CraftWorld) w;
|
||||||
@ -74,9 +60,6 @@ public class MapChunkCache118 extends GenericMapChunkCache {
|
|||||||
if ((c != null) && c.o) { // c.loaded
|
if ((c != null) && c.o) { // c.loaded
|
||||||
nbt = ChunkRegionLoader.a(cw.getHandle(), c);
|
nbt = ChunkRegionLoader.a(cw.getHandle(), c);
|
||||||
}
|
}
|
||||||
if (!isLitChunk(nbt)) {
|
|
||||||
nbt = null;
|
|
||||||
}
|
|
||||||
if (nbt != null) {
|
if (nbt != null) {
|
||||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||||
}
|
}
|
||||||
@ -93,9 +76,6 @@ public class MapChunkCache118 extends GenericMapChunkCache {
|
|||||||
nbt = cw.getHandle().k().a.f(cc); // playerChunkMap
|
nbt = cw.getHandle().k().a.f(cc); // playerChunkMap
|
||||||
} catch (IOException iox) {
|
} catch (IOException iox) {
|
||||||
}
|
}
|
||||||
if (!isLitChunk(nbt)) {
|
|
||||||
nbt = null;
|
|
||||||
}
|
|
||||||
if (nbt != null) {
|
if (nbt != null) {
|
||||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||||
}
|
}
|
||||||
|
@ -60,20 +60,6 @@ public class FabricMapChunkCache extends GenericMapChunkCache {
|
|||||||
super.setChunks(dw, chunks);
|
super.setChunks(dw, chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLitChunk(NbtCompound nbt) {
|
|
||||||
if ((nbt != null) && nbt.contains("Level")) {
|
|
||||||
nbt = nbt.getCompound("Level");
|
|
||||||
}
|
|
||||||
if (nbt != null) {
|
|
||||||
String stat = nbt.getString("Status");
|
|
||||||
ChunkStatus cs = ChunkStatus.byId(stat);
|
|
||||||
if ((stat != null) && (cs.isAtLeast(ChunkStatus.LIGHT) || (cs == ChunkStatus.EMPTY))) { // ChunkStatus.LIGHT OR migrated EMPTY
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load generic chunk from existing and already loaded chunk
|
// Load generic chunk from existing and already loaded chunk
|
||||||
protected GenericChunk getLoadedChunk(DynmapChunk chunk) {
|
protected GenericChunk getLoadedChunk(DynmapChunk chunk) {
|
||||||
GenericChunk gc = null;
|
GenericChunk gc = null;
|
||||||
@ -85,7 +71,7 @@ public class FabricMapChunkCache extends GenericMapChunkCache {
|
|||||||
// TODO: find out why this is happening and why it only seems to happen since 1.16.2
|
// TODO: find out why this is happening and why it only seems to happen since 1.16.2
|
||||||
Log.severe("ChunkSerializer.serialize threw a NullPointerException", e);
|
Log.severe("ChunkSerializer.serialize threw a NullPointerException", e);
|
||||||
}
|
}
|
||||||
if (isLitChunk(nbt)) {
|
if (nbt != null) {
|
||||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +95,7 @@ public class FabricMapChunkCache extends GenericMapChunkCache {
|
|||||||
GenericChunk gc = null;
|
GenericChunk gc = null;
|
||||||
NbtCompound nbt = readChunk(chunk.x, chunk.z);
|
NbtCompound nbt = readChunk(chunk.x, chunk.z);
|
||||||
// If read was good
|
// If read was good
|
||||||
if (isLitChunk(nbt)) {
|
if (nbt != null) {
|
||||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||||
}
|
}
|
||||||
return gc;
|
return gc;
|
||||||
|
@ -31,27 +31,13 @@ public class ForgeMapChunkCache extends GenericMapChunkCache {
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLitChunk(CompoundTag nbt) {
|
|
||||||
if ((nbt != null) && nbt.contains("Level")) {
|
|
||||||
nbt = nbt.getCompound("Level");
|
|
||||||
}
|
|
||||||
if (nbt != null) {
|
|
||||||
String stat = nbt.getString("Status");
|
|
||||||
ChunkStatus cs = ChunkStatus.byName(stat);
|
|
||||||
if ((stat != null) && (cs.isOrAfter(ChunkStatus.LIGHT) || (cs == ChunkStatus.EMPTY))) { // ChunkStatus.LIGHT or migrated EMPTY
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load generic chunk from existing and already loaded chunk
|
// Load generic chunk from existing and already loaded chunk
|
||||||
protected GenericChunk getLoadedChunk(DynmapChunk chunk) {
|
protected GenericChunk getLoadedChunk(DynmapChunk chunk) {
|
||||||
GenericChunk gc = null;
|
GenericChunk gc = null;
|
||||||
ChunkAccess ch = cps.getChunk(chunk.x, chunk.z, ChunkStatus.FULL, false);
|
ChunkAccess ch = cps.getChunk(chunk.x, chunk.z, ChunkStatus.FULL, false);
|
||||||
if (ch != null) {
|
if (ch != null) {
|
||||||
CompoundTag nbt = ChunkSerializer.write(w, ch);
|
CompoundTag nbt = ChunkSerializer.write(w, ch);
|
||||||
if (isLitChunk(nbt)) {
|
if (nbt != null) {
|
||||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,7 +48,7 @@ public class ForgeMapChunkCache extends GenericMapChunkCache {
|
|||||||
GenericChunk gc = null;
|
GenericChunk gc = null;
|
||||||
CompoundTag nbt = readChunk(chunk.x, chunk.z);
|
CompoundTag nbt = readChunk(chunk.x, chunk.z);
|
||||||
// If read was good
|
// If read was good
|
||||||
if (isLitChunk(nbt)) {
|
if (nbt != null) {
|
||||||
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
gc = parseChunkFromNBT(new NBT.NBTCompound(nbt));
|
||||||
}
|
}
|
||||||
return gc;
|
return gc;
|
||||||
|
Loading…
Reference in New Issue
Block a user