improve mojang lightning

This commit is contained in:
LabyStudio
2022-02-03 01:18:22 +01:00
parent 9a70a3cc37
commit 0a16cb9721
9 changed files with 167 additions and 112 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ window.GameWindow = class {
// Stats
this.stats = new Stats()
this.stats.showPanel(1);
this.stats.showPanel(0);
wrapper.appendChild(this.stats.dom);
// Add web renderer canvas to wrapper
+4
View File
@@ -27,6 +27,10 @@ window.Minecraft = class {
}
init() {
// Load spawn chunk
this.world.getChunkAt(0, 0);
this.player.respawn();
// Start render loop
this.running = true;
this.requestNextFrame();
+23 -12
View File
@@ -42,22 +42,33 @@ window.Player = class {
this.prevFovModifier = 0;
this.fovModifier = 0;
this.timeFovChanged = 0;
this.resetPos();
}
resetPos() {
this.setPos(0, 80, 0);
respawn() {
let spawnY = this.world.getHeightAt(0, 0);
this.setPosition(0, spawnY + 8, 0);
}
setPos(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
setPosition(x, y, z) {
let width = 0.3;
let height = 0.9;
this.boundingBox = new BoundingBox(
x - width,
y - height,
z - width,
x + width,
y + height,
z + width
);
let w = 0.3;
let h = 0.9;
this.boundingBox = new BoundingBox(x - w, y - h, z - w, x + w, y + h, z + w);
this.motionX = 0;
this.motionY = 0;
this.motionZ = 0;
// Update position
this.x = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0;
this.y = this.boundingBox.minY;
this.z = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0;
}
turn(motionX, motionY) {
@@ -299,7 +310,7 @@ window.Player = class {
let sneaking = false;
if (Keyboard.isKeyDown("KeyR")) { // R
this.resetPos();
this.respawn();
}
if (Keyboard.isKeyDown("KeyW")) { // W
moveForward++;
@@ -1,6 +1,6 @@
window.BlockRenderer = class {
static CLASSIC_LIGHTNING = true;
static CLASSIC_LIGHTNING = false;
constructor(worldRenderer) {
this.worldRenderer = worldRenderer;
+74 -81
View File
@@ -26,27 +26,22 @@ window.Chunk = class {
}
generateSkylightMap() {
let highest = World.TOTAL_HEIGHT;
// Calculate height map
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
this.heightMap[z << 4 | x] = -1;
this.setHeightAt(x, z, 0); // TODO set to 0 to calculate proper lightning
this.updateHeightMap(x, World.TOTAL_HEIGHT, z);
if ((this.heightMap[z << 4 | x] & 0xff) < highest) {
highest = this.heightMap[z << 4 | x] & 0xff;
}
}
}
this.highestY = highest;
for (let k = 0; k < 16; k++) {
for (let i1 = 0; i1 < 16; i1++) {
this.notifyNeighbors(k, i1);
// Update light of neighbor blocks
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
this.notifyNeighbors(x, z);
}
}
// Rebuild all sections
this.setModifiedAllSections();
}
@@ -76,57 +71,34 @@ window.Chunk = class {
}
updateHeightMap(relX, y, relZ) {
let currentHighestY = this.heightMap[relZ << 4 | relX] & 0xff;
let currentHighestY = this.getHeightAt(relX, relZ);
let highestY = currentHighestY;
if (y > currentHighestY) {
highestY = y;
}
while (highestY > 0) {
let typeId = this.getBlockAt(relX, highestY, relZ);
let block = Block.getById(typeId);
if (typeId !== 0 && block.getOpacity() !== 0) {
break;
}
highestY = this.calculateHeightAt(relX, relZ, highestY);
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;
}
this.setHeightAt(relX, relZ, highestY);
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);
for (let hy = highestY; hy < currentHighestY; hy++) {
this.setLightAt(EnumSkyBlock.SKY, relX, hy, 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) {
@@ -147,15 +119,7 @@ window.Chunk = class {
this.setLightAt(EnumSkyBlock.SKY, relX, highestY, relZ, lightLevel);
}
while (highestY > 0) {
let typeId = this.getBlockID(relX, highestY - 1, relZ);
let block = Block.getById(typeId);
if (typeId !== 0 && block.isSolid()) {
break;
}
highestY--;
}
highestY = this.calculateHeightAt(relX, relZ, highestY);
if (highestY !== prevHeight) {
this.world.updateLight(EnumSkyBlock.SKY, x - 1, highestY, z - 1, x + 1, prevHeight, z + 1);
@@ -163,34 +127,76 @@ window.Chunk = class {
this.setModifiedAllSections();
}
calculateHeightAt(x, z, startY) {
let y = startY;
while (y > 0) {
let typeId = this.getBlockAt(x, y - 1, z);
let block = Block.getById(typeId);
let opacity = typeId === 0 ? 0 : block.getOpacity();
if (opacity !== 0) {
break;
}
y--;
}
return y;
}
updateHeightMapAt(x, z) {
let y = this.calculateHeightAt(x, z, World.TOTAL_HEIGHT);
this.setHeightAt(x, z, y);
}
setHeightAt(x, z, height) {
this.heightMap[z << 4 | x] = height;
}
/**
* Is the highest solid block or above
*/
isHighestBlock(x, y, z) {
return y >= this.getHighestBlockAt(x, z);
}
/**
* Is above the highest solid block
*/
isAboveGround(x, y, z) {
return y >= this.getHeightAt(x, z);
}
/**
* Get the first non-solid block
*/
getHeightAt(x, z) {
return this.heightMap[z << 4 | x];
}
/**
* Get the highest solid block
*/
getHighestBlockAt(x, z) {
return this.getHeightAt(x, z) - 1;
}
setLightAt(sourceType, x, y, z, level) {
this.getSection(y >> 4).setLightAt(sourceType, x, y & 15, z, level);
let section = this.getSection(y >> 4);
section.setLightAt(sourceType, x, y & 15, z, level);
}
setBlockAt(x, y, z, typeId) {
let byte0 = typeId;
let height = this.heightMap[z << 4 | x] & 0xff;
let height = this.getHeightAt(x, z);
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);
this.getSection(y >> 4).setBlockAt(x, y & 15, z, typeId);
if (!this.loaded) {
return;
}
//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) {
let block = Block.getById(typeId);
if (typeId !== 0 && block.isSolid()) {
if (y >= height) {
@@ -200,18 +206,13 @@ window.Chunk = class {
this.updateHeightMap(x, y, z);
}
let totalX = this.x * 16 + x;
let totalZ = this.z * 16 + 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.setModifiedAllSections();
return true;
}
@@ -224,14 +225,6 @@ window.Chunk = class {
return this.getSection(y >> 4).getBlockAt(x, y & 15, z);
}
isHighestBlock(x, y, z) {
return y >= (this.heightMap[z << 4 | x] & 0xff);
}
getHeightAt(x, z) {
return this.heightMap[z << 4 | x] & 0xff;
}
getSection(y) {
return this.sections[y];
}
+61 -14
View File
@@ -1,18 +1,18 @@
window.World = class {
static TOTAL_HEIGHT = ChunkSection.SIZE * 16 - 1;
static TOTAL_HEIGHT = ChunkSection.SIZE * 8 - 1; // ChunkSection.SIZE * 16 - 1;
constructor(minecraft) {
this.minecrat = minecraft;
this.group = new THREE.Object3D();
this.group.matrixAutoUpdate = false;
this.chunks = new Map();
this.lightUpdateQueue = [];
// Load world
this.generator = new WorldGenerator(this, Date.now() % 100000);
this.lightUpdateQueue = [];
}
onTick() {
@@ -81,14 +81,35 @@ window.World = class {
}
updateLights() {
// Update lights in queue
let i = 5000;
while (this.lightUpdateQueue.length > 0) {
if (i <= 0) {
return true;
let scope = this;
if (this.lightUpdateQueue.length > 10) {
// Update lights async
setTimeout(function () {
// Update lights in queue
let i = 5000;
while (scope.lightUpdateQueue.length > 0) {
if (i <= 0) {
break;
}
let meta = scope.lightUpdateQueue.shift();
meta.updateBlockLightning(scope);
i--;
}
}, 0);
} else {
// Update lights in queue
let i = 10;
while (scope.lightUpdateQueue.length > 0) {
if (i <= 0) {
return true;
}
let meta = scope.lightUpdateQueue.shift();
meta.updateBlockLightning(scope);
i--;
}
this.lightUpdateQueue.shift().updateBlockLightning(this);
i--;
}
return false;
}
@@ -116,8 +137,11 @@ window.World = class {
}
}
// Add light update region to queue
this.lightUpdateQueue.push(new MetadataChunkBlock(sourceType, x1, y1, z1, x2, y2, z2));
if (this.lightUpdateQueue.length > 0x186a0) {
// Max light updates in queue
if (this.lightUpdateQueue.length > 100000) {
this.lightUpdateQueue = [];
}
}
@@ -141,7 +165,7 @@ window.World = class {
return;
}
if (sourceType === EnumSkyBlock.SKY) {
if (this.isHighestBlock(x, y, z)) {
if (this.isAboveGround(x, y, z)) {
level = 15;
}
} else if (sourceType === EnumSkyBlock.BLOCK) {
@@ -155,17 +179,40 @@ window.World = class {
}
}
/**
* Get the first non-solid block
*/
getHeightAt(x, z) {
if (!this.chunkExists(x >> 4, z >> 4)) {
return 0;
}
return this.getChunkAt(x >> 4, z >> 4).getHeightAt(x & 15, z & 15);
}
/**
* Get the highest solid block
*/
getHighestBlockAt(x, z) {
if (!this.chunkExists(x >> 4, z >> 4)) {
return 0;
}
return this.getChunkAt(x >> 4, z >> 4).getHighestBlockAt(x & 15, z & 15);
}
/**
* Is the highest solid block or above
*/
isHighestBlock(x, y, z) {
let chunk = this.getChunkAt(x >> 4, z >> 4)
return y >= chunk.getHeightAt(x & 15, z & 15);
return chunk.isHighestBlock(x & 15, y, z & 15);
}
/**
* Is above the highest solid block
*/
isAboveGround(x, y, z) {
let chunk = this.getChunkAt(x >> 4, z >> 4)
return chunk.isAboveGround(x & 15, y, z & 15);
}
getTotalLightAt(x, y, z) {
@@ -5,7 +5,7 @@ window.BlockWater = class extends Block {
}
getOpacity() {
return 0.93;
return 0.01;
}
isSolid() {
@@ -117,7 +117,7 @@ window.WorldGenerator = class {
if (perlin > 0 && this.random.nextInt(2) === 0) {
// Get the highest block at this position
let highestY = this.world.getHeightAt(absoluteX, absoluteZ);
let highestY = this.world.getHighestBlockAt(absoluteX, absoluteZ);
// Don't place a tree if there is no grass
if (this.world.getBlockAt(absoluteX, highestY, absoluteZ) === Block.GRASS.getId()
@@ -42,7 +42,7 @@ window.MetadataChunkBlock = class {
let level = 0;
if (this.type === EnumSkyBlock.SKY) {
if (world.isHighestBlock(x, y, z)) {
if (world.isAboveGround(x, y, z)) {
level = 15;
}
} else if (this.type === EnumSkyBlock.BLOCK) {