lighting sort of works
This commit is contained in:
parent
5396b83f3f
commit
3b208eb8db
10 changed files with 80 additions and 52 deletions
|
@ -1,8 +1,7 @@
|
|||
{
|
||||
"port": 25565,
|
||||
"onlineMode": false,
|
||||
"maxPlayers": 20,
|
||||
"seed": "really janky",
|
||||
"saveCompression": "DEFLATE",
|
||||
"saveCompression": "NONE",
|
||||
"worldName": "world"
|
||||
}
|
|
@ -2,7 +2,6 @@ import { SaveCompressionType } from "./server/enums/SaveCompressionType";
|
|||
|
||||
export interface Config {
|
||||
port: number,
|
||||
onlineMode: boolean,
|
||||
maxPlayers: number,
|
||||
seed: number|string,
|
||||
worldName: string,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 !== "") {
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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");
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue