recode mojang lightning
This commit is contained in:
@@ -47,7 +47,7 @@ window.BlockRenderer = class {
|
||||
|
||||
// Classic lightning
|
||||
if (BlockRenderer.CLASSIC_LIGHTNING) {
|
||||
let brightness = 0.9 / 15.0 * world.getLightAt(minX + face.x, minY + face.y, minZ + face.z) + 0.1;
|
||||
let brightness = 0.9 / 15.0 * world.getTotalLightAt(minX + face.x, minY + face.y, minZ + face.z) + 0.1;
|
||||
let color = brightness * face.getShading();
|
||||
this.tessellator.setColor(color, color, color);
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -84,7 +84,13 @@ window.ChunkSection = class {
|
||||
|
||||
setLightAt(sourceType, x, y, z, lightLevel) {
|
||||
let index = y << 8 | z << 4 | x;
|
||||
this.blockLight[index] = lightLevel;
|
||||
|
||||
if (sourceType === EnumSkyBlock.SKY) {
|
||||
this.skyLight[index] = lightLevel;
|
||||
}
|
||||
if (sourceType === EnumSkyBlock.BLOCK) {
|
||||
this.blockLight[index] = lightLevel;
|
||||
}
|
||||
}
|
||||
|
||||
getTotalLightAt(x, y, z) {
|
||||
@@ -102,7 +108,7 @@ window.ChunkSection = class {
|
||||
if (sourceType === EnumSkyBlock.SKY) {
|
||||
return this.skyLight[index];
|
||||
}
|
||||
if (sourceType === EnumSkyBlock.Block) {
|
||||
if (sourceType === EnumSkyBlock.BLOCK) {
|
||||
return this.blockLight[index];
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -63,7 +63,12 @@ window.World = class {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lightUpdates++;
|
||||
let centerX = (x2 + x1) / 2;
|
||||
let centerZ = (z2 + z1) / 2;
|
||||
|
||||
if (!this.blockExists(centerX, 64, centerZ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let size = this.lightUpdateQueue.length;
|
||||
|
||||
@@ -72,39 +77,49 @@ window.World = class {
|
||||
if (max > size) {
|
||||
max = size;
|
||||
}
|
||||
|
||||
for (let i = 0; i < max; i++) {
|
||||
let meta = this.lightUpdateQueue[size - i - 1];
|
||||
let meta = this.lightUpdateQueue[(this.lightUpdateQueue.length - i - 1)];
|
||||
if (meta.type === sourceType && meta.isOutsideOf(x1, y1, z1, x2, y2, z2)) {
|
||||
this.lightUpdates--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push light update to queue
|
||||
}
|
||||
this.lightUpdateQueue.push(new MetadataChunkBlock(sourceType, x1, y1, z1, x2, y2, z2));
|
||||
if (this.lightUpdateQueue.length > 0x186a0) {
|
||||
this.lightUpdateQueue = [];
|
||||
}
|
||||
this.lightUpdates--;
|
||||
}
|
||||
|
||||
neighborLightPropagationChanged(sourceType, x, y, z, lightLevel) {
|
||||
blockExists(x, y, z) {
|
||||
if (y < 0 || y >= 128) {
|
||||
return false;
|
||||
} else {
|
||||
return this.chunkExists(x >> 4, z >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
chunkExists(chunkX, chunkZ) {
|
||||
let index = chunkX + (chunkZ << 16);
|
||||
let chunk = this.chunks.get(index);
|
||||
return typeof chunk !== 'undefined';
|
||||
}
|
||||
|
||||
neighborLightPropagationChanged(sourceType, x, y, z, level) {
|
||||
if (!this.blockExists(x, y, z)) {
|
||||
return;
|
||||
}
|
||||
if (sourceType === EnumSkyBlock.SKY) {
|
||||
if (this.isHighestBlock(x, y, z)) {
|
||||
lightLevel = 15;
|
||||
level = 15;
|
||||
}
|
||||
} else if (sourceType === EnumSkyBlock.BLOCK) {
|
||||
let typeId = this.getBlockAt(x, y, z);
|
||||
let block = Block.getById(typeId);
|
||||
let blockLight = block.getLightValue();
|
||||
|
||||
if (blockLight > lightLevel) {
|
||||
lightLevel = blockLight;
|
||||
let i1 = this.getBlockAt(x, y, z);
|
||||
if (0 > level) { // TODO
|
||||
level = 0;
|
||||
}
|
||||
}
|
||||
if (this.getSavedLightValue(sourceType, x, y, z) !== lightLevel) {
|
||||
if (this.getSavedLightValue(sourceType, x, y, z) !== level) {
|
||||
this.updateLight(sourceType, x, y, z, x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -130,6 +145,10 @@ window.World = class {
|
||||
}
|
||||
|
||||
getHeightAt(x, z) {
|
||||
if (!this.chunkExists(x >> 4, z >> 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.getChunkAt(x >> 4, z >> 4).getHeightAt(x & 15, z & 15);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ window.Block = class {
|
||||
|
||||
static blocks = new Map();
|
||||
|
||||
static lightOpacity = [];
|
||||
|
||||
static create() {
|
||||
Block.STONE = new BlockStone(1, 0);
|
||||
Block.GRASS = new BlockGrass(2, 1);
|
||||
@@ -20,6 +22,7 @@ window.Block = class {
|
||||
|
||||
// Register block
|
||||
Block.blocks.set(id, this);
|
||||
Block.lightOpacity[id] = this.isSolid() ? 255 : 0;
|
||||
}
|
||||
|
||||
getId() {
|
||||
|
||||
@@ -11,29 +11,41 @@ window.MetadataChunkBlock = class {
|
||||
}
|
||||
|
||||
updateBlockLightning(world) {
|
||||
let centerX = (this.x2 - this.x1) + 1;
|
||||
let centerY = (this.y2 - this.y1) + 1;
|
||||
let centerZ = (this.z2 - this.z1) + 1;
|
||||
let index = centerX * centerY * centerZ;
|
||||
if (index > 32768) {
|
||||
return;
|
||||
}
|
||||
for (let x = this.x1; x <= this.x2; x++) {
|
||||
for (let z = this.z1; z <= this.z2; z++) {
|
||||
if (!world.blockExists(x, 0, z)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let y = this.y1; y <= this.y2; y++) {
|
||||
if (y < 0 || y >= World.TOTAL_HEIGHT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let savedLightValue = world.getSavedLightValue(this.type, x, y, z);
|
||||
|
||||
let level = 0;
|
||||
let newLevel = 0;
|
||||
|
||||
let typeId = world.getBlockAt(x, y, z);
|
||||
let block = Block.getById(typeId);
|
||||
let opacity = Block.lightOpacity[typeId];
|
||||
|
||||
let opacity = typeId === 0 ? 0 : (block.getOpacity() * 255);
|
||||
if (opacity === 0) {
|
||||
opacity = 1;
|
||||
}
|
||||
|
||||
let level = 0;
|
||||
|
||||
if (this.type === EnumSkyBlock.SKY) {
|
||||
if (world.isHighestBlock(x, y, z)) {
|
||||
level = 15;
|
||||
}
|
||||
} else if (this.type === EnumSkyBlock.BLOCK) {
|
||||
level = typeId === 0 ? 0 : block.getLightValue();
|
||||
level = 0; // TODO
|
||||
}
|
||||
|
||||
if (opacity >= 15 && level === 0) {
|
||||
@@ -63,9 +75,7 @@ window.MetadataChunkBlock = class {
|
||||
if (z2Level > newLevel) {
|
||||
newLevel = z2Level;
|
||||
}
|
||||
|
||||
newLevel -= opacity;
|
||||
|
||||
if (newLevel < 0) {
|
||||
newLevel = 0;
|
||||
}
|
||||
@@ -73,11 +83,9 @@ window.MetadataChunkBlock = class {
|
||||
newLevel = level;
|
||||
}
|
||||
}
|
||||
|
||||
if (savedLightValue === newLevel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
world.setLightAt(this.type, x, y, z, newLevel);
|
||||
|
||||
let decreasedLevel = newLevel - 1;
|
||||
|
||||
Reference in New Issue
Block a user