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, "port": 25565,
"onlineMode": false,
"maxPlayers": 20, "maxPlayers": 20,
"seed": "really janky", "seed": "really janky",
"saveCompression": "DEFLATE", "saveCompression": "NONE",
"worldName": "world" "worldName": "world"
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,10 +2,12 @@ export class Block {
public readonly blockId:number; public readonly blockId:number;
public static readonly blocks:Array<Block> = new Array<Block>(); public static readonly blocks:Array<Block> = new Array<Block>();
public static readonly lightPassage:Array<number> = new Array<number>(); public static readonly lightPassage:Array<number> = new Array<number>();
public static readonly blockNames:Array<string> = new Array<string>();
public constructor(blockId:number) { public constructor(blockId:number) {
Block.blocks[blockId] = this; Block.blocks[blockId] = this;
Block.lightPassage[blockId] = 0; Block.lightPassage[blockId] = 0;
Block.blockNames[blockId] = "";
this.blockId = blockId; this.blockId = blockId;
} }
@ -17,34 +19,47 @@ export class Block {
Block.lightPassage[this.blockId] = value; 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) { public setLightPassage(value:number) {
this.lightPassage = value; this.lightPassage = value;
return this; return this;
} }
public setBlockName(value:string) {
this.blockName = value;
return this;
}
// Define statics here // Define statics here
static readonly stone = new Block(1); static readonly stone = new Block(1).setBlockName("Stone");
static readonly grass = new Block(2); static readonly grass = new Block(2).setBlockName("Grass");
static readonly dirt = new Block(3); 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 sand = new Block(12).setBlockName("Sand");
static readonly gravel = new Block(13); static readonly gravel = new Block(13).setBlockName("Gravel");
static readonly wood = new Block(17); static readonly wood = new Block(17).setBlockName("Wood");
static readonly leaves = new Block(18).setLightPassage(1); 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 flowerDandelion = new Block(37).setLightPassage(255).setBlockName("Dandelion");
static readonly flowerRose = new Block(38); 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 caveGenerator3:Noise3D;
private caveGenerator4:Noise3D; private caveGenerator4:Noise3D;
private caveGenerator5:Noise3D; private caveGenerator5:Noise3D;
private caveGenerator6:Noise3D;
private underwaterGravelGenerator:Noise2D; private underwaterGravelGenerator:Noise2D;
private underwaterSandGenerator:Noise2D; private underwaterSandGenerator:Noise2D;
@ -49,13 +50,12 @@ export class HillyGenerator implements IGenerator {
this.caveGenerator3 = this.createGenerator3D(); this.caveGenerator3 = this.createGenerator3D();
this.caveGenerator4 = this.createGenerator3D(); this.caveGenerator4 = this.createGenerator3D();
this.caveGenerator5 = this.createGenerator3D(); this.caveGenerator5 = this.createGenerator3D();
this.caveGenerator6 = this.createGenerator3D();
this.underwaterGravelGenerator = this.createGenerator2D(); this.underwaterGravelGenerator = this.createGenerator2D();
this.underwaterSandGenerator = this.createGenerator2D(); this.underwaterSandGenerator = this.createGenerator2D();
this.underwaterClayGenerator = this.createGenerator2D(); this.underwaterClayGenerator = this.createGenerator2D();
this.flowerGenerator = this.createGenerator2D(); this.flowerGenerator = this.createGenerator2D();
} }
private 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.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.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.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.caveGenerator4((chunk.x * 16 + x) / 8, caveY / 8, (chunk.z * 16 + z) / 8) > 0.6
this.caveGenerator5((chunk.x * 16 + x) / 16, caveY / 16, (chunk.z * 16 + z) / 16) > 0.5
) { ) {
if (caveY <= 3) { if (caveY <= 3) {
chunk.setBlock(Block.lavaStill.blockId, x, caveY, z); chunk.setBlock(Block.lavaStill.blockId, x, caveY, z);

View file

@ -36,12 +36,12 @@ export class PacketMapChunk implements IPacket {
public writeData() { public writeData() {
return new Promise<Buffer>((resolve, reject) => { return new Promise<Buffer>((resolve, reject) => {
// TODO: Use block and sky nibble array buffers // 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++) { for (let i = 0; i < 16384; i++) {
fakeLighting.writeUByte(0xFF); 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) => { deflate(data.toBuffer(), (err, data) => {
if (err) { if (err) {