lighting sort of works

This commit is contained in:
Holly Stubbs 2023-06-19 18:29:16 +01:00
parent 5396b83f3f
commit 3b208eb8db
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
10 changed files with 80 additions and 52 deletions

View file

@ -1,8 +1,7 @@
{
"port": 25565,
"onlineMode": false,
"maxPlayers": 20,
"seed": "really janky",
"saveCompression": "DEFLATE",
"saveCompression": "NONE",
"worldName": "world"
}

View file

@ -2,7 +2,6 @@ import { SaveCompressionType } from "./server/enums/SaveCompressionType";
export interface Config {
port: number,
onlineMode: boolean,
maxPlayers: number,
seed: number|string,
worldName: string,

View file

@ -1,3 +1,4 @@
import { Console } from "../console";
import { FunkyArray } from "../funkyArray";
import { NibbleArray } from "../nibbleArray";
import { Block } from "./blocks/Block";
@ -40,7 +41,7 @@ export class Chunk {
this.metadata = new NibbleArray(metadata);
this.skyLight = new NibbleArray(16 * 16 * this.MAX_HEIGHT);
this.blockLight = new NibbleArray(16 * 16 * this.MAX_HEIGHT);
//this.calculateLighting();
this.calculateLighting();
} else {
this.blocks = new Uint8Array(16 * 16 * this.MAX_HEIGHT);
this.metadata = new NibbleArray(16 * 16 * this.MAX_HEIGHT);
@ -49,7 +50,7 @@ export class Chunk {
if (typeof(generateOrBlockData) === "boolean" && generateOrBlockData) {
this.world.generator.generate(this);
//this.calculateLighting();
this.calculateLighting();
}
}
}
@ -57,7 +58,7 @@ export class Chunk {
public getTopBlockY(x:number, z:number) {
let castY = this.MAX_HEIGHT;
while (castY-- > 0) {
if (this.getBlockId(x, castY, z) !== 0) {
if (this.getBlockId(x >>> 0, castY, z >>> 0) !== 0) {
break;
}
}
@ -66,10 +67,10 @@ export class Chunk {
public calculateLighting() {
let blockId = 0;
for (let y = 0; y < 128; y++) {
let colLight = 255;
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
let colLight = 255;
for (let y = this.MAX_HEIGHT - 1; y > 0; y--) {
blockId = this.getBlockId(x, y, z);
if (blockId == 0) {
if (colLight <= 0) {
@ -79,16 +80,15 @@ export class Chunk {
this.setBlockLight(Math.round((colLight / 255) * 15), x, y, z);
this.setSkyLight(Math.round((colLight / 255) * 15), x, y, z);
}
continue;
}
if (colLight <= 0) {
this.setBlockLight(0, x, y, z);
} else {
this.setBlockLight(Math.round((colLight / 255) * 15), x, y, z);
colLight -= (255 - Block.blocks[blockId].lightPassage);
if (colLight <= 0) {
this.setBlockLight(0, x, y, z);
} else {
this.setBlockLight(Math.round((colLight / 255) * 15), x, y, z);
colLight -= (255 - Block.blocks[blockId].lightPassage);
}
}
}
}
}
}
}

View file

@ -87,7 +87,7 @@ export class MPClient {
packet.message = `Woosh!`;
const topBlock = this.entity.world.getChunk(this.entity.x >> 4, this.entity.z >> 4).getTopBlockY(this.entity.x & 0xf, this.entity.z & 0xf);
console.log(topBlock);
this.send(new PacketPlayerPositionLook(this.entity.x, topBlock, topBlock + 0.62, this.entity.z, this.entity.yaw, this.entity.pitch, false).writeData());
this.send(new PacketPlayerPosition(this.entity.x, topBlock + 4, topBlock + 4.62, this.entity.z, false).writeData());
}
if (packet.message !== "") {

View file

@ -75,7 +75,7 @@ export class MinecraftServer {
this.worlds.set(0, this.overworld = new World(this.saveManager, worldSeed));
// Generate spawn area (overworld)
(async () => {
/*(async () => {
const generateStartTime = Date.now();
Console.printInfo("Generating spawn area...");
for (let x = -3; x < 3; x++) {
@ -84,6 +84,16 @@ export class MinecraftServer {
}
}
Console.printInfo(`Done! Took ${Date.now() - generateStartTime}ms`);
}).bind(this)();*/
(async () => {
const generateStartTime = Date.now();
Console.printInfo("Generating spawn area...");
for (let x = 0; x < 1; x++) {
for (let z = 0; z < 1; z++) {
await this.overworld.getChunkSafe(x, z);
}
}
Console.printInfo(`Done! Took ${Date.now() - generateStartTime}ms`);
}).bind(this)();
this.serverClock = setInterval(() => {

View file

@ -12,6 +12,7 @@ import { IQueuedUpdate } from "./queuedUpdateTypes/IQueuedUpdate";
export class World {
public static ENTITY_MAX_SEND_DISTANCE = 50;
private static READ_CHUNKS_FROM_DISK = false;
private readonly saveManager;
@ -84,7 +85,7 @@ export class World {
const coordPair = Chunk.CreateCoordPair(x, z);
const existingChunk = this.chunks.get(coordPair);
if (!(existingChunk instanceof Chunk)) {
if (this.saveManager.chunksOnDisk.includes(coordPair)) {
if (World.READ_CHUNKS_FROM_DISK && this.saveManager.chunksOnDisk.includes(coordPair)) {
return this.saveManager.readChunkFromDisk(this, x, z)
.then(chunk => {
//console.log("Loaded " + x + "," + z + " from disk");
@ -92,7 +93,9 @@ export class World {
});
} else {
resolve(this.chunks.set(coordPair, new Chunk(this, x, z, true)));
this.saveManager.writeChunkToDisk(this.getChunk(x, z));
if (World.READ_CHUNKS_FROM_DISK) {
this.saveManager.writeChunkToDisk(this.getChunk(x, z));
}
return;
}
}

View file

@ -87,12 +87,15 @@ export class WorldSaveManager {
}
public writeChunkToDisk(chunk:Chunk) {
return new Promise<boolean>((resolve, reject) => {
resolve(false);
});
return new Promise<boolean>((resolve, reject) => {
const saveType = this.config.saveCompression;
const chunkFileWriter = createWriter(Endian.BE, 10);
chunkFileWriter.writeUByte(0xFC); // Chunk File Magic
// TODO: Change to 1 when lighting actually works
chunkFileWriter.writeUByte(0); // File Version
chunkFileWriter.writeUByte(1); // File Version
chunkFileWriter.writeUByte(saveType); // Save compression type
chunkFileWriter.writeUByte(16); // Chunk X
chunkFileWriter.writeUByte(128); // Chunk Y
@ -100,15 +103,15 @@ export class WorldSaveManager {
const chunkData = createWriter(Endian.BE)
.writeBuffer(Buffer.from(chunk.getData()))
.writeBuffer(chunk.getMetadataBuffer()).toBuffer()
//.writeBuffer(chunk.getBlockLightBuffer())
//.writeBuffer(chunk.getSkyLightBuffer()).toBuffer();
.writeBuffer(chunk.getMetadataBuffer())
.writeBuffer(chunk.getBlockLightBuffer())
.writeBuffer(chunk.getSkyLightBuffer()).toBuffer();
if (saveType === SaveCompressionType.NONE) {
chunkFileWriter.writeInt(chunkData.length); // Data length
chunkFileWriter.writeBuffer(chunkData); // Chunk data
writeFile(`${this.worldChunksFolderPath}/${Chunk.CreateCoordPair(chunk.x, chunk.z)}.hwc`, chunkFileWriter.toBuffer(), () => {
writeFile(`${this.worldChunksFolderPath}/${Chunk.CreateCoordPair(chunk.x, chunk.z).toString(16)}.hwc`, chunkFileWriter.toBuffer(), () => {
const cPair = Chunk.CreateCoordPair(chunk.x, chunk.z);
if (!this.chunksOnDisk.includes(cPair)) {
this.chunksOnDisk.push(cPair);
@ -125,7 +128,7 @@ export class WorldSaveManager {
chunkFileWriter.writeInt(data.length);
chunkFileWriter.writeBuffer(data);
writeFile(`${this.worldChunksFolderPath}/${Chunk.CreateCoordPair(chunk.x, chunk.z)}.hwc`, chunkFileWriter.toBuffer(), () => {
writeFile(`${this.worldChunksFolderPath}/${Chunk.CreateCoordPair(chunk.x, chunk.z).toString(16)}.hwc`, chunkFileWriter.toBuffer(), () => {
const cPair = Chunk.CreateCoordPair(chunk.x, chunk.z);
if (!this.chunksOnDisk.includes(cPair)) {
this.chunksOnDisk.push(cPair);
@ -142,7 +145,7 @@ export class WorldSaveManager {
readChunkFromDisk(world:World, x:number, z:number) {
return new Promise<Chunk>((resolve, reject) => {
readFile(`${this.worldChunksFolderPath}/${Chunk.CreateCoordPair(x, z)}.hwc`, (err, data) => {
readFile(`${this.worldChunksFolderPath}/${Chunk.CreateCoordPair(x, z).toString(16)}.hwc`, (err, data) => {
if (err) {
return reject(err);
}
@ -188,7 +191,7 @@ export class WorldSaveManager {
const contentLength = chunkFileReader.readInt();
if (saveCompressionType === SaveCompressionType.NONE) {
const chunkData = createReader(Endian.BE, chunkFileReader.readBuffer(contentLength));
const chunk = new Chunk(world, x, z, chunkData.readUint8Array(totalByteSize), chunkData.readUint8Array(totalByteSize / 2));
const chunk = new Chunk(world, x, z, chunkData.readUint8Array(totalByteSize), chunkData.readUint8Array(totalByteSize / 2), chunkData.readUint8Array(totalByteSize / 2), chunkData.readUint8Array(totalByteSize / 2));
resolve(chunk);
} else if (saveCompressionType === SaveCompressionType.DEFLATE) {
inflate(chunkFileReader.readBuffer(contentLength), (err, data) => {

View file

@ -2,10 +2,12 @@ export class Block {
public readonly blockId:number;
public static readonly blocks:Array<Block> = new Array<Block>();
public static readonly lightPassage:Array<number> = new Array<number>();
public static readonly blockNames:Array<string> = new Array<string>();
public constructor(blockId:number) {
Block.blocks[blockId] = this;
Block.lightPassage[blockId] = 0;
Block.blockNames[blockId] = "";
this.blockId = blockId;
}
@ -17,34 +19,47 @@ export class Block {
Block.lightPassage[this.blockId] = value;
}
public get blockName() {
return Block.blockNames[this.blockId];
}
public set blockName(value:string) {
Block.blockNames[this.blockId] = value;
}
public setLightPassage(value:number) {
this.lightPassage = value;
return this;
}
public setBlockName(value:string) {
this.blockName = value;
return this;
}
// Define statics here
static readonly stone = new Block(1);
static readonly grass = new Block(2);
static readonly dirt = new Block(3);
static readonly stone = new Block(1).setBlockName("Stone");
static readonly grass = new Block(2).setBlockName("Grass");
static readonly dirt = new Block(3).setBlockName("Dirt");
static readonly bedrock = new Block(7);
static readonly bedrock = new Block(7).setBlockName("Bedrock");
static readonly waterStill = new Block(9).setLightPassage(3);
static readonly waterStill = new Block(9).setLightPassage(128).setBlockName("Still Water");
static readonly lavaStill = new Block(11);
static readonly lavaStill = new Block(11).setBlockName("Still Lava");
static readonly sand = new Block(12);
static readonly gravel = new Block(13);
static readonly sand = new Block(12).setBlockName("Sand");
static readonly gravel = new Block(13).setBlockName("Gravel");
static readonly wood = new Block(17);
static readonly leaves = new Block(18).setLightPassage(1);
static readonly wood = new Block(17).setBlockName("Wood");
static readonly leaves = new Block(18).setLightPassage(240).setBlockName("Leaves");
static readonly glass = new Block(20).setLightPassage(255);
static readonly glass = new Block(20).setLightPassage(255).setBlockName("Glass");
static readonly tallGrass = new Block(31);
static readonly tallGrass = new Block(31).setLightPassage(255).setBlockName("Tall Grass");
static readonly flowerDandelion = new Block(37);
static readonly flowerRose = new Block(38);
static readonly flowerDandelion = new Block(37).setLightPassage(255).setBlockName("Dandelion");
static readonly flowerRose = new Block(38).setLightPassage(255).setBlockName("Rose");
static readonly clay = new Block(82);
static readonly clay = new Block(82).setBlockName("Clay");
}

View file

@ -24,6 +24,7 @@ export class HillyGenerator implements IGenerator {
private caveGenerator3:Noise3D;
private caveGenerator4:Noise3D;
private caveGenerator5:Noise3D;
private caveGenerator6:Noise3D;
private underwaterGravelGenerator:Noise2D;
private underwaterSandGenerator:Noise2D;
@ -49,13 +50,12 @@ export class HillyGenerator implements IGenerator {
this.caveGenerator3 = this.createGenerator3D();
this.caveGenerator4 = this.createGenerator3D();
this.caveGenerator5 = this.createGenerator3D();
this.caveGenerator6 = this.createGenerator3D();
this.underwaterGravelGenerator = this.createGenerator2D();
this.underwaterSandGenerator = this.createGenerator2D();
this.underwaterClayGenerator = this.createGenerator2D();
this.flowerGenerator = this.createGenerator2D();
}
private createGenerator2D() {
@ -144,8 +144,7 @@ export class HillyGenerator implements IGenerator {
((this.caveGenerator1((chunk.x * 16 + x) / 16, caveY / 16, (chunk.z * 16 + z) / 16) +
this.caveGenerator2((chunk.x * 16 + x) / 8, caveY / 8, (chunk.z * 16 + z) / 8)) / 2) > 0.45
|| this.caveGenerator3((chunk.x * 16 + x) / 16, caveY / 16, (chunk.z * 16 + z) / 16) > 0.6 ||
this.caveGenerator4((chunk.x * 16 + x) / 16, caveY / 16, (chunk.z * 16 + z) / 16) > 0.6 ||
this.caveGenerator5((chunk.x * 16 + x) / 16, caveY / 16, (chunk.z * 16 + z) / 16) > 0.5
this.caveGenerator4((chunk.x * 16 + x) / 8, caveY / 8, (chunk.z * 16 + z) / 8) > 0.6
) {
if (caveY <= 3) {
chunk.setBlock(Block.lavaStill.blockId, x, caveY, z);

View file

@ -36,12 +36,12 @@ export class PacketMapChunk implements IPacket {
public writeData() {
return new Promise<Buffer>((resolve, reject) => {
// TODO: Use block and sky nibble array buffers
const fakeLighting = createWriter(Endian.BE, 16384);
/*const fakeLighting = createWriter(Endian.BE, 16384);
for (let i = 0; i < 16384; i++) {
fakeLighting.writeUByte(0xFF);
}
}*/
const data = createWriter(Endian.BE).writeBuffer(this.chunk.getBlockBuffer()).writeBuffer(this.chunk.getMetadataBuffer()).writeBuffer(fakeLighting.toBuffer()).writeBuffer(fakeLighting.toBuffer());//.writeBuffer(this.chunk.blockLight.toBuffer()).writeBuffer(this.chunk.skyLight.toBuffer());
const data = createWriter(Endian.BE).writeBuffer(this.chunk.getBlockBuffer()).writeBuffer(this.chunk.getMetadataBuffer()).writeBuffer(this.chunk.blockLight.toBuffer()).writeBuffer(this.chunk.skyLight.toBuffer());//.writeBuffer(fakeLighting.toBuffer()).writeBuffer(fakeLighting.toBuffer());
deflate(data.toBuffer(), (err, data) => {
if (err) {