tiny-essentials
Version:
Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.
778 lines (469 loc) โข 18.6 kB
Markdown
# ๐ฆ TinyInventory
**TinyInventory** is a lightweight yet powerful inventory management system designed for games, simulations, and applications that require structured item handling. It provides:
* **Stack management** (items merge up to configurable stack limits).
* **Slot management** (fixed, dynamic, and special equipment slots).
* **Weight and size constraints** for advanced gameplay mechanics.
* **Serialization & cloning** (save, load, and duplicate inventories safely).
* **Flexible item registry support** to integrate with custom game logic.
With a clean API and robust safeguards, TinyInventory ensures that every item transaction โ whether adding, removing, moving, or trading โ follows consistent rules and prevents invalid states.
It is designed to work standalone or as a foundation for higher-level systems, such as crafting, trading, or player equipment managers.
## ๐ฆ Core Types & Properties
### ๐งฉ ItemDef
Represents a registered **item definition** in the global registry.
| Property | Type | Description |
| ---------- | -------------------- | ------------------------------------ |
| `id` | `string` | Unique identifier for the item. |
| `weight` | `number` | Weight of a single unit. |
| `metadata` | `InventoryMetadata` | Default metadata for this item type. |
| `maxStack` | `number` | Maximum stack size per slot. |
| `onUse` | `OnUseEvent \| null` | Callback triggered when used. |
| `type` | `string \| null` | Optional category/type. |
### ๐ InventoryItem
Represents a **stored item instance** inside the inventory.
| Property | Type | Description |
| ---------- | ------------------- | --------------------------- |
| `id` | `string` | Item identifier. |
| `metadata` | `InventoryMetadata` | Metadata for this instance. |
| `quantity` | `number` | Units in this stack. |
### ๐ InvSlots
An array of item stacks in the inventory.
```ts
(InventoryItem | null)[]
```
### ๐๏ธ InventoryMetadata
Metadata object for **arbitrary key-value pairs**.
```ts
Record<string | number | symbol, any>
```
### ๐ก๏ธ SpecialSlot
Represents a **special slot** (e.g., equipment).
| Property | Type | Description |
| -------- | ----------------------- | -------------------------- |
| `type` | `string \| null` | Optional slot category. |
| `item` | `InventoryItem \| null` | Item equipped in the slot. |
### ๐ Event System
* `OnEvent` โ `(payload: EventPayload) => void`
* **AddItemEvent** โ triggered when an item is added
* **SetItemEvent** โ triggered when an item is set/overwritten
* **RemoveItemEvent** โ triggered when an item is removed
* **UseItemEvent** โ triggered when an item is used
### ๐ท๏ธ OnUseEvent
Special callback executed when using an item.
```ts
(payload: EventPayload) => void
```
### ๐ฏ EventsType
Supported event strings:
`"add" | "remove" | "use" | "set"`
### ๐ Callbacks
* **GetItemsByMetadataCallback** โ Filters items by metadata.
* **FindItemCallback** โ Works like `Array.prototype.find()` to locate items.
### ๐ SerializedInventory
Full JSON structure for saving/loading inventories.
| Property | Type | Description | |
| -------------- | ----------------------------- | -------------------------------- | ------------- |
| `__schema` | `"TinyInventory"` | Schema identifier. | |
| `version` | `number` | Format version. | |
| `maxWeight` | `number \| null` | Max weight allowed. | |
| `maxSlots` | `number \| null` | Max slots allowed. | |
| `maxSize` | `number \| null` | Max item amount. | |
| `maxStack` | `number` | Global stack limit. | |
| `items` | \`(InventoryItem | null)\[]\` | Stored items. |
| `specialSlots` | `Record<string, SpecialSlot>` | Reserved slots (e.g., "helmet"). | |
### ๐๏ธ ItemListData
Tuple representing an inventory entry:
```ts
[InventoryItem, number] // [item, index]
```
### ๐ฌ EventPayload
Payload object dispatched when an inventory action occurs.
| Property | Type | Description | |
| -------------- | ------------------------------- | ------------------------ | ---------------------------- |
| `index` | \`number | null\` | Item index in slots. |
| `item` | \`InventoryItem | null\` | Item affected. |
| `isCollection` | `boolean` | True if from collection. | |
| `specialSlot` | \`string | null\` | Special slot ID if relevant. |
| `remove` | `(forceSpace: boolean) => void` | Function to remove item. | |
### โ AddItemResult
Result object returned after adding an item.
| Property | Type | Description |
| ------------- | --------------------------------------- | --------------------------------------------- |
| `remaining` | `number` | Quantity not added due to space/stack limits. |
| `placesAdded` | `{ index: number; quantity: number }[]` | Slots where items were placed. |
## ๐๏ธ TinyInventory Class
A **flexible inventory management system** providing:
* ๐ฆ Standard slots with configurable **limits** (weight, size, stack).
* ๐ก๏ธ Special slots for **equipment & unique items**.
* โ๏ธ Full **CRUD** operations (add, remove, move, use, equip, unequip).
* ๐ง **Metadata-aware** handling (durability, enchantments, etc.).
* ๐พ **Serialization/Deserialization** to JSON.
* ๐ **Event triggers** for `"add"`, `"remove"`, `"use"`, `"set"`.
### ๐ท๏ธ Static: `#ItemRegistry`
TinyInventory comes with a **global item registry** that defines all possible item types before they are used in any inventory.
This ensures consistency in rules such as stack limits, metadata defaults, weight, and usage behavior (`id โ ItemDef`).
#### ๐ `TinyInventory.itemRegistry` (getter)
Returns a deep-cloned snapshot of the registered item definitions.
* โ
Prevents accidental mutations of the internal registry.
* ๐ Each entry includes `id`, `weight`, `maxStack`, `metadata`, `type`, and `onUse`.
**Returns:**
```ts
Record<string, ItemDef>
```
#### โ `TinyInventory.removeItem(itemId)`
Removes an item type from the registry.
**Parameters:**
* `itemId` *(string)* โ The unique identifier.
**Returns:**
* `true` if the item existed and was removed.
* `false` if the item was not found.
#### โ
`TinyInventory.hasItem(itemId)`
Checks if an item type exists in the registry.
**Parameters:**
* `itemId` *(string)* โ The unique identifier.
**Returns:**
* `true` if the item exists.
* `false` otherwise.
#### ๐ฅ `TinyInventory.getItem(itemId)`
Retrieves the definition of a registered item.
**Parameters:**
* `itemId` *(string)* โ The unique identifier.
**Returns:**
* `ItemDef` โ The item definition.
โ ๏ธ Throws `Error` if the item is not defined.
#### ๐ ๏ธ Static: `defineItem(config)`
Registers or updates an item in the global registry.
```ts
TinyInventory.defineItem({
id: "apple",
weight: 0.2,
maxStack: 10,
metadata: { edible: true },
type: "food",
onUse: (payload) => console.log("Apple eaten!", payload),
});
```
โ ๏ธ Throws if `id` is missing or invalid.
### โ๏ธ Constructor
Creates a new inventory instance with customizable constraints:
```ts
new TinyInventory({
maxWeight: 100,
maxSlots: 20,
maxSize: 200,
maxStack: 99,
specialSlots: { helmet: { type: "armor" }, weapon: { type: "sword" } }
});
```
### ๐ Properties (Getters & Setters)
* `maxStack` โ Maximum stack size per slot.
* `maxSize` โ Maximum total quantity of items.
* `maxSlots` โ Maximum number of slots.
* `maxWeight` โ Maximum total weight allowed.
* `events` โ Returns registered event listeners.
* `items` โ Returns cloned item list.
* `specialSlots` โ Returns cloned special slots.
### ๐ Calculated Properties
* `size` โ Total quantity of items.
* `slotsSize` โ Number of occupied slots.
* `weight` โ Total carried weight.
## โ๏ธ Space & Capacity Checks
### ๐ `hasSpace(settings?)`
Checks if there is **available space** based on slot, size, and weight limits.
```ts
hasSpace({
weight?: number,
sizeLength?: number,
slotsLength?: number
}): boolean
```
| Parameter | Type | Default | Description |
| ------------- | ------ | ------- | ------------------------------------------------------ |
| `weight` | number | `0` | Extra weight to preview (e.g., before adding an item). |
| `sizeLength` | number | `0` | Extra item count to preview. |
| `slotsLength` | number | `0` | Extra slot count to preview. |
โ
Returns `true` if the inventory can handle the addition.
### ๐๏ธ `isHeavy(extraWeight = 0)`
Checks if the **total weight** exceeds the max allowed.
* `true` โ Overweight
* `false` โ Within limits
### ๐ฆ `areFull(extraLength = 0)`
Checks if the **item count** exceeds `maxSize`.
* Uses `>` check (strictly over the limit).
### ๐ฆ `isFull(extraLength = 0)`
Checks if the **item count** has **reached** `maxSize`.
* Uses `>=` check (at limit or over).
### ๐ฏ `areFullSlots(extraLength = 0)`
Checks if the **slot count** exceeds `maxSlots`.
* Uses `>` check.
### ๐ฏ `isFullSlots(extraLength = 0)`
Checks if the **slot count** has **reached** `maxSlots`.
* Uses `>=` check.
## ๐ Event System
### โก `#triggerEvent(type, payload)`
Internal method to dispatch inventory events.
* `type` โ `"add" | "remove" | "use" | "set"`
* `payload` โ `EventPayload`
### โ `off(eventType, callback)`
Unregisters a specific event listener.
### ๐งน `offAll(eventType)`
Removes **all callbacks** for a given event type.
### ๐ช `cloneEventCallbacks(eventType)`
Returns a **shallow copy** of all listeners for an event type.
### ๐ Event Registration Helpers
* `onAddItem(callback)` โ Listen to item additions.
* `onSetItem(callback)` โ Listen to item sets/replacements.
* `onRemoveItem(callback)` โ Listen to removals.
* `onUseItem(callback)` โ Listen to item usage.
## ๐งน Slot Management
### ๐งฝ `compactInventory()`
Removes unnecessary `null` values, **compacting slots**.
* Preserves item order.
* Triggers `"remove"` event for cleared slots.
## ๐งน Inventory Clearing
### ๐งฝ `clear()`
Clears **all items** and **event listeners** from the inventory.
* Resets normal and special slots.
* Clears all registered event listeners (`add`, `remove`, `use`, `set`).
* Preserves max limits and slot definitions.
### ๐งน `clearAllEvents()`
Removes **all registered event listeners** from the inventory.
* Event types affected: `"add"`, `"remove"`, `"use"`, `"set"`.
* Does not affect any items in inventory.
### ๐๏ธ `clearAllItems()`
Removes **all items** from the inventory, including normal and special slots.
* Calls `clearItems()` and `clearSpecialItems()` internally.
* Does not remove slots or event listeners.
### ๐ฆ `clearItems()`
Clears all items in **normal inventory slots**.
* Resets the `#items` array to empty.
* Does not affect special slots or event listeners.
### ๐ฏ `clearSpecialItems()`
Clears all items in **special slots**, without removing the slots themselves.
* Each slot remains defined, but its `item` property is set to `null`.
* Does not affect normal slots or event listeners.
## โ Item Management
### ๐ฅ `addItem(options)`
Adds an item to the inventory, respecting:
* โ
Stack limits
* โ
Metadata equality
* โ
Capacity (size, slots, weight)
```ts
addItem({
itemId: string,
quantity?: number,
metadata?: InventoryMetadata,
forceSpace?: boolean
}): AddItemResult
```
#### Behavior:
1. ๐ **Fills existing stacks** first.
2. ๐ค **Uses empty slots** if possible.
3. ๐ **Pushes new stacks** at the end if needed.
๐ฆ Returns `{ remaining, placesAdded }`.
โ ๏ธ Throws if the item is not registered.
### ๐ค `getItemFrom(slotIndex)`
Retrieves item from a slot.
* Returns a **clone** (safe copy).
* Throws if index is out of bounds.
### โ๏ธ `setItem(options)`
Directly sets or clears an item at a specific slot.
* Validates stack size & registry.
* Supports `null` for deletion.
* Triggers `"set"` event.
* Throws if invalid index or type.
### โ `deleteItem(slotIndex, forceSpace?)`
Shortcut for clearing a slot (`setItem({ item: null })`).
### ๐ `moveItem(fromIndex, toIndex, forceSpace?)`
Moves an item from one slot to another.
* Throws if source is empty.
* Replaces destination if valid.
### ๐๏ธ `removeItem(options)`
Removes a quantity of a given item (normal slots + special slots).
```ts
removeItem({
itemId: string,
metadata?: InventoryMetadata | null,
quantity?: number
}): boolean
```
* โ
Matches by `id` and optional `metadata`.
* โ
Works across both normal slots and special slots.
* โ
Triggers `"remove"` events.
* Returns `true` if fully removed, `false` if not enough items.
## ๐ฎ Item Usage & Special Slots
### ๐งฉ `#removeItemCallback(config)`
Creates a **removal callback** for normal or special slots.
```ts
#removeItemCallback({
locationType: "special" | "normal",
item: InventoryItem,
specialSlot?: string,
slotIndex?: number,
forceSpace?: boolean
}): (forceSpace?: boolean) => void
```
* Decrements item quantity.
* Clears slot if quantity reaches `0`.
* Returns a function that executes the removal.
### ๐ฏ `useItem({ slotIndex, specialSlot, forceSpace }, ...args)`
Uses an item from either a **normal slot** or a **special slot**.
โจ Behavior:
* Calls the itemโs `onUse` callback if defined.
* Provides a `remove()` function inside the `onUse` context.
* Triggers the `"use"` event.
โ ๏ธ Throws if the item doesnโt exist.
## ๐ก๏ธ Special Slot Management
### ๐ `hasSpecialSlot(slotId)`
Checks if a special slot exists.
### ๐ฆ `getSpecialItem(slotId)`
Gets the item from a special slot.
* Returns `null` if empty.
* Throws if slot doesnโt exist.
### ๐ท๏ธ `getSpecialSlotType(slotId)`
Gets the type/category of a special slot.
* Returns `null` if unrestricted.
### โ๏ธ `setSpecialSlot({ slotId, item, forceSpace })`
Sets or clears an item in a special slot.
* Validates item structure.
* Ensures registry + weight/space limits.
* Triggers `"set"` event.
### โ `deleteSpecialItem(slotId, forceSpace?)`
Clears a special slot (sets item to `null`).
### โ๏ธ `equipItem({ slotId, slotIndex, quantity, forceSpace })`
Equips an item from the inventory into a special slot.
โจ Behavior:
1. **Same item equipped + stackable** โ merge up to `maxStack`.
2. **Different item equipped** โ unequips old item and equips the new one.
3. Returns leftover quantity (not equipped).
โ ๏ธ Throws if slot does not exist, types mismatch, or insufficient quantity.
### ๐ก๏ธ `unequipItem({ slotId, quantity, forceSpace })`
Unequips an item from a special slot back to the inventory.
* If `quantity` is omitted โ unequips the whole stack.
* Returns `true` if successful, `false` if empty.
* Throws if invalid quantity.
## ๐ ๏ธ Utility Methods
### ๐งฌ `#cloneItemData(item)`
Creates a **deep clone** of an item (copies metadata).
### ๐ `getItemList()`
Returns an array of all items with their slot indexes:
```ts
[ InventoryItem, index ][]
```
### ๐ฆ `getAllItems()`
Returns all items in the inventory,
including **special slots**, excluding `null`s.
### ๐ `getItemsByMetadata(filterFn)`
Finds items by metadata.
* `filterFn(itemTypeMetadata, itemInstance)` must return `true` to include item.
### ๐ `findItem(predicate)`
Finds the **first item** matching the predicate.
### ๐ `findItems(predicate)`
Finds **all items** matching the predicate.
### ๐ข `getItemCount(itemId)`
Counts the **total quantity** of a given item across the whole inventory.
### โ
`hasItem(itemId, quantity = 1)`
Checks if the inventory has at least `quantity` of a given item.
### ๐ `existsItemAt(slotIndex)`
Checks if there is an item at a given **normal slot index**.
## ๐ Serialization & Cloning
### ๐งฌ `clone()`
Creates a **deep copy** of the entire inventory.
โจ Behavior:
* Copies all items, slots, and metadata.
* The clone is fully independent (changes wonโt affect the original).
๐ Returns:
* A new `TinyInventory` instance.
### ๐ฆ `toObject()`
Creates a **plain JSON-safe object** representing the current inventory state.
โจ Behavior:
* Functions (like `onUse`) are **not serialized**.
* Only item data, slots, and metadata are saved.
๐ Returns:
* A `SerializedInventory` object (safe to `JSON.stringify`).
### ๐ `toJSON(space = 0)`
Serializes the inventory into a **JSON string**.
* `space` controls pretty-print indentation (e.g., `2`).
๐ Returns:
* A JSON string representing the inventory.
## ๐ฅ Deserialization
### ๐ ๏ธ `static fromObject(obj)`
Rebuilds a `TinyInventory` instance from a plain object produced by `toObject()`.
โจ Behavior:
* Requires **item definitions** to already exist in the external registry.
* Validates schema (`__schema: "TinyInventory"`, `version: 1`).
* Restores normal slots and special slots.
โ ๏ธ Throws if validation fails or schema is invalid.
๐ Returns:
* A populated `TinyInventory` instance.
### ๐ `static fromJSON(json)`
Rebuilds a `TinyInventory` from a JSON string produced by `toJSON()`.
๐ Returns:
* A populated `TinyInventory` instance.