players!!!!
This commit is contained in:
parent
36d294a810
commit
f93bb2605d
17 changed files with 487 additions and 18 deletions
|
@ -7,17 +7,45 @@ import { PacketPlayerLook } from "./packets/PlayerLook";
|
||||||
import { PacketPlayerPositionLook } from "./packets/PlayerPositionLook";
|
import { PacketPlayerPositionLook } from "./packets/PlayerPositionLook";
|
||||||
import { Player } from "./entities/Player";
|
import { Player } from "./entities/Player";
|
||||||
import { PacketChat } from "./packets/Chat";
|
import { PacketChat } from "./packets/Chat";
|
||||||
|
import { MinecraftServer } from "./MinecraftServer";
|
||||||
|
import { Vec3 } from "./Vec3";
|
||||||
|
import { Console } from "../console";
|
||||||
|
|
||||||
export class MPClient {
|
export class MPClient {
|
||||||
|
private readonly mcServer:MinecraftServer;
|
||||||
private readonly socket:Socket;
|
private readonly socket:Socket;
|
||||||
public readonly entity:Player;
|
public readonly entity:Player;
|
||||||
|
|
||||||
public constructor(socket:Socket, entity:Player) {
|
public constructor(mcServer:MinecraftServer, socket:Socket, entity:Player) {
|
||||||
|
this.mcServer = mcServer;
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePacket(reader:Reader) {
|
private mapCoordsToFace(pos:Vec3, face:number) {
|
||||||
|
switch (face) {
|
||||||
|
case 0:
|
||||||
|
pos.y--;
|
||||||
|
return pos;
|
||||||
|
case 1:
|
||||||
|
pos.y++;
|
||||||
|
return pos;
|
||||||
|
case 2:
|
||||||
|
pos.z--;
|
||||||
|
return pos;
|
||||||
|
case 3:
|
||||||
|
pos.z++;
|
||||||
|
return pos;
|
||||||
|
case 4:
|
||||||
|
pos.x--;
|
||||||
|
return pos;
|
||||||
|
case 5:
|
||||||
|
pos.x++;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public handlePacket(reader:Reader) {
|
||||||
const packetId = reader.readUByte();
|
const packetId = reader.readUByte();
|
||||||
|
|
||||||
switch (packetId) {
|
switch (packetId) {
|
||||||
|
@ -26,32 +54,51 @@ export class MPClient {
|
||||||
case Packets.PlayerPosition: this.handlePacketPlayerPosition(new PacketPlayerPosition().readData(reader)); break;
|
case Packets.PlayerPosition: this.handlePacketPlayerPosition(new PacketPlayerPosition().readData(reader)); break;
|
||||||
case Packets.PlayerLook: this.handlePacketPlayerLook(new PacketPlayerLook().readData(reader)); break;
|
case Packets.PlayerLook: this.handlePacketPlayerLook(new PacketPlayerLook().readData(reader)); break;
|
||||||
case Packets.PlayerPositionLook: this.handlePacketPlayerPositionLook(new PacketPlayerPositionLook().readData(reader)); break;
|
case Packets.PlayerPositionLook: this.handlePacketPlayerPositionLook(new PacketPlayerPositionLook().readData(reader)); break;
|
||||||
|
case Packets.PlayerDigging: this.handlePacketPlayerDigging(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChat(packet:PacketChat) {
|
private handleChat(packet:PacketChat) {
|
||||||
const message = packet.message.split(" ");
|
const message = packet.message.split(" ");
|
||||||
|
if (message[0].startsWith("/")) {
|
||||||
|
packet.message = "";
|
||||||
if (message[0] === "/tp") {
|
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());
|
this.send(new PacketPlayerPositionLook(parseFloat(message[1]), parseFloat(message[2]), parseFloat(message[2]) + 0.62, parseFloat(message[3]), 0, 0, false).writeData());
|
||||||
}
|
Console.printInfo(packet.message = `Teleported ${this.entity.username} to ${message[1]} ${message[2]} ${message[3]}`);
|
||||||
|
} else if (message[0] === "/csay") {
|
||||||
|
const consoleMessage = `[CONSOLE] ${message.slice(1, message.length).join(" ")}`;
|
||||||
|
Console.printChat(consoleMessage);
|
||||||
|
this.mcServer.sendToAllClients(new PacketChat(consoleMessage).writeData());
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePacketPlayer(packet:PacketPlayer) {
|
if (packet.message !== "") {
|
||||||
|
this.send(packet.writeData());
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet.message = `<${this.entity.username}> ${packet.message}`;
|
||||||
|
Console.printChat(packet.message);
|
||||||
|
this.mcServer.sendToAllClients(packet.writeData());
|
||||||
|
}
|
||||||
|
|
||||||
|
private handlePacketPlayer(packet:PacketPlayer) {
|
||||||
this.entity.onGround = packet.onGround;
|
this.entity.onGround = packet.onGround;
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePacketPlayerPosition(packet:PacketPlayerPosition) {
|
private handlePacketPlayerPosition(packet:PacketPlayerPosition) {
|
||||||
this.entity.x = packet.x;
|
this.entity.x = packet.x;
|
||||||
this.entity.y = packet.y;
|
this.entity.y = packet.y;
|
||||||
this.entity.z = packet.z;
|
this.entity.z = packet.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePacketPlayerLook(packet:PacketPlayerLook) {
|
private handlePacketPlayerLook(packet:PacketPlayerLook) {
|
||||||
this.entity.yaw = packet.yaw;
|
this.entity.yaw = packet.yaw;
|
||||||
this.entity.pitch = packet.pitch;
|
this.entity.pitch = packet.pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePacketPlayerPositionLook(packet:PacketPlayerPositionLook) {
|
private handlePacketPlayerPositionLook(packet:PacketPlayerPositionLook) {
|
||||||
this.entity.x = packet.x;
|
this.entity.x = packet.x;
|
||||||
this.entity.y = packet.y;
|
this.entity.y = packet.y;
|
||||||
this.entity.z = packet.z;
|
this.entity.z = packet.z;
|
||||||
|
@ -59,7 +106,11 @@ export class MPClient {
|
||||||
this.entity.pitch = packet.pitch;
|
this.entity.pitch = packet.pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
send(buffer:Buffer|Writer) {
|
private handlePacketPlayerDigging() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public send(buffer:Buffer|Writer) {
|
||||||
if (buffer instanceof Writer) {
|
if (buffer instanceof Writer) {
|
||||||
this.socket.write(buffer.toBuffer());
|
this.socket.write(buffer.toBuffer());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Config } from "../config";
|
import { Config } from "../config";
|
||||||
import { Console } from "../console";
|
import { Console } from "../console";
|
||||||
import { Server, Socket } from "net";
|
import { Server, Socket, SocketAddress } from "net";
|
||||||
import { FunkyArray } from "../funkyArray";
|
import { FunkyArray } from "../funkyArray";
|
||||||
import { World } from "./World";
|
import { World } from "./World";
|
||||||
import { Reader } from "../bufferStuff";
|
import { Reader } from "../bufferStuff";
|
||||||
|
@ -14,6 +14,7 @@ import { Player } from "./entities/Player";
|
||||||
import { PacketSpawnPosition } from "./packets/SpawnPosition";
|
import { PacketSpawnPosition } from "./packets/SpawnPosition";
|
||||||
import { PacketPlayerPositionLook } from "./packets/PlayerPositionLook";
|
import { PacketPlayerPositionLook } from "./packets/PlayerPositionLook";
|
||||||
import { PacketChat } from "./packets/Chat";
|
import { PacketChat } from "./packets/Chat";
|
||||||
|
import { PacketNamedEntitySpawn } from "./packets/NamedEntitySpawn";
|
||||||
|
|
||||||
export class MinecraftServer {
|
export class MinecraftServer {
|
||||||
private static readonly PROTOCOL_VERSION = 14;
|
private static readonly PROTOCOL_VERSION = 14;
|
||||||
|
@ -112,7 +113,7 @@ export class MinecraftServer {
|
||||||
const clientEntity = new Player(this, world, loginPacket.username);
|
const clientEntity = new Player(this, world, loginPacket.username);
|
||||||
world.addEntity(clientEntity);
|
world.addEntity(clientEntity);
|
||||||
|
|
||||||
const client = new MPClient(socket, clientEntity);
|
const client = new MPClient(this, socket, clientEntity);
|
||||||
setMPClient(client);
|
setMPClient(client);
|
||||||
clientEntity.mpClient = client;
|
clientEntity.mpClient = client;
|
||||||
this.clients.set(loginPacket.username, client);
|
this.clients.set(loginPacket.username, client);
|
||||||
|
@ -122,6 +123,14 @@ export class MinecraftServer {
|
||||||
socket.write(new PacketLoginRequest(clientEntity.entityId, "", 0, 0).writeData());
|
socket.write(new PacketLoginRequest(clientEntity.entityId, "", 0, 0).writeData());
|
||||||
socket.write(new PacketSpawnPosition(8, 64, 8).writeData());
|
socket.write(new PacketSpawnPosition(8, 64, 8).writeData());
|
||||||
|
|
||||||
|
const thisPlayerSpawn = new PacketNamedEntitySpawn(clientEntity.entityId, clientEntity.username, clientEntity.absX, clientEntity.absY, clientEntity.absZ, clientEntity.absYaw, clientEntity.absPitch, 0).writeData();
|
||||||
|
world.players.forEach(player => {
|
||||||
|
if (player.entityId !== clientEntity.entityId && clientEntity.distanceTo(player) < World.ENTITY_MAX_SEND_DISTANCE) {
|
||||||
|
socket.write(new PacketNamedEntitySpawn(player.entityId, player.username, player.absX, player.absY, player.absZ, player.absYaw, player.absPitch, 0).writeData());
|
||||||
|
player.mpClient?.send(thisPlayerSpawn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
socket.write(new PacketPlayerPositionLook(8, 70, 70.62, 8, 0, 0, false).writeData());
|
socket.write(new PacketPlayerPositionLook(8, 70, 70.62, 8, 0, 0, false).writeData());
|
||||||
} else {
|
} else {
|
||||||
socket.write(new PacketDisconnectKick("Failed to find world to put player in.").writeData());
|
socket.write(new PacketDisconnectKick("Failed to find world to put player in.").writeData());
|
||||||
|
|
19
server/Vec3.ts
Normal file
19
server/Vec3.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
export class Vec3 {
|
||||||
|
public x:number;
|
||||||
|
public y:number;
|
||||||
|
public z:number;
|
||||||
|
|
||||||
|
public constructor(x?:number, y?:number, z?:number) {
|
||||||
|
if (typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number") {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
} else if (typeof(x) === "number" && typeof(y) !== "number" && typeof(z) !== "number") {
|
||||||
|
this.x = x;
|
||||||
|
this.y = x;
|
||||||
|
this.z = x;
|
||||||
|
} else {
|
||||||
|
this.x = this.y = this.z = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,19 +7,26 @@ import { HillyGenerator } from "./generators/Hilly";
|
||||||
import { IGenerator } from "./generators/IGenerator";
|
import { IGenerator } from "./generators/IGenerator";
|
||||||
|
|
||||||
export class World {
|
export class World {
|
||||||
|
public static ENTITY_MAX_SEND_DISTANCE = 50;
|
||||||
|
|
||||||
public chunks:FunkyArray<number, Chunk>;
|
public chunks:FunkyArray<number, Chunk>;
|
||||||
public entites:FunkyArray<number, IEntity>;
|
public entites:FunkyArray<number, IEntity>;
|
||||||
|
public players:FunkyArray<number, Player>;
|
||||||
|
|
||||||
public generator:IGenerator;
|
public generator:IGenerator;
|
||||||
|
|
||||||
public constructor(seed:number) {
|
public constructor(seed:number) {
|
||||||
this.chunks = new FunkyArray<number, Chunk>();
|
this.chunks = new FunkyArray<number, Chunk>();
|
||||||
this.entites = new FunkyArray<number, IEntity>();
|
this.entites = new FunkyArray<number, IEntity>();
|
||||||
|
this.players = new FunkyArray<number, Player>();
|
||||||
this.generator = new HillyGenerator(seed);
|
this.generator = new HillyGenerator(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addEntity(entity:IEntity) {
|
public addEntity(entity:IEntity) {
|
||||||
this.entites.set(entity.entityId, entity);
|
this.entites.set(entity.entityId, entity);
|
||||||
|
if (entity instanceof Player) {
|
||||||
|
this.players.set(entity.entityId, entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: getChunkByCoordPair failed in here during removeEntity, figure out why.
|
// TODO: getChunkByCoordPair failed in here during removeEntity, figure out why.
|
||||||
|
@ -33,6 +40,7 @@ export class World {
|
||||||
this.unloadChunk(coordPair);
|
this.unloadChunk(coordPair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.players.remove(entity.entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.entites.remove(entity.entityId);
|
this.entites.remove(entity.entityId);
|
||||||
|
@ -53,6 +61,14 @@ export class World {
|
||||||
return existingChunk;
|
return existingChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sendToNearbyClients(sentFrom:IEntity, buffer:Buffer) {
|
||||||
|
this.players.forEach(player => {
|
||||||
|
if (sentFrom.entityId !== player.entityId && Math.abs(sentFrom.distanceTo(player)) < World.ENTITY_MAX_SEND_DISTANCE) {
|
||||||
|
player.mpClient?.send(buffer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public getChunkByCoordPair(coordPair:number) {
|
public getChunkByCoordPair(coordPair:number) {
|
||||||
const existingChunk = this.chunks.get(coordPair);
|
const existingChunk = this.chunks.get(coordPair);
|
||||||
if (!(existingChunk instanceof Chunk)) {
|
if (!(existingChunk instanceof Chunk)) {
|
||||||
|
@ -69,6 +85,8 @@ export class World {
|
||||||
|
|
||||||
public tick() {
|
public tick() {
|
||||||
this.entites.forEach(entity => {
|
this.entites.forEach(entity => {
|
||||||
|
entity.onTick();
|
||||||
|
|
||||||
if (entity instanceof Player) {
|
if (entity instanceof Player) {
|
||||||
if (entity.justUnloaded.length > 0) {
|
if (entity.justUnloaded.length > 0) {
|
||||||
for (const coordPair of entity.justUnloaded) {
|
for (const coordPair of entity.justUnloaded) {
|
||||||
|
@ -82,8 +100,6 @@ export class World {
|
||||||
entity.justUnloaded = new Array<number>();
|
entity.justUnloaded = new Array<number>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.onTick();
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,6 +21,14 @@ export class Entity implements IEntity {
|
||||||
this.x = this.y = this.z = this.lastX = this.lastY = this.lastZ = 0;
|
this.x = this.y = this.z = this.lastX = this.lastY = this.lastZ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
distanceTo(entity:IEntity) {
|
||||||
|
const dX = entity.x - this.x,
|
||||||
|
dY = entity.y - this.y,
|
||||||
|
dZ = entity.z - this.z;
|
||||||
|
|
||||||
|
return Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2) + Math.pow(dZ, 2));
|
||||||
|
}
|
||||||
|
|
||||||
onTick() {
|
onTick() {
|
||||||
this.lastX = this.x;
|
this.lastX = this.x;
|
||||||
this.lastY = this.y;
|
this.lastY = this.y;
|
||||||
|
|
|
@ -1,20 +1,79 @@
|
||||||
import { World } from "../World";
|
import { World } from "../World";
|
||||||
|
import { PacketEntityLook } from "../packets/EntityLook";
|
||||||
|
import { PacketEntityLookRelativeMove } from "../packets/EntityLookRelativeMove";
|
||||||
|
import { PacketEntityRelativeMove } from "../packets/EntityRelativeMove";
|
||||||
|
import { PacketEntityTeleport } from "../packets/EntityTeleport";
|
||||||
import { Entity } from "./Entity";
|
import { Entity } from "./Entity";
|
||||||
|
|
||||||
export class EntityLiving extends Entity {
|
export class EntityLiving extends Entity {
|
||||||
public yaw:number;
|
public yaw:number;
|
||||||
|
public lastYaw:number;
|
||||||
public pitch:number;
|
public pitch:number;
|
||||||
|
public lastPitch:number;
|
||||||
public onGround:boolean;
|
public onGround:boolean;
|
||||||
|
|
||||||
|
public absX:number;
|
||||||
|
public absY:number;
|
||||||
|
public absZ:number;
|
||||||
|
public absYaw:number;
|
||||||
|
public absPitch:number;
|
||||||
|
public lastAbsX:number;
|
||||||
|
public lastAbsY:number;
|
||||||
|
public lastAbsZ:number;
|
||||||
|
public lastAbsYaw:number;
|
||||||
|
public lastAbsPitch:number;
|
||||||
|
|
||||||
public constructor(world:World) {
|
public constructor(world:World) {
|
||||||
super(world);
|
super(world);
|
||||||
|
|
||||||
this.yaw = 0;
|
this.yaw = this.lastYaw = this.pitch = this.lastPitch = this.absX = this.absY = this.absZ = this.absYaw = this.absPitch = this.lastAbsX = this.lastAbsY = this.lastAbsZ = this.lastAbsYaw = this.lastAbsPitch = 0;
|
||||||
this.pitch = 0;
|
|
||||||
this.onGround = false;
|
this.onGround = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private constrainRot(rot:number) {
|
||||||
|
return Math.min(Math.max(rot, -128), 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sendPositionUpdate() {
|
||||||
|
this.absX = Math.floor(this.x * 32);
|
||||||
|
this.absY = Math.floor(this.y * 32);
|
||||||
|
this.absZ = Math.floor(this.z * 32);
|
||||||
|
// This is suuuuuper jank
|
||||||
|
this.absYaw = this.constrainRot(Math.floor(((this.yaw - 180 >= 0 ? this.yaw - 180 : (this.yaw - 180) % 360 + 360) % 360 / 360) * 256) - 128);
|
||||||
|
this.absPitch = this.constrainRot(Math.floor((this.pitch % 360 * 256) / 360));
|
||||||
|
const diffX = this.absX - this.lastAbsX;
|
||||||
|
const diffY = this.absY - this.lastAbsY;
|
||||||
|
const diffZ = this.absZ - this.lastAbsZ;
|
||||||
|
const diffYaw = this.absYaw - this.lastAbsYaw;
|
||||||
|
const diffPitch = this.absPitch - this.lastAbsPitch;
|
||||||
|
|
||||||
|
const doRelativeMove = Math.abs(diffX) >= 5 || Math.abs(diffY) >= 5 || Math.abs(diffZ) >= 5;
|
||||||
|
const doLook = Math.abs(diffYaw) >= 5 || Math.abs(diffPitch) >= 5;
|
||||||
|
if (Math.abs(diffX) > 128 || Math.abs(diffY) > 128 || Math.abs(diffZ) > 128) {
|
||||||
|
this.world.sendToNearbyClients(this, new PacketEntityTeleport(this.entityId, this.absX, this.absY, this.absZ, this.absYaw, this.absPitch).writeData());
|
||||||
|
} else if (doRelativeMove && doLook) {
|
||||||
|
this.world.sendToNearbyClients(this, new PacketEntityLookRelativeMove(this.entityId, diffX, diffY, diffZ, this.absYaw, this.absPitch).writeData());
|
||||||
|
} else if (doRelativeMove) {
|
||||||
|
this.world.sendToNearbyClients(this, new PacketEntityRelativeMove(this.entityId, diffX, diffY, diffZ).writeData());
|
||||||
|
} else if (doLook) {
|
||||||
|
this.world.sendToNearbyClients(this, new PacketEntityLook(this.entityId, this.absYaw, this.absPitch).writeData());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doRelativeMove) {
|
||||||
|
this.lastAbsX = this.absX;
|
||||||
|
this.lastAbsY = this.absY;
|
||||||
|
this.lastAbsZ = this.absZ;
|
||||||
|
}
|
||||||
|
if (doLook) {
|
||||||
|
this.lastAbsYaw = this.absYaw;
|
||||||
|
this.lastAbsPitch = this.absPitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onTick() {
|
onTick() {
|
||||||
super.onTick();
|
super.onTick();
|
||||||
|
this.sendPositionUpdate();
|
||||||
|
this.lastYaw = this.yaw;
|
||||||
|
this.lastPitch = this.lastPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,5 +6,6 @@ export interface IEntity {
|
||||||
lastX:number,
|
lastX:number,
|
||||||
lastY:number,
|
lastY:number,
|
||||||
lastZ:number,
|
lastZ:number,
|
||||||
|
distanceTo:(entity:IEntity) => number,
|
||||||
onTick:() => void
|
onTick:() => void
|
||||||
}
|
}
|
|
@ -33,6 +33,7 @@ export class Player extends EntityLiving {
|
||||||
if (bitX != this.lastX >> 4 || bitZ != this.lastZ >> 4 || this.firstUpdate) {
|
if (bitX != this.lastX >> 4 || bitZ != this.lastZ >> 4 || this.firstUpdate) {
|
||||||
if (this.firstUpdate) {
|
if (this.firstUpdate) {
|
||||||
this.firstUpdate = false;
|
this.firstUpdate = false;
|
||||||
|
// TODO: Make this based on the player's coords
|
||||||
this.mpClient?.send(new PacketPreChunk(0, 0, true).writeData());
|
this.mpClient?.send(new PacketPreChunk(0, 0, true).writeData());
|
||||||
const chunk = this.world.getChunk(0, 0);
|
const chunk = this.world.getChunk(0, 0);
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
|
@ -13,9 +13,22 @@ export enum Packets {
|
||||||
PlayerPosition = 0x0B,
|
PlayerPosition = 0x0B,
|
||||||
PlayerLook = 0x0C,
|
PlayerLook = 0x0C,
|
||||||
PlayerPositionLook = 0x0D,
|
PlayerPositionLook = 0x0D,
|
||||||
|
PlayerDigging = 0x0E,
|
||||||
|
PlayerBlockPlacement = 0x0F,
|
||||||
|
HoldingChange = 0x10,
|
||||||
|
UseBed = 0x11,
|
||||||
|
Animation = 0x12,
|
||||||
|
EntityAction = 0x13,
|
||||||
|
NamedEntitySpawn = 0x14,
|
||||||
|
|
||||||
PreChunk = 0x32,
|
PreChunk = 0x32,
|
||||||
MapChunk = 0x33,
|
MapChunk = 0x33,
|
||||||
|
|
||||||
DisconnectKick = 255
|
Entity = 0x1E,
|
||||||
|
EntityRelativeMove = 0x1F,
|
||||||
|
EntityLook = 0x20,
|
||||||
|
EntityLookRelativeMove = 0x21,
|
||||||
|
EntityTeleport = 0x22,
|
||||||
|
|
||||||
|
DisconnectKick = 0xff
|
||||||
}
|
}
|
|
@ -34,7 +34,6 @@ export class HillyGenerator implements IGenerator {
|
||||||
// This is good enough (and fast enough) for what is needed here.
|
// This is good enough (and fast enough) for what is needed here.
|
||||||
private mulberry32(a:number) {
|
private mulberry32(a:number) {
|
||||||
return function() {
|
return function() {
|
||||||
// TODO: Determine if "a" is needed
|
|
||||||
let t = a += 0x6D2B79F5;
|
let t = a += 0x6D2B79F5;
|
||||||
t = Math.imul(t ^ t >>> 15, t | 1);
|
t = Math.imul(t ^ t >>> 15, t | 1);
|
||||||
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
||||||
|
@ -87,6 +86,14 @@ export class HillyGenerator implements IGenerator {
|
||||||
chunk.setBlock(Block.wood.blockId, x, tY, z);
|
chunk.setBlock(Block.wood.blockId, x, tY, z);
|
||||||
tY++;
|
tY++;
|
||||||
}
|
}
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x - 1, tY - 2, z);
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x + 1, tY - 2, z);
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x, tY - 2, z - 1);
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x, tY - 2, z + 1);
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x - 2, tY - 2, z);
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x + 2, tY - 2, z);
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x, tY - 2, z - 2);
|
||||||
|
chunk.setBlock(Block.leaves.blockId, x, tY - 2, z + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
server/packets/Entity.ts
Normal file
26
server/packets/Entity.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { Reader, Writer } from "../../bufferStuff";
|
||||||
|
import { Packets } from "../enums/Packets";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
|
||||||
|
export class PacketEntity implements IPacket {
|
||||||
|
public packetId = Packets.Entity;
|
||||||
|
public entityId:number;
|
||||||
|
|
||||||
|
public constructor(entityId?:number) {
|
||||||
|
if (typeof(entityId) == "number") {
|
||||||
|
this.entityId = entityId;
|
||||||
|
} else {
|
||||||
|
this.entityId = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:Reader) {
|
||||||
|
this.entityId = reader.readInt();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return new Writer(5).writeUByte(this.packetId).writeInt(this.entityId).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
34
server/packets/EntityLook.ts
Normal file
34
server/packets/EntityLook.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import { Reader, Writer } from "../../bufferStuff";
|
||||||
|
import { Packets } from "../enums/Packets";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
|
||||||
|
export class PacketEntityLook implements IPacket {
|
||||||
|
public packetId = Packets.EntityLook;
|
||||||
|
public entityId:number;
|
||||||
|
public yaw:number;
|
||||||
|
public pitch:number;
|
||||||
|
|
||||||
|
public constructor(entityId?:number, yaw?:number, pitch?:number) {
|
||||||
|
if (typeof(entityId) == "number" && typeof(yaw) === "number" && typeof(pitch) === "number") {
|
||||||
|
this.entityId = entityId;
|
||||||
|
this.yaw = yaw;
|
||||||
|
this.pitch = pitch;
|
||||||
|
} else {
|
||||||
|
this.entityId = Number.MIN_VALUE;
|
||||||
|
this.yaw = Number.MIN_VALUE;
|
||||||
|
this.pitch = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:Reader) {
|
||||||
|
this.entityId = reader.readInt();
|
||||||
|
this.yaw = reader.readByte();
|
||||||
|
this.pitch = reader.readByte();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return new Writer(7).writeUByte(this.packetId).writeInt(this.entityId).writeByte(this.yaw).writeByte(this.pitch).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
46
server/packets/EntityLookRelativeMove.ts
Normal file
46
server/packets/EntityLookRelativeMove.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { Reader, Writer } from "../../bufferStuff";
|
||||||
|
import { Packets } from "../enums/Packets";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
|
||||||
|
export class PacketEntityLookRelativeMove implements IPacket {
|
||||||
|
public packetId = Packets.EntityLookRelativeMove;
|
||||||
|
public entityId:number;
|
||||||
|
public dX:number;
|
||||||
|
public dY:number;
|
||||||
|
public dZ:number;
|
||||||
|
public yaw:number;
|
||||||
|
public pitch:number;
|
||||||
|
|
||||||
|
public constructor(entityId?:number, dX?:number, dY?:number, dZ?:number, yaw?:number, pitch?:number) {
|
||||||
|
if (typeof(entityId) == "number" && typeof(dX) === "number" && typeof(dY) === "number" && typeof(dZ) === "number" && typeof(yaw) === "number" && typeof(pitch) === "number") {
|
||||||
|
this.entityId = entityId;
|
||||||
|
this.dX = dX;
|
||||||
|
this.dY = dY;
|
||||||
|
this.dZ = dZ;
|
||||||
|
this.yaw = yaw;
|
||||||
|
this.pitch = pitch;
|
||||||
|
} else {
|
||||||
|
this.entityId = Number.MIN_VALUE;
|
||||||
|
this.dX = Number.MIN_VALUE;
|
||||||
|
this.dY = Number.MIN_VALUE;
|
||||||
|
this.dZ = Number.MIN_VALUE;
|
||||||
|
this.yaw = Number.MIN_VALUE;
|
||||||
|
this.pitch = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:Reader) {
|
||||||
|
this.entityId = reader.readInt();
|
||||||
|
this.dX = reader.readByte();
|
||||||
|
this.dY = reader.readByte();
|
||||||
|
this.dZ = reader.readByte();
|
||||||
|
this.yaw = reader.readByte();
|
||||||
|
this.pitch = reader.readByte();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return new Writer(10).writeUByte(this.packetId).writeInt(this.entityId).writeByte(this.dX).writeByte(this.dY).writeByte(this.dZ).writeByte(this.yaw).writeByte(this.pitch).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
38
server/packets/EntityRelativeMove.ts
Normal file
38
server/packets/EntityRelativeMove.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { Reader, Writer } from "../../bufferStuff";
|
||||||
|
import { Packets } from "../enums/Packets";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
|
||||||
|
export class PacketEntityRelativeMove implements IPacket {
|
||||||
|
public packetId = Packets.EntityRelativeMove;
|
||||||
|
public entityId:number;
|
||||||
|
public dX:number;
|
||||||
|
public dY:number;
|
||||||
|
public dZ:number;
|
||||||
|
|
||||||
|
public constructor(entityId?:number, dX?:number, dY?:number, dZ?:number) {
|
||||||
|
if (typeof(entityId) == "number" && typeof(dX) === "number" && typeof(dY) === "number" && typeof(dZ) === "number") {
|
||||||
|
this.entityId = entityId;
|
||||||
|
this.dX = dX;
|
||||||
|
this.dY = dY;
|
||||||
|
this.dZ = dZ;
|
||||||
|
} else {
|
||||||
|
this.entityId = Number.MIN_VALUE;
|
||||||
|
this.dX = Number.MIN_VALUE;
|
||||||
|
this.dY = Number.MIN_VALUE;
|
||||||
|
this.dZ = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:Reader) {
|
||||||
|
this.entityId = reader.readInt();
|
||||||
|
this.dX = reader.readByte();
|
||||||
|
this.dY = reader.readByte();
|
||||||
|
this.dZ = reader.readByte();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return new Writer(8).writeUByte(this.packetId).writeInt(this.entityId).writeByte(this.dX).writeByte(this.dY).writeByte(this.dZ).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
46
server/packets/EntityTeleport.ts
Normal file
46
server/packets/EntityTeleport.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { Reader, Writer } from "../../bufferStuff";
|
||||||
|
import { Packets } from "../enums/Packets";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
|
||||||
|
export class PacketEntityTeleport implements IPacket {
|
||||||
|
public packetId = Packets.EntityTeleport;
|
||||||
|
public entityId:number;
|
||||||
|
public x:number;
|
||||||
|
public y:number;
|
||||||
|
public z:number;
|
||||||
|
public yaw:number;
|
||||||
|
public pitch:number;
|
||||||
|
|
||||||
|
public constructor(entityId?:number, x?:number, y?:number, z?:number, yaw?:number, pitch?:number) {
|
||||||
|
if (typeof(entityId) == "number" && typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number" && typeof(yaw) === "number" && typeof(pitch) === "number") {
|
||||||
|
this.entityId = entityId;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.yaw = yaw;
|
||||||
|
this.pitch = pitch;
|
||||||
|
} else {
|
||||||
|
this.entityId = Number.MIN_VALUE;
|
||||||
|
this.x = Number.MIN_VALUE;
|
||||||
|
this.y = Number.MIN_VALUE;
|
||||||
|
this.z = Number.MIN_VALUE;
|
||||||
|
this.yaw = Number.MIN_VALUE;
|
||||||
|
this.pitch = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:Reader) {
|
||||||
|
this.entityId = reader.readInt();
|
||||||
|
this.x = reader.readInt();
|
||||||
|
this.y = reader.readInt();
|
||||||
|
this.z = reader.readInt();
|
||||||
|
this.yaw = reader.readByte();
|
||||||
|
this.pitch = reader.readByte();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return new Writer(19).writeUByte(this.packetId).writeInt(this.entityId).writeInt(this.x).writeInt(this.y).writeInt(this.z).writeByte(this.yaw).writeByte(this.pitch).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
53
server/packets/NamedEntitySpawn.ts
Normal file
53
server/packets/NamedEntitySpawn.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import { Reader, Writer } from "../../bufferStuff";
|
||||||
|
import { Packets } from "../enums/Packets";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
|
||||||
|
export class PacketNamedEntitySpawn implements IPacket {
|
||||||
|
public packetId = Packets.NamedEntitySpawn;
|
||||||
|
public entityId:number;
|
||||||
|
public playerName:string;
|
||||||
|
public x:number;
|
||||||
|
public y:number;
|
||||||
|
public z:number;
|
||||||
|
public yaw:number;
|
||||||
|
public pitch:number;
|
||||||
|
public currentItem:number;
|
||||||
|
|
||||||
|
public constructor(entityId?:number, playerName?:string, x?:number, y?:number, z?:number, yaw?:number, pitch?:number, currentItem?:number) {
|
||||||
|
if (typeof(entityId) === "number" && typeof(playerName) === "string" && typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number" && typeof(yaw) === "number" && typeof(pitch) === "number" && typeof(currentItem) === "number") {
|
||||||
|
this.entityId = entityId;
|
||||||
|
this.playerName = playerName;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.yaw = yaw;
|
||||||
|
this.pitch = pitch;
|
||||||
|
this.currentItem = currentItem;
|
||||||
|
} else {
|
||||||
|
this.entityId = Number.MIN_VALUE;
|
||||||
|
this.playerName = "";
|
||||||
|
this.x = Number.MIN_VALUE;
|
||||||
|
this.y = Number.MIN_VALUE;
|
||||||
|
this.z = Number.MIN_VALUE;
|
||||||
|
this.yaw = Number.MIN_VALUE;
|
||||||
|
this.pitch = Number.MIN_VALUE;
|
||||||
|
this.currentItem = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:Reader) {
|
||||||
|
this.entityId = reader.readInt();
|
||||||
|
this.playerName = reader.readString();
|
||||||
|
this.x = reader.readInt();
|
||||||
|
this.y = reader.readInt();
|
||||||
|
this.z = reader.readInt();
|
||||||
|
this.yaw = reader.readByte();
|
||||||
|
this.pitch = reader.readByte();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return new Writer(23 + this.playerName.length * 2).writeUByte(this.packetId).writeInt(this.entityId).writeString(this.playerName).writeInt(this.x).writeInt(this.y).writeInt(this.z).writeByte(this.yaw).writeByte(this.pitch).writeShort(this.currentItem).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
42
server/packets/PlayerDigging.ts
Normal file
42
server/packets/PlayerDigging.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { Reader, Writer } from "../../bufferStuff";
|
||||||
|
import { Packets } from "../enums/Packets";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
|
||||||
|
export class PacketPlayerDigging implements IPacket {
|
||||||
|
public packetId = Packets.PlayerDigging;
|
||||||
|
public status:number;
|
||||||
|
public x:number;
|
||||||
|
public y:number;
|
||||||
|
public z:number;
|
||||||
|
public face:number;
|
||||||
|
|
||||||
|
public constructor(status?:number, x?:number, y?:number, z?:number, face?:number) {
|
||||||
|
if (typeof(status) == "number" && typeof(x) === "number" && typeof(y) === "number" && typeof(z) === "number" && typeof(face) === "number") {
|
||||||
|
this.status = status;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.face = face;
|
||||||
|
} else {
|
||||||
|
this.status = Number.MIN_VALUE;
|
||||||
|
this.x = Number.MIN_VALUE;
|
||||||
|
this.y = Number.MIN_VALUE;
|
||||||
|
this.z = Number.MIN_VALUE;
|
||||||
|
this.face = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:Reader) {
|
||||||
|
this.status = reader.readByte();
|
||||||
|
this.x = reader.readInt();
|
||||||
|
this.y = reader.readByte();
|
||||||
|
this.z = reader.readInt();
|
||||||
|
this.face = reader.readByte();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return new Writer(12).writeUByte(this.packetId).writeByte(this.status).writeInt(this.x).writeByte(this.y).writeInt(this.z).writeByte(this.face).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue