implement packet compression, implement player controller, implement join server authentication, add cobblestone, implement chunk provider, implement block position, implement session, implement movement, chunk, chat and block update packets, version 1.1.5

This commit is contained in:
LabyStudio
2022-06-19 14:25:40 +02:00
parent 2e42d482ed
commit 7266a89f5a
67 changed files with 11831 additions and 2761 deletions
+30 -2
View File
@@ -300,6 +300,34 @@ export default class Chunk {
return true;
}
fillChunk(data, size, fullChunk) {
let i = 0;
for (let layer = 0; layer < Chunk.SECTION_AMOUNT; layer++) {
if ((size & 1 << layer) !== 0) {
let section = this.getSection(layer);
for (let k = 0; k < ChunkSection.SIZE * ChunkSection.SIZE * ChunkSection.SIZE; k++) {
let x = k & 15;
let z = (k >> 4) & 15;
let y = (k >> 8) & 15;
let value = (((data[i] & 0xFF) | (data[i + 1] & 0xFF) << 8));
let typeId = value >> 4;
let meta = value & 0xF; // TODO handle meta of block
// TODO support more blocks
if (typeId !== 0 && Block.getById(typeId) === null) {
typeId = 1;
}
section.setBlockAt(x, y, z, typeId);
i += 2;
}
}
}
}
getBlockID(x, y, z) {
return this.getBlockAt(x, y, z);
}
@@ -317,7 +345,7 @@ export default class Chunk {
}
rebuild(renderer) {
for (let y = 0; y < this.sections.length; y++) {
for (let y = 0; y < Chunk.SECTION_AMOUNT; y++) {
this.sections[y].rebuild(renderer);
}
}
@@ -331,7 +359,7 @@ export default class Chunk {
}
setModifiedAllSections() {
for (let y = 0; y < this.sections.length; y++) {
for (let y = 0; y < Chunk.SECTION_AMOUNT; y++) {
this.sections[y].isModified = true;
}
}
@@ -66,7 +66,7 @@ export default class ChunkSection {
let absoluteZ = this.z * ChunkSection.SIZE + z;
let block = Block.getById(typeId);
if (block.isTranslucent() !== isTranslucentRenderPhase) {
if (block === null || block.isTranslucent() !== isTranslucentRenderPhase) {
continue;
}
+17 -75
View File
@@ -1,5 +1,4 @@
import ChunkSection from "./ChunkSection.js";
import WorldGenerator from "./generator/WorldGenerator.js";
import MathHelper from "../../util/MathHelper.js";
import BoundingBox from "../../util/BoundingBox.js";
import EnumSkyBlock from "../../util/EnumSkyBlock.js";
@@ -9,13 +8,12 @@ import Vector3 from "../../util/Vector3.js";
import Vector4 from "../../util/Vector4.js";
import MetadataChunkBlock from "../../util/MetadataChunkBlock.js";
import * as THREE from "../../../../../../libraries/three.module.js";
import Random from "../../util/Random.js";
export default class World {
static TOTAL_HEIGHT = ChunkSection.SIZE * 8 - 1; // ChunkSection.SIZE * 16 - 1;
constructor(minecraft, seed) {
constructor(minecraft) {
this.minecraft = minecraft;
this.entities = [];
@@ -23,14 +21,12 @@ export default class World {
this.group = new THREE.Object3D();
this.group.matrixAutoUpdate = false;
this.chunks = new Map();
this.lightUpdateQueue = [];
this.chunkProvider = null;
this.time = 0;
this.spawn = new Vector3(0, 0, 0);
this.setSeed(seed);
// Update lights async
let scope = this;
setInterval(function () {
@@ -42,14 +38,8 @@ export default class World {
}, 0);
}
setSeed(seed) {
this.seed = seed;
this.generator = new WorldGenerator(this, seed);
this.random = new Random(seed);
}
getSeed() {
return this.seed;
setChunkProvider(chunkProvider) {
this.chunkProvider = chunkProvider;
}
onTick() {
@@ -67,44 +57,7 @@ export default class World {
}
getChunkAt(x, z) {
let index = x + (z << 16);
let chunk = this.chunks.get(index);
if (typeof chunk === 'undefined') {
// Generate new chunk
chunk = this.generator.newChunk(this, x, z);
// Register and mark as loaded
chunk.loaded = true;
this.chunks.set(index, chunk);
// Populate the chunk
if (!chunk.isTerrainPopulated && this.chunkExists(x + 1, z + 1) && this.chunkExists(x, z + 1) && this.chunkExists(x + 1, z)) {
this.populate(x, z);
}
if (this.chunkExists(x - 1, z) && !this.getChunkAt(x - 1, z).isTerrainPopulated && this.chunkExists(x - 1, z + 1) && this.chunkExists(x, z + 1) && this.chunkExists(x - 1, z)) {
this.populate(x - 1, z);
}
if (this.chunkExists(x, z - 1) && !this.getChunkAt(x, z - 1).isTerrainPopulated && this.chunkExists(x + 1, z - 1) && this.chunkExists(x, z - 1) && this.chunkExists(x + 1, z)) {
this.populate(x, z - 1);
}
if (this.chunkExists(x - 1, z - 1) && !this.getChunkAt(x - 1, z - 1).isTerrainPopulated && this.chunkExists(x - 1, z - 1) && this.chunkExists(x, z - 1) && this.chunkExists(x - 1, z)) {
this.populate(x - 1, z - 1);
}
// Register in three.js
this.group.add(chunk.group);
}
return chunk;
}
populate(x, z) {
let chunk = this.getChunkAt(x, z);
if (!chunk.isTerrainPopulated) {
chunk.isTerrainPopulated = true;
// Populate chunk
this.generator.populateChunk(chunk.x, chunk.z);
}
return this.chunkProvider.getChunkAt(x, z);
}
getChunkAtBlock(x, y, z) {
@@ -207,9 +160,7 @@ export default class World {
}
chunkExists(chunkX, chunkZ) {
let index = chunkX + (chunkZ << 16);
let chunk = this.chunks.get(index);
return typeof chunk !== 'undefined';
return this.chunkProvider !== null && this.chunkProvider.chunkExists(chunkX, chunkZ);
}
neighborLightPropagationChanged(sourceType, x, y, z, level) {
@@ -302,7 +253,12 @@ export default class World {
isSolidBlockAt(x, y, z) {
let typeId = this.getBlockAt(x, y, z);
return typeId !== 0 && Block.getById(typeId).isSolid();
if (typeId === 0) {
return false;
}
let block = Block.getById(typeId);
return block !== null && block.isSolid();
}
isTranslucentBlockAt(x, y, z) {
@@ -604,6 +560,7 @@ export default class World {
addEntity(entity) {
this.entities.push(entity);
entity.initRenderer();
this.group.add(entity.renderer.group);
}
@@ -631,25 +588,6 @@ export default class World {
this.spawn = new Vector3(x, y + 8, z);
}
findSpawn() {
if (this.spawn.y <= 0) {
this.spawn.y = 64;
}
while (this.getBlockAboveSeaLevel(this.spawn.x, this.spawn.z) === 0) {
this.spawn.x += this.random.nextInt(8) - this.random.nextInt(8);
this.spawn.z += this.random.nextInt(8) - this.random.nextInt(8);
}
}
getBlockAboveSeaLevel(x, z) {
let y = this.generator.seaLevel;
while (this.getBlockAt(x, y + 1, z) !== 0) {
y++;
}
return this.getBlockAt(x, y, z);
}
loadSpawnChunks() {
let viewDistance = this.minecraft.settings.viewDistance;
for (let x = -viewDistance; x <= viewDistance; x++) {
@@ -660,4 +598,8 @@ export default class World {
this.spawn.y = this.getHeightAt(this.spawn.x, this.spawn.z) + 8;
}
getChunkProvider() {
return this.chunkProvider;
}
}
@@ -0,0 +1,12 @@
import World from "./World.js";
import ChunkProviderClient from "./provider/ChunkProviderClient.js";
export default class WorldClient extends World {
constructor(minecraft) {
super(minecraft);
// Set chunk provider to remote chunk loader
this.setChunkProvider(new ChunkProviderClient(this))
}
}
@@ -49,7 +49,12 @@ export default class Block {
shouldRenderFace(world, x, y, z, face) {
let typeId = world.getBlockAtFace(x, y, z, face);
return typeId === 0 || Block.getById(typeId).isTranslucent();
if (typeId === 0) {
return true;
}
let block = Block.getById(typeId);
return block === null || block.isTranslucent();
}
getColor(world, x, y, z, face) {
@@ -208,7 +213,8 @@ export default class Block {
}
static getById(typeId) {
return Block.blocks.get(typeId);
let block = Block.blocks.get(typeId);
return typeof block === "undefined" ? null : block;
}
}
@@ -13,6 +13,7 @@ import BlockBedrock from "./type/BlockBedrock.js";
import BlockGlass from "./type/BlockGlass.js";
import SoundGlass from "./sound/SoundGlass.js";
import BlockGravel from "./type/BlockGravel.js";
import BlockCobblestone from "./type/BlockCobblestone.js";
export class BlockRegistry {
@@ -30,6 +31,7 @@ export class BlockRegistry {
BlockRegistry.STONE = new BlockStone(1, 0);
BlockRegistry.GRASS = new BlockGrass(2, 1);
BlockRegistry.DIRT = new BlockDirt(3, 2);
BlockRegistry.COBBLE_STONE = new BlockCobblestone(4, 14);
BlockRegistry.WOOD = new BlockWood(5, 10);
BlockRegistry.BEDROCK = new BlockBedrock(7, 11);
BlockRegistry.GRAVEL = new BlockGravel(13, 13);
@@ -0,0 +1,9 @@
import Block from "../Block.js";
export default class BlockCobblestone extends Block {
constructor(id, textureSlotId) {
super(id, textureSlotId);
}
}
@@ -7,6 +7,8 @@ export default class Generator {
this.world = world;
this.seed = seed;
this.random = new Random(seed);
this.seaLevel = 64;
}
generateInChunk(chunkX, chunkZ, primer) {
@@ -35,4 +37,12 @@ export default class Generator {
let {seedX, seedZ} = this.generateSeedOffset();
this.setSeedOffset(chunkX, chunkZ, seedX, seedZ);
}
getSeed() {
return this.seed;
}
getSeaLevel() {
return this.seaLevel;
}
}
@@ -13,8 +13,6 @@ export default class WorldGenerator extends Generator {
constructor(world, seed) {
super(world, seed);
this.seaLevel = 64;
this.caveGenerator = new CaveGenerator(world, seed);
this.terrainGenerator4 = new NoiseGeneratorOctaves(this.random, 16);
@@ -0,0 +1,61 @@
import Chunk from "../Chunk.js";
export default class ChunkProvider {
constructor(world) {
this.world = world;
this.chunks = new Map();
}
chunkExists(x, z) {
let index = x + (z << 16);
let chunk = this.chunks.get(index);
return typeof chunk !== 'undefined';
}
getChunkAt(x, z) {
let index = x + (z << 16);
let chunk = this.chunks.get(index);
if (typeof chunk === 'undefined') {
chunk = this.loadChunk(x, z);
}
return chunk;
}
generateChunk(x, z) {
let chunk = new Chunk(this.world, x, z);
chunk.generateSkylightMap();
chunk.generateBlockLightMap();
return chunk;
}
populateChunk(chunk) {
}
loadChunk(x, z) {
let index = x + (z << 16);
let chunk = this.generateChunk(x, z)
// Register and mark as loaded
chunk.loaded = true;
this.chunks.set(index, chunk);
this.populateChunk(chunk);
// Register in three.js
this.world.group.add(chunk.group);
return chunk;
}
unloadChunk(x, z) {
let index = x + (z << 16);
this.chunks.delete(index);
}
getChunks() {
return this.chunks;
}
}
@@ -0,0 +1,20 @@
import ChunkProvider from "./ChunkProvider.js";
import Chunk from "../Chunk.js";
export default class ChunkProviderClient extends ChunkProvider {
constructor(world) {
super(world);
this.emptyChunk = new Chunk(world, 0, 0);
this.emptyChunk.generateSkylightMap();
this.emptyChunk.generateBlockLightMap();
}
getChunkAt(x, z) {
let index = x + (z << 16);
let chunk = this.chunks.get(index);
return typeof chunk === 'undefined' ? this.emptyChunk : chunk;
}
}
@@ -0,0 +1,67 @@
import ChunkProvider from "./ChunkProvider.js";
import WorldGenerator from "../generator/WorldGenerator.js";
import Random from "../../../util/Random.js";
export default class ChunkProviderGenerate extends ChunkProvider {
constructor(world, seed) {
super(world);
this.generator = new WorldGenerator(world, seed);
}
generateChunk(x, z) {
return this.generator.newChunk(this.world, x, z);
}
populateChunk(chunk) {
let x = chunk.x;
let z = chunk.z;
// Populate the chunk
if (!chunk.isTerrainPopulated && this.chunkExists(x + 1, z + 1) && this.chunkExists(x, z + 1) && this.chunkExists(x + 1, z)) {
this._populateChunkAt(x, z);
}
if (this.chunkExists(x - 1, z) && !this.getChunkAt(x - 1, z).isTerrainPopulated && this.chunkExists(x - 1, z + 1) && this.chunkExists(x, z + 1) && this.chunkExists(x - 1, z)) {
this._populateChunkAt(x - 1, z);
}
if (this.chunkExists(x, z - 1) && !this.getChunkAt(x, z - 1).isTerrainPopulated && this.chunkExists(x + 1, z - 1) && this.chunkExists(x, z - 1) && this.chunkExists(x + 1, z)) {
this._populateChunkAt(x, z - 1);
}
if (this.chunkExists(x - 1, z - 1) && !this.getChunkAt(x - 1, z - 1).isTerrainPopulated && this.chunkExists(x - 1, z - 1) && this.chunkExists(x, z - 1) && this.chunkExists(x - 1, z)) {
this._populateChunkAt(x - 1, z - 1);
}
}
_populateChunkAt(x, z) {
let chunk = this.getChunkAt(x, z);
if (!chunk.isTerrainPopulated) {
chunk.isTerrainPopulated = true;
// Populate chunk
this.generator.populateChunk(chunk.x, chunk.z);
}
}
findSpawn() {
let spawn = this.world.spawn;
if (spawn.y <= 0) {
spawn.y = 64;
}
let random = new Random(this.generator.getSeed());
while (this.getBlockAboveSeaLevel(spawn.x, spawn.z) === 0) {
spawn.x += random.nextInt(8) - random.nextInt(8);
spawn.z += random.nextInt(8) - random.nextInt(8);
}
}
getBlockAboveSeaLevel(x, z) {
let y = this.generator.getSeaLevel();
while (this.world.getBlockAt(x, y + 1, z) !== 0) {
y++;
}
return this.world.getBlockAt(x, y, z);
}
}