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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user