mc-beta-server/server/inventories/Inventory.ts

139 lines
3.5 KiB
TypeScript
Raw Normal View History

2023-11-09 17:04:11 +00:00
import { Endian, IReader, IWriter, createWriter } from "bufferstuff";
2024-11-29 15:00:48 +00:00
import FunkyArray from "funky-array";
2023-10-29 05:08:26 +00:00
import IInventory from "./IInventory";
import ItemStack from "./ItemStack";
2023-10-29 05:08:26 +00:00
export default class Inventory implements IInventory {
2024-11-29 15:00:48 +00:00
private static CHANGE_HANDLER_ROLLING_HANDLE_ID = 0;
public changeHandlers:FunkyArray<number, (itemStack: ItemStack) => void>;
2023-11-02 08:31:43 +00:00
public itemStacks:Array<ItemStack | null>;
2023-10-29 05:08:26 +00:00
private size:number;
private name:string;
public constructor(size:number, name:string) {
2024-11-29 15:00:48 +00:00
this.changeHandlers = new FunkyArray<number, (itemStack: ItemStack) => void>();
2023-10-29 05:08:26 +00:00
this.itemStacks = new Array<ItemStack | null>();
for (let i = 0; i < size; i++) {
this.itemStacks.push(null);
}
this.size = size;
this.name = name;
}
2024-11-29 15:00:48 +00:00
registerChangeHandler(changeHandler: (itemStack: ItemStack) => void) {
const changeHandlerHandle = Inventory.CHANGE_HANDLER_ROLLING_HANDLE_ID++;
this.changeHandlers.set(changeHandlerHandle, changeHandler);
return changeHandlerHandle;
}
unregisterChangeHandler(changeHandlerHandle: number) {
if (this.changeHandlers.has(changeHandlerHandle)) {
this.changeHandlers.remove(changeHandlerHandle);
}
}
2023-11-09 17:04:11 +00:00
public fromSave(reader:IReader) {
const inventorySize = reader.readByte();
for (let i = 0; i < inventorySize; i++) {
this.itemStacks[i] = ItemStack.FromSave(reader);
}
}
public toSave(writer:IWriter) {
writer.writeByte(this.size);
for (const itemStack of this.itemStacks) {
if (itemStack === null) {
writer.writeShort(-1);
continue;
}
itemStack.toSave(writer);
}
}
2023-11-02 08:31:43 +00:00
addItemStack(itemStack:ItemStack) {
2023-12-18 01:23:52 +00:00
throw new Error("Adding items to non player inventories is unimplemented.");
2023-11-02 08:31:43 +00:00
// Check bottom inventory row (hotbar) first.
/*let workingItemStack:ItemStack | null;
for (let slotId = 9; slotId <= 35; slotId++) {
if (itemStack.size === 0) {
break;
}
if ((workingItemStack = this.itemStacks[slotId]) != null) {
workingItemStack.insert(itemStack);
}
}*/
}
2023-10-29 05:08:26 +00:00
getInventoryName() {
return this.name;
}
getInventorySize() {
return this.itemStacks.length;
}
getSlotItemStack(slotId:number) {
return this.itemStacks[slotId];
}
2023-11-07 01:50:51 +00:00
dropEmptyItemStacks() {
for (let i = 0; i < this.itemStacks.length; i++) {
const itemStack = this.itemStacks[i];
if (itemStack?.size === 0) {
this.itemStacks[i] = null;
}
}
}
2023-10-29 05:08:26 +00:00
setSlotItemStack(slotId:number, itemStack: ItemStack | null) {
if (slotId < 0 || slotId > this.size - 1) {
throw new Error(`Tried to set an Inventory ItemStack out of bounds! Requested slot: ${slotId}, Inventory Size: ${this.size}`);
}
this.itemStacks[slotId] = itemStack;
return this;
}
private calculateInventoryPayloadSize() {
let bufferSize = 0;
for (const stack of this.itemStacks) {
if (stack) {
bufferSize += 5; // short + byte + short
} else {
bufferSize += 2; // short
}
}
return bufferSize;
}
constructInventoryPayload() {
const writer = createWriter(Endian.BE, this.calculateInventoryPayloadSize());
for (const stack of this.itemStacks) {
writer.writeShort(stack == null ? -1 : stack.itemID);
if (stack != null) {
writer.writeByte(stack.size);
writer.writeShort(stack.damage);
}
}
return writer.toBuffer();
}
2023-12-18 01:23:52 +00:00
constructInventorySinglePayload(slotId:number) {
const stack = this.itemStacks[slotId];
const writer = createWriter(Endian.BE, stack == null ? 2 : 5);
writer.writeShort(stack == null ? -1 : stack.itemID);
if (stack != null) {
writer.writeByte(stack.size);
writer.writeShort(stack.damage);
}
return writer.toBuffer();
}
2023-10-29 05:08:26 +00:00
}