UNPKG

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
# ๐Ÿ“ฆ 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.