implement dimension switching
This commit is contained in:
parent
9feafc46c7
commit
74374cb0d6
|
@ -57,8 +57,6 @@ export class Chunk {
|
|||
public getTopBlockY(x:number, z:number) {
|
||||
let castY = this.MAX_HEIGHT;
|
||||
while (castY-- > 0) {
|
||||
const blockId = this.getBlockId(x >>> 0, castY, z >>> 0);
|
||||
console.log(blockId === 0 ? "Air" : Block.blocks[blockId].blockName);
|
||||
if (this.getBlockId(x >>> 0, castY, z >>> 0) !== 0) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@ import { PacketPlayerDigging } from "./packets/PlayerDigging";
|
|||
import { Player } from "./entities/Player";
|
||||
import { Socket } from "net";
|
||||
import { Vec3 } from "./Vec3";
|
||||
import { PacketRespawn } from "./packets/Respawn";
|
||||
import { PacketSpawnPosition } from "./packets/SpawnPosition";
|
||||
|
||||
export class MPClient {
|
||||
private readonly mcServer:MinecraftServer;
|
||||
private readonly socket:Socket;
|
||||
public readonly entity:Player;
|
||||
public entity:Player;
|
||||
|
||||
private diggingAt:Vec3;
|
||||
|
||||
|
@ -77,15 +79,25 @@ export class MPClient {
|
|||
if (message[0].startsWith("/")) {
|
||||
packet.message = "";
|
||||
if (message[0] === "/tp") {
|
||||
this.send(new PacketPlayerPositionLook(parseFloat(message[1]), parseFloat(message[2]), parseFloat(message[2]) + 0.62, parseFloat(message[3]), 0, 0, false).writeData());
|
||||
const x = this.entity.x = parseFloat(message[1]);
|
||||
const y = this.entity.y = parseFloat(message[2]);
|
||||
const z = this.entity.z = parseFloat(message[3]);
|
||||
this.send(new PacketPlayerPositionLook(x, y, y + 0.62, z, 0, 0, false).writeData());
|
||||
Console.printInfo(packet.message = `Teleported ${this.entity.username} to ${message[1]} ${message[2]} ${message[3]}`);
|
||||
} else if (message[0] === "/csay") {
|
||||
this.mcServer.sendChatMessage(`[CONSOLE] ${message.slice(1, message.length).join(" ")}`);
|
||||
} else if (message[0] === "/top") {
|
||||
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 PacketPlayerPosition(this.entity.x, topBlock + 3, topBlock + 3.62, this.entity.z, false).writeData());
|
||||
} else if (message[0] === "/tpx") {
|
||||
const dimension = parseInt(message[1]);
|
||||
if (this.mcServer.worlds.has(dimension)) {
|
||||
packet.message = "\u00a76Switching dimensions...";
|
||||
this.switchDimension(dimension);
|
||||
} else {
|
||||
packet.message = `\u00a7cNo dimension by id "${dimension} exists!"`;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.message !== "") {
|
||||
|
@ -157,6 +169,26 @@ export class MPClient {
|
|||
}
|
||||
}
|
||||
|
||||
private switchDimension(dimension:number) {
|
||||
const world = this.mcServer.worlds.get(dimension);
|
||||
if (world == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.entity.world.removeEntity(this.entity);
|
||||
this.entity.world = world;
|
||||
world.addEntity(this.entity);
|
||||
|
||||
this.send(new PacketRespawn(dimension).writeData());
|
||||
//this.send(new PacketSpawnPosition(8, 64, 8).writeData());
|
||||
this.entity.x = 8;
|
||||
this.entity.y = 70;
|
||||
this.entity.z = 8;
|
||||
this.send(new PacketPlayerPositionLook(8, 70, 70.62, 8, 0, 0, false).writeData());
|
||||
|
||||
this.entity.forceUpdatePlayerChunks();
|
||||
}
|
||||
|
||||
private handleDisconnectKick() {
|
||||
this.socket.end();
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ export class MinecraftServer {
|
|||
private readonly serverClock:NodeJS.Timeout;
|
||||
private tickCounter:number = 0;
|
||||
private clients:FunkyArray<string, MPClient>;
|
||||
private worlds:FunkyArray<number, World>;
|
||||
public worlds:FunkyArray<number, World>;
|
||||
public saveManager:WorldSaveManager;
|
||||
private overworld:World;
|
||||
private nether:World;
|
||||
|
|
|
@ -61,6 +61,10 @@ export class World {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Clear player chunk list (they may be switching dimensions)
|
||||
entity.loadedChunks = new Array<number>();
|
||||
entity.justUnloaded = new Array<number>();
|
||||
|
||||
this.players.remove(entity.entityId);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ export class Entity implements IEntity {
|
|||
private lastCrouchState:boolean;
|
||||
private lastFireState:boolean;
|
||||
|
||||
private queuedChunkUpdate:boolean;
|
||||
|
||||
public constructor(world:World) {
|
||||
this.entityId = Entity.nextEntityId++;
|
||||
|
||||
|
@ -35,7 +37,7 @@ export class Entity implements IEntity {
|
|||
|
||||
this.world = world;
|
||||
this.x = this.y = this.z = this.lastX = this.lastY = this.lastZ = 0;
|
||||
this.crouching = this.lastCrouchState = this.lastFireState = false;
|
||||
this.crouching = this.lastCrouchState = this.lastFireState = this.queuedChunkUpdate = false;
|
||||
|
||||
this.chunk = world.getChunk(this.x >> 4, this.z >> 4);
|
||||
|
||||
|
@ -92,8 +94,13 @@ export class Entity implements IEntity {
|
|||
updateEntityChunk() {
|
||||
const bitX = this.x >> 4;
|
||||
const bitZ = this.z >> 4;
|
||||
if (bitX != this.lastX >> 4 || bitZ != this.lastZ >> 4) {
|
||||
if (bitX != this.lastX >> 4 || bitZ != this.lastZ >> 4 || this.queuedChunkUpdate) {
|
||||
if (this.world.chunkExists(bitX, bitZ)) {
|
||||
this.chunk = this.world.getChunk(bitX, bitZ);
|
||||
this.queuedChunkUpdate = false;
|
||||
} else {
|
||||
this.queuedChunkUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,6 @@ export class EntityLiving extends Entity {
|
|||
|
||||
// Drowning
|
||||
if (this.isInWater()) {
|
||||
console.log("in water!");
|
||||
if (this.timeInWater == Number.MIN_SAFE_INTEGER) {
|
||||
this.timeInWater = 320;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import { EntityLiving } from "./EntityLiving";
|
|||
import { PacketPreChunk } from "../packets/PreChunk";
|
||||
import { PacketUpdateHealth } from "../packets/UpdateHealth";
|
||||
|
||||
const CHUNK_LOAD_RANGE = 5;
|
||||
|
||||
export class Player extends EntityLiving {
|
||||
public username:string;
|
||||
private server:MinecraftServer;
|
||||
|
@ -32,6 +34,10 @@ export class Player extends EntityLiving {
|
|||
this.lastHealth = this.health;
|
||||
}
|
||||
|
||||
public forceUpdatePlayerChunks() {
|
||||
this.firstUpdate = true;
|
||||
}
|
||||
|
||||
private async updatePlayerChunks() {
|
||||
const bitX = this.x >> 4;
|
||||
const bitZ = this.z >> 4;
|
||||
|
@ -47,8 +53,8 @@ export class Player extends EntityLiving {
|
|||
|
||||
// Load or keep any chunks we need
|
||||
const currentLoads = [];
|
||||
for (let x = bitX - 10; x < bitX + 10; x++) {
|
||||
for (let z = bitZ - 10; z < bitZ + 10; z++) {
|
||||
for (let x = bitX - CHUNK_LOAD_RANGE; x < bitX + CHUNK_LOAD_RANGE; x++) {
|
||||
for (let z = bitZ - CHUNK_LOAD_RANGE; z < bitZ + CHUNK_LOAD_RANGE; z++) {
|
||||
const coordPair = Chunk.CreateCoordPair(x, z);
|
||||
if (!this.loadedChunks.includes(coordPair)) {
|
||||
const chunk = await this.world.getChunkSafe(x, z);
|
||||
|
|
|
@ -4,19 +4,23 @@ import { Packet } from "../enums/Packet";
|
|||
|
||||
export class PacketRespawn implements IPacket {
|
||||
public packetId = Packet.Respawn;
|
||||
public health:number;
|
||||
public dimension:number;
|
||||
|
||||
public constructor(health:number) {
|
||||
this.health = health;
|
||||
public constructor(dimension?:number) {
|
||||
if (typeof(dimension) == "number") {
|
||||
this.dimension = dimension;
|
||||
} else {
|
||||
this.dimension = Number.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
public readData(reader:IReader) {
|
||||
this.health = reader.readShort();
|
||||
this.dimension = reader.readByte();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public writeData() {
|
||||
return createWriter(Endian.BE, 3).writeUByte(this.packetId).writeShort(this.health).toBuffer();
|
||||
return createWriter(Endian.BE, 2).writeUByte(this.packetId).writeByte(this.dimension).toBuffer();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue