From 23a1d124c0afa2dafd009f0a7dd2fde5712dc2bc Mon Sep 17 00:00:00 2001 From: Holly Date: Sun, 5 Nov 2023 10:58:35 +0000 Subject: [PATCH] Send player equipment on join --- server/MinecraftServer.ts | 8 ++++++ server/entities/Player.ts | 57 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/server/MinecraftServer.ts b/server/MinecraftServer.ts index 5ebc5c9..a62f5d9 100644 --- a/server/MinecraftServer.ts +++ b/server/MinecraftServer.ts @@ -171,6 +171,9 @@ export class MinecraftServer { client.send(timePacket); }); } + + // const memoryUsage = process.memoryUsage(); + // console.log(`Memory Usage: ${(memoryUsage.heapUsed / 1024 / 1024).toFixed(1)}MB / ${(memoryUsage.heapTotal / 1024 / 1024).toFixed(1)}MB ArrayBuffers: ${(memoryUsage.arrayBuffers / 1024 / 1024).toFixed(1)}MB`); } this.worlds.forEach(world => { @@ -228,8 +231,13 @@ export class MinecraftServer { const thisPlayerSpawn = new PacketNamedEntitySpawn(clientEntity.entityId, clientEntity.username, clientEntity.absPosition.x, clientEntity.absPosition.y, clientEntity.absPosition.z, clientEntity.absRotation.yaw, clientEntity.absRotation.pitch, clientEntity.mpClient?.getHeldItemStack()?.itemID).writeData(); world.players.forEach(player => { if (player.entityId !== clientEntity.entityId && clientEntity.distanceTo(player) < World.ENTITY_MAX_SEND_DISTANCE) { + // Inform the joining player of the players around them socket.write(new PacketNamedEntitySpawn(player.entityId, player.username, player.absPosition.x, player.absPosition.y, player.absPosition.z, player.absRotation.yaw, player.absRotation.pitch, player.mpClient?.getHeldItemStack()?.itemID).writeData()); + player.sendPlayerEquipment(clientEntity); + + // Inform players around the joining player of the joined player player.mpClient?.send(thisPlayerSpawn); + clientEntity.sendPlayerEquipment(player); } }); diff --git a/server/entities/Player.ts b/server/entities/Player.ts index af86293..4cf1f29 100644 --- a/server/entities/Player.ts +++ b/server/entities/Player.ts @@ -11,6 +11,7 @@ import { ItemStack } from "../inventories/ItemStack"; import { Block } from "../blocks/Block"; import PlayerInventory from "../inventories/PlayerInventory"; import { Item } from "../items/Item"; +import { PacketEntityEquipment } from "../packets/EntityEquipment"; const CHUNK_LOAD_RANGE = 15; @@ -23,6 +24,8 @@ export class Player extends EntityLiving { public mpClient?:MPClient; public inventory:PlayerInventory; + public trackedEquipment:Array; + public constructor(server:MinecraftServer, world:World, username:string) { super(world); this.server = server; @@ -38,10 +41,16 @@ export class Player extends EntityLiving { this.inventory.setSlotItemStack(39, new ItemStack(Item.ironAxe, 1)); this.inventory.setSlotItemStack(43, new ItemStack(Block.dirt, 32)); + this.trackedEquipment = new Array(); + for (let i = 0; i < 5; i++) { + this.trackedEquipment.push(null); + } + this.username = username; this.position.set(8, 64, 8); } + // Forces a player chunk update *next tick* public forceUpdatePlayerChunks() { this.firstUpdate = true; } @@ -90,14 +99,60 @@ export class Player extends EntityLiving { } } + private getEquipmentForVirtualSlot(slot:number) { + if (slot === 0) { + return this.mpClient?.getHeldItemStack() ?? null; + } else { + this.inventory.getSlotItemStack(4 + slot); // 5 - 8 + } + + return null; + } + + private sendEquipment(equipmentId:number, itemStack:ItemStack | null) { + this.sendToNearby(new PacketEntityEquipment(this.entityId, equipmentId, itemStack == null ? -1 : itemStack.itemID, itemStack == null ? 0 : itemStack.damage).writeData()); + } + + private sendEquipmentPlayer(mpClient:MPClient, equipmentId:number, itemStack:ItemStack | null) { + mpClient.send(new PacketEntityEquipment(this.entityId, equipmentId, itemStack == null ? -1 : itemStack.itemID, itemStack == null ? 0 : itemStack.damage).writeData()); + } + + // For login. + public sendPlayerEquipment(playerToSendTo:Player) { + const mpClient = playerToSendTo.mpClient; + if (mpClient == null) { + return; + } + + for (let slotId = 0; slotId < 5; slotId++) { + const itemStack = this.getEquipmentForVirtualSlot(slotId); + const trackedEquipment = this.trackedEquipment[slotId]; + + if ((itemStack == null || trackedEquipment == null) || !itemStack.compare(trackedEquipment)) { + this.trackedEquipment[slotId] = itemStack; + this.sendEquipmentPlayer(mpClient, slotId, itemStack); + } + } + } + public onTick() { this.updatePlayerChunks(); - // Calculate player motion + // Calculate player motion since we don't have it serverside. this.motion.set(this.position.x - this.lastPosition.x, this.position.y - this.lastPosition.y, this.position.z - this.lastPosition.z); super.onTick(); + for (let slotId = 0; slotId < 5; slotId++) { + const itemStack = this.getEquipmentForVirtualSlot(slotId); + const trackedEquipment = this.trackedEquipment[slotId]; + + if ((itemStack == null || trackedEquipment == null) || !itemStack.compare(trackedEquipment)) { + this.trackedEquipment[slotId] = itemStack; + this.sendEquipment(slotId, itemStack); + } + } + if (this.health != this.lastHealth) { this.lastHealth = this.health; this.mpClient?.send(new PacketUpdateHealth(this.health).writeData());