diff --git a/server/inventories/ItemStack.ts b/server/inventories/ItemStack.ts index f698a39..e67e254 100644 --- a/server/inventories/ItemStack.ts +++ b/server/inventories/ItemStack.ts @@ -92,18 +92,19 @@ export class ItemStack { public insert(itemStack:ItemStack) { const remainingSpace = this.spaceAvaliable; if (remainingSpace === 0) { - return; + return false; } if (remainingSpace >= itemStack.size) { this.size += itemStack.size; itemStack.size = 0; - return; + return true; } if (remainingSpace < itemStack.size) { this.size += remainingSpace; itemStack.size -= remainingSpace; + return true; } } diff --git a/server/inventories/PlayerInventory.ts b/server/inventories/PlayerInventory.ts index a842da6..e43ce2a 100644 --- a/server/inventories/PlayerInventory.ts +++ b/server/inventories/PlayerInventory.ts @@ -1,4 +1,6 @@ import { Player } from "../entities/Player"; +import { PacketSetSlot } from "../packets/SetSlot"; +import { PacketWindowItems } from "../packets/WindowItems"; import { Inventory } from "./Inventory"; import { ItemStack } from "./ItemStack"; @@ -11,64 +13,95 @@ export default class PlayerInventory extends Inventory { this.player = player; } + sendUpdatedStacks(stackIdsChanged:Array) { + let updateBuffer = Buffer.alloc(0); + for (const slotId of stackIdsChanged) { + const slotItem = this.itemStacks[slotId]; + let buffer:Buffer; + if (slotItem == null) { + buffer = new PacketSetSlot(0, slotId, -1).writeData(); + } else { + buffer = new PacketSetSlot(0, slotId, slotItem.itemID, slotItem.size, slotItem.damage).writeData(); + } + + updateBuffer = Buffer.concat([updateBuffer, buffer], updateBuffer.length + buffer.length); + } + if (updateBuffer.length > 0) { + this.player.mpClient?.send(updateBuffer); + } + } + addItemStack(itemStack:ItemStack) { const itemStacksOfSameType:Array = new Array(); + const itemStackIds:Array = new Array(); + const stackIdsChanged:Array = new Array(); // Check bottom inventory row (hotbar) first. let workingItemStack:ItemStack | null; for (let slotId = 36; slotId <= 44; slotId++) { if ((workingItemStack = this.itemStacks[slotId]) != null) { itemStacksOfSameType.push(workingItemStack); + itemStackIds.push(slotId); } } for (let slotId = 9; slotId <= 35; slotId++) { if ((workingItemStack = this.itemStacks[slotId]) != null) { itemStacksOfSameType.push(workingItemStack); + itemStackIds.push(slotId); } } // Insert into existing stacks first. - for (const inventoryItemStack of itemStacksOfSameType) { + for (let i = 0; i < itemStacksOfSameType.length; i++) { + const inventoryItemStack = itemStacksOfSameType[i]; // Exit early if we have nothing left if (itemStack.size === 0) { - return; + return this.sendUpdatedStacks(stackIdsChanged); } if (inventoryItemStack.itemID !== itemStack.itemID || inventoryItemStack.damage !== itemStack.damage) { continue; } - inventoryItemStack.insert(itemStack); + if (inventoryItemStack.insert(itemStack)) { + stackIdsChanged.push(itemStackIds[i]); + } } // Exit early if we have nothing left if (itemStack.size === 0) { - return; + return this.sendUpdatedStacks(stackIdsChanged); } for (let slotId = 36; slotId <= 44; slotId++) { // Exit early if we have nothing left if (itemStack.size === 0) { - return; + return this.sendUpdatedStacks(stackIdsChanged); } if ((workingItemStack = this.itemStacks[slotId]) == null) { const stack = this.itemStacks[slotId] = new ItemStack(itemStack.itemID, 0, itemStack.damage); - stack.insert(itemStack); + if (stack.insert(itemStack)) { + stackIdsChanged.push(slotId); + } } } for (let slotId = 9; slotId <= 35; slotId++) { // Exit early if we have nothing left if (itemStack.size === 0) { - return; + return this.sendUpdatedStacks(stackIdsChanged); } if ((workingItemStack = this.itemStacks[slotId]) == null) { const stack = this.itemStacks[slotId] = new ItemStack(itemStack.itemID, 0, itemStack.damage); - stack.insert(itemStack); + if (stack.insert(itemStack)) { + stackIdsChanged.push(slotId); + } } } + + this.sendUpdatedStacks(stackIdsChanged) } } \ No newline at end of file diff --git a/server/packets/SetSlot.ts b/server/packets/SetSlot.ts new file mode 100644 index 0000000..1b5168e --- /dev/null +++ b/server/packets/SetSlot.ts @@ -0,0 +1,49 @@ +import { createWriter, IReader, Endian } from "bufferstuff"; +import { IPacket } from "./IPacket"; +import { Packet } from "../enums/Packet"; + +export class PacketSetSlot implements IPacket { + public packetId = Packet.SetSlot; + public windowId:number; + public slot:number; + public itemId:number; + public itemCount:number; + public itemUses:number; + + public constructor(windowId?:number, slot?:number, itemId?:number, itemCount?:number, itemUses?:number) { + if (typeof(windowId) === "number" && typeof(slot) === "number" && typeof(itemId) === "number" && typeof(itemCount) === "number" && typeof(itemUses) === "number") { + this.windowId = windowId; + this.slot = slot; + this.itemId = itemId; + this.itemCount = itemCount; + this.itemUses = itemUses; + } else { + this.windowId = Number.MIN_VALUE; + this.slot = Number.MIN_VALUE; + this.itemId = Number.MIN_VALUE; + this.itemCount = Number.MIN_VALUE; + this.itemUses = Number.MIN_VALUE; + } + } + + public readData(reader:IReader) { + this.windowId = reader.readByte(); + this.slot = reader.readShort(); + this.itemId = reader.readShort(); + if (this.itemId !== -1) { + this.itemCount = reader.readByte(); + this.itemUses = reader.readShort(); + } + + return this; + } + + public writeData() { + const writer = createWriter(Endian.BE, this.itemId === -1 ? 6 : 9).writeUByte(this.packetId).writeByte(this.windowId).writeShort(this.slot).writeShort(this.itemId); + if (this.itemId !== -1) { + writer.writeByte(this.itemCount); + writer.writeShort(this.itemUses); + } + return writer.toBuffer(); + } +} \ No newline at end of file