recode mojang lightning

This commit is contained in:
LabyStudio
2022-02-02 12:46:08 +01:00
parent 14c13297fb
commit f1b6779221
6 changed files with 208 additions and 121 deletions
+143 -92
View File
@@ -21,37 +21,37 @@ window.Chunk = class {
// Create height map
this.heightMap = [];
this.initHeightMapAndLight();
}
setBlockAt(x, y, z, typeId) {
let section = this.getSection(y >> 4);
let prevTypeId = section.getBlockAt(x, y & 15, z);
if (prevTypeId === typeId) {
return;
}
initHeightMapAndLight() {
let highest = World.TOTAL_HEIGHT;
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
this.heightMap[z << 4 | x] = -1;
// Update block type id
section.setBlockAt(x, y & 15, z, typeId);
this.updateHeightMap(x, World.TOTAL_HEIGHT, z);
let block = Block.getById(typeId);
let heightLevel = this.heightMap[z << 4 | x] & 0xff;
if (typeId !== 0 && block.isSolid()) {
if (y >= heightLevel) {
// Update height map if it is the new highest block now
this.updateHeightMap(x, y + 1, z);
if ((this.heightMap[z << 4 | x] & 0xff) < highest) {
highest = this.heightMap[z << 4 | x] & 0xff;
}
}
} else if (y === heightLevel - 1) {
// Update height map if it is below the highest block because it could block the sun
this.updateHeightMap(x, y, z);
}
// Update light at block
//this.world.updateLight(EnumSkyBlock.SKY, x, y, z, x, y, z);
//this.world.updateLight(EnumSkyBlock.BLOCK, x, y, z, x, y, z);
this.highestY = highest;
for (let k = 0; k < 16; k++) {
for (let i1 = 0; i1 < 16; i1++) {
this.notifyNeighbors(k, i1);
}
}
this.queueForRebuild();
}
updateBlockLight() {
// Notify neighbors
//this.notifyNeighbors(x, z);
}
notifyNeighbors(x, z) {
@@ -72,6 +72,126 @@ window.Chunk = class {
} else if (height < y) {
this.world.updateLight(EnumSkyBlock.SKY, x, height, z, x, y, z);
}
this.queueForRebuild();
}
updateHeightMap(relX, y, relZ) {
let currentHighestY = this.heightMap[relZ << 4 | relX] & 0xff;
let highestY = currentHighestY;
if (y > currentHighestY) {
highestY = y;
}
while (highestY > 0 && Block.lightOpacity[this.getBlockAt(relX, highestY - 1, relZ)] === 0) {
highestY--;
}
if (highestY === currentHighestY) {
return;
}
//this.world.heightLevelChanged(relX, relZ, highestY, currentHighestY);
this.heightMap[relZ << 4 | relX] = highestY;
if (highestY < this.highestY) {
this.highestY = highestY;
} else {
let highest = 127;
for (let cx = 0; cx < 16; cx++) {
for (let cz = 0; cz < 16; cz++) {
if ((this.heightMap[cz << 4 | cx] & 0xff) < highest) {
highest = this.heightMap[cz << 4 | cx] & 0xff;
}
}
}
this.highestY = highest;
}
let x = this.x * 16 + relX;
let z = this.z * 16 + relZ;
if (highestY < currentHighestY) {
for (let l2 = highestY; l2 < currentHighestY; l2++) {
this.setLightAt(EnumSkyBlock.SKY, relX, l2, relZ, 15);
}
} else {
this.world.updateLight(EnumSkyBlock.SKY, x, currentHighestY, z, x, highestY, z);
for (let hy = currentHighestY; hy < highestY; hy++) {
this.setLightAt(EnumSkyBlock.SKY, relX, hy, relZ, 0);
}
}
let lightLevel = 15;
let prevHeight = highestY;
while (highestY > 0 && lightLevel > 0) {
highestY--;
let opacity = Block.lightOpacity[this.getBlockID(relX, highestY, relZ)];
if (opacity === 0) {
opacity = 1;
}
lightLevel -= opacity;
if (lightLevel < 0) {
lightLevel = 0;
}
this.setLightAt(EnumSkyBlock.SKY, relX, highestY, relZ, lightLevel);
}
for (; highestY > 0 && Block.lightOpacity[this.getBlockID(relX, highestY - 1, relZ)] === 0; highestY--) {
}
if (highestY !== prevHeight) {
this.world.updateLight(EnumSkyBlock.SKY, x - 1, highestY, z - 1, x + 1, prevHeight, z + 1);
}
this.queueForRebuild();
}
setLightAt(sourceType, x, y, z, level) {
this.getSection(y >> 4).setLightAt(sourceType, x, y & 15, z, level);
}
setBlockAt(x, y, z, typeId) {
let byte0 = typeId;
let height = this.heightMap[z << 4 | x] & 0xff;
let prevTypeId = this.getBlockAt(x, y, z);
if (prevTypeId === typeId) {
return false;
}
let totalX = this.x * 16 + x;
let totalZ = this.z * 16 + z;
this.getSection(y >> 4).setBlockAt(x, y & 15, z, byte0);
//if (k1 !== 0 && !this.worldObj.multiplayerWorld) {
//Block.blocksList[k1].onBlockRemoval(this.world, l1, j, i2);
//}
//this.data.setNibble(i, j, k, i1);
//if (!this.worldObj.worldProvider.field_6478_e) {
if (Block.lightOpacity[byte0] !== 0) {
if (y >= height) {
this.updateHeightMap(x, y + 1, z);
}
} else if (y === height - 1) {
this.updateHeightMap(x, y, z);
}
this.world.updateLight(EnumSkyBlock.SKY, totalX, y, totalZ, totalX, y, totalZ);
//}
this.world.updateLight(EnumSkyBlock.BLOCK, totalX, y, totalZ, totalX, y, totalZ);
this.notifyNeighbors(x, z);
if (typeId !== 0) {
//Block.blocksList[l].onBlockAdded(this.worldObj, l1, j, i2);
}
//this.data.setNibble(i, j, k, i1);
this.queueForRebuild();
return true;
}
getBlockID(x, y, z) {
return this.getBlockAt(x, y, z);
}
getBlockAt(x, y, z) {
@@ -86,75 +206,6 @@ window.Chunk = class {
return this.heightMap[z << 4 | x] & 0xff;
}
updateHeightMap(x, y, z) {
let currentHighestY = this.heightMap[z << 4 | x] & 0xff;
let highestY = currentHighestY;
if (y > currentHighestY) {
highestY = y;
}
// Find new highest blocks
while (highestY > 0) {
let typeId = this.getBlockAt(x, highestY, z);
let block = Block.getById(typeId);
if (typeId !== 0 && block.isSolid()) {
break;
}
highestY--;
}
// Check if highest block changed
if (highestY === currentHighestY) {
return;
}
// Save in height map
this.heightMap[z << 4 | x] = highestY;
let totalX = this.x * 16 + x;
let totalZ = this.z * 16 + z;
if (highestY < currentHighestY) {
for (let hy = highestY; hy < currentHighestY; hy++) {
this.getSection(hy >> 4).setLightAt(EnumSkyBlock.SKY, x, hy, z, 15);
}
} else {
this.world.updateLight(EnumSkyBlock.SKY, totalX, currentHighestY, totalZ, totalX, highestY, totalZ);
for (let hy = currentHighestY; hy < highestY; hy++) {
this.getSection(hy >> 4).setLightAt(EnumSkyBlock.SKY, x, hy, z, 0);
}
}
let lightLevel = 15;
let currentY = highestY;
while (currentY > 0 && lightLevel > 0) {
currentY--;
let typeId = this.getBlockAt(x, currentY, z);
let block = Block.getById(typeId);
// Reduce light level by opacity
if (typeId !== 0) {
lightLevel *= (1 - block.getOpacity());
}
// Min light level
if (lightLevel < 0) {
lightLevel = 0;
}
// Update light level
this.getSection(currentY >> 4).setLightAt(EnumSkyBlock.SKY, x & 15, currentY, z & 15, lightLevel);
}
if (currentY !== highestY) {
this.world.updateLight(EnumSkyBlock.SKY, x - 1, currentY, z - 1, x + 1, currentY, z + 1);
}
}
getSection(y) {
return this.sections[y];
}