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.
1 lines • 22.3 kB
JavaScript
(()=>{"use strict";var t={d:(e,i)=>{for(var r in i)t.o(i,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:i[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};t.d(e,{TinyInventory:()=>r});class i{static#t=new Map;static get itemRegistry(){const t={},e=Object.fromEntries(i.#t);for(const i in e)t[i]={...e[i],metadata:{...e[i].metadata}};return t}static defineItem(t){if(!t||"object"!=typeof t)throw new TypeError("Config must be a valid object.");if(!t.id||"string"!=typeof t.id)throw new TypeError("Item must have a valid string 'id'.");if(void 0!==t.weight&&("number"!=typeof t.weight||t.weight<0))throw new TypeError(`weight must be a number >= 0. Received: ${t.weight}`);if(void 0!==t.maxStack&&(!Number.isInteger(t.maxStack)||t.maxStack<=0))throw new TypeError(`maxStack must be a positive integer. Received: ${t.maxStack}`);if(void 0!==t.metadata&&"object"!=typeof t.metadata)throw new TypeError("metadata must be an object.");if(void 0!==t.onUse&&null!==t.onUse&&"function"!=typeof t.onUse)throw new TypeError("onUse must be a function or null.");if(void 0!==t.type&&null!==t.type&&"string"!=typeof t.type)throw new TypeError("type must be a string or null.");i.#t.set(t.id,{id:t.id,weight:t.weight||0,maxStack:t.maxStack||1,metadata:t.metadata||{},type:t.type??null,onUse:"function"==typeof t.onUse?t.onUse:null})}static removeItem(t){if("string"!=typeof t)throw new TypeError("itemId must be a string.");return i.#t.delete(t)}static hasItem(t){if("string"!=typeof t)throw new TypeError("itemId must be a string.");return i.#t.has(t)}static getItem(t){if("string"!=typeof t)throw new TypeError("itemId must be a string.");const e=i.#t.get(t);if(!e)throw new Error(`Item '${t}' not defined in registry.`);return e}#e=new Map;#i={add:[],remove:[],use:[],set:[]};#r=[];#o;#n;#s;#a;get maxStack(){return this.#o}set maxStack(t){if(!Number.isInteger(t)||Number.isFinite(t)&&t<=0)throw new TypeError(`maxStack must be a positive integer. Received: ${t}`);this.#o=t}get maxSize(){return this.#n}set maxSize(t){if(null!==t&&(!Number.isInteger(t)||t<=0))throw new TypeError(`maxSize must be null or a positive integer. Received: ${t}`);this.#n=t}get maxSlots(){return this.#s}set maxSlots(t){if(null!==t&&(!Number.isInteger(t)||t<=0))throw new TypeError(`maxSlots must be null or a positive integer. Received: ${t}`);this.#s=t}get maxWeight(){return this.#a}set maxWeight(t){if(null!==t&&("number"!=typeof t||t<=0))throw new TypeError(`maxWeight must be null or a positive number. Received: ${t}`);this.#a=t}get events(){return{add:[...this.#i.add],remove:[...this.#i.remove],use:[...this.#i.use],set:[...this.#i.set]}}get items(){return[...this.#r].map(t=>t?this.#l(t):null)}get specialSlots(){return new Map([...this.#e.entries()].map(([t,e])=>[t,{type:e.type,item:e.item?this.#l(e.item):null}]))}get size(){const t=this.getAllItems();let e=0;for(const i of t)e+=i.quantity;return e}get slotsSize(){return this.getAllItems().length}get weight(){return this.getAllItems().reduce((t,e)=>{const r=i.getItem(e.id);return t+(r?.weight||0)*e.quantity},0)}_cleanNulls(){let t=this.#r.length-1;for(;t>=0&&null===this.#r[t];)t--;this.#r=this.#r.slice(0,t+1)}constructor(t={}){if("object"!=typeof t||null===t)throw new TypeError("`options` must be an object.");if(void 0!==t.maxWeight&&null!==t.maxWeight&&"number"!=typeof t.maxWeight)throw new TypeError("`maxWeight` must be a number or null.");if(void 0!==t.maxSlots&&null!==t.maxSlots&&"number"!=typeof t.maxSlots)throw new TypeError("`maxSlots` must be a number or null.");if(void 0!==t.maxSize&&null!==t.maxSize&&"number"!=typeof t.maxSize)throw new TypeError("`maxSize` must be a number or null.");if(void 0!==t.maxStack&&"number"!=typeof t.maxStack)throw new TypeError("`maxStack` must be a number.");if(void 0!==t.specialSlots&&"object"!=typeof t.specialSlots)throw new TypeError("`specialSlots` must be an object if defined.");if(this.#a=t.maxWeight??null,this.#s=t.maxSlots??null,this.#n=t.maxSize??null,this.#o=t.maxStack??1/0,t.specialSlots)for(const e in t.specialSlots){const i=t.specialSlots[e];if("object"!=typeof i||null===i)throw new TypeError("Each `specialSlot` entry must be an object.");if(void 0!==i.type&&null!==i.type&&"string"!=typeof i.type)throw new TypeError("`specialSlot.type` must be a string or null.");this.#e.set(e,{type:i.type??null,item:null})}}hasSpace({weight:t=0,sizeLength:e=0,slotsLength:i=0}={}){if("number"!=typeof t)throw new TypeError("`weight` must be a number.");if("number"!=typeof e)throw new TypeError("`sizeLength` must be a number.");if("number"!=typeof i)throw new TypeError("`slotsLength` must be a number.");return!(this.areFull(e)||this.areFullSlots(i)||this.isHeavy(t))}isHeavy(t=0){if("number"!=typeof t)throw new TypeError("`extraWeight` must be a number.");return null!==this.#a&&this.weight+t>this.#a}areFull(t=0){if("number"!=typeof t)throw new TypeError("`extraLength` must be a number.");return null!==this.#n&&this.size+t>this.#n}isFull(t=0){if("number"!=typeof t)throw new TypeError("`extraLength` must be a number.");return null!==this.#n&&this.size+t>=this.#n}areFullSlots(t=0){if("number"!=typeof t)throw new TypeError("`extraLength` must be a number.");return null!==this.#s&&this.slotsSize+t>this.#s}isFullSlots(t=0){if("number"!=typeof t)throw new TypeError("`extraLength` must be a number.");return null!==this.#s&&this.slotsSize+t>=this.#s}#m(t,e){if("string"!=typeof t)throw new TypeError("`type` must be a string.");if("object"!=typeof e||null===e)throw new TypeError("`payload` must be an object.");if(this.#i[t])for(const i of this.#i[t])i(e)}off(t,e){if("string"!=typeof t)throw new TypeError("`eventType` must be a string.");if("function"!=typeof e)throw new TypeError("`callback` must be a function.");if(!this.#i[t])return;const i=this.#i[t],r=i.indexOf(e);-1!==r&&i.splice(r,1)}offAll(t){if("string"!=typeof t)throw new TypeError("`eventType` must be a string.");this.#i[t]&&(this.#i[t]=[])}cloneEventCallbacks(t){if("string"!=typeof t)throw new TypeError("`eventType` must be a string.");return this.#i[t]?[...this.#i[t]]:[]}onAddItem(t){if("function"!=typeof t)throw new TypeError("`callback` must be a function.");this.#i.add.push(t)}onSetItem(t){if("function"!=typeof t)throw new TypeError("`callback` must be a function.");this.#i.set.push(t)}onRemoveItem(t){if("function"!=typeof t)throw new TypeError("`callback` must be a function.");this.#i.remove.push(t)}onUseItem(t){if("function"!=typeof t)throw new TypeError("`callback` must be a function.");this.#i.use.push(t)}compactInventory(){this.#r=this.#r.filter((t,e)=>{const i=null!==t;return i||this.#m("remove",{index:e,item:null,isCollection:!0,specialSlot:null,remove:()=>{}}),i})}addItem({itemId:t,quantity:e=1,metadata:r={},forceSpace:o=!1}){if("string"!=typeof t)throw new TypeError("`itemId` must be a string.");if("number"!=typeof e||!Number.isFinite(e)||e<=0)throw new TypeError("`quantity` must be a positive number.");if("object"!=typeof r||null===r)throw new TypeError("`metadata` must be an object.");if("boolean"!=typeof o)throw new TypeError("`forceSpace` must be a boolean.");const n=i.getItem(t);let s=e;const a=n.maxStack<=this.#o?n.maxStack:this.#o,l=[],m=(t,e)=>JSON.stringify(t)===JSON.stringify(e);let u=!0;for(;s>0&&u;){u=!1;for(const e in this.#r){const i=this.#r[e];if(i&&i.id===t&&i.quantity<a&&m(i.metadata,r)){const t=Math.min(a-i.quantity,s);if(!o&&!this.hasSpace({weight:n.weight*t,sizeLength:t}))continue;i.quantity+=t,s-=t,u=!0;const r=Number(e),m=l.findIndex(t=>t.index===r);if(m<0?l.push({index:r,quantity:t}):l[m].quantity+=t,this.#m("add",{item:this.#l(i),index:r,isCollection:!0,specialSlot:null,remove:this.#u({locationType:"normal",slotIndex:r,forceSpace:o,item:i})}),s<=0)break}}}if(s>0)for(const e in this.#r)if(null===this.#r[e]){const i=Math.min(a,s);if(!o&&!this.hasSpace({weight:n.weight*i,sizeLength:i}))continue;const m={id:t,quantity:i,metadata:r};this.#r[e]=m,s-=i;const u=Number(e),c=l.findIndex(t=>t.index===u);if(c<0?l.push({index:u,quantity:i}):l[c].quantity+=i,this.#m("add",{item:this.#l(m),index:u,isCollection:!0,specialSlot:null,remove:this.#u({locationType:"normal",slotIndex:u,forceSpace:o,item:m})}),s<=0)break}for(;s>0;){const e=Math.min(a,s);if(!o&&!this.hasSpace({weight:n.weight*e,sizeLength:e,slotsLength:1}))break;const i={id:t,quantity:e,metadata:r};this.#r.push(i);const m=this.#r.length-1,u=l.findIndex(t=>t.index===m);u<0?l.push({index:m,quantity:e}):l[u].quantity+=e,this.#m("add",{item:this.#l(i),index:m,isCollection:!0,specialSlot:null,remove:this.#u({locationType:"normal",slotIndex:m,forceSpace:o,item:i})}),s-=e}return{remaining:s,placesAdded:l}}getItemFrom(t){if("number"!=typeof t||!Number.isInteger(t))throw new TypeError("`slotIndex` must be an integer.");if(t<0||t>=this.#r.length)throw new Error(`Slot index '${t}' out of bounds .`);return this.#r[t]?this.#l(this.#r[t]):null}setItem({slotIndex:t,item:e,forceSpace:r=!1}){if("number"!=typeof t||!Number.isInteger(t))throw new TypeError("`slotIndex` must be an integer.");if("boolean"!=typeof r)throw new TypeError("`forceSpace` must be a boolean.");const o=e&&"object"==typeof e&&"string"==typeof e.id&&"number"==typeof e.quantity&&!Number.isNaN(e.quantity)&&Number.isFinite(e.quantity)&&e.quantity>-1&&"object"==typeof e.metadata;if(null!==e&&!o)throw new Error("Invalid item type: must be null or a valid InventoryItem.");const n=e?i.#t.get(e.id):null;if(null!==e&&!n)throw new Error(`Item '${e?.id??"unknown"}' not defined in registry.`);if(n&&e){const t=n.maxStack<=this.#o?n.maxStack:this.#o;if(e.quantity>t)throw new Error(`Item '${e.id}' exceeds max stack size. Allowed: ${t}, got: ${e.quantity}.`)}if(null!==this.#s&&(t<0||t>=this.#s))throw new Error(`Slot index ${t} out of range.`);const s=this.#r[t]??null,a=s?i.#t.get(s.id)??null:null,l=(t,e)=>e?e.weight*(t?t.quantity:0):0,m=t=>t?t.quantity:0;if(!r&&!this.hasSpace({weight:l(e,n)-l(s,a),sizeLength:m(e)-m(s)}))throw new Error("Inventory is full or overweight.");for(;this.#r.length<=t;)this.#r.push(null);this.#r[t]=e,this._cleanNulls(),this.#m("set",{index:t,isCollection:!0,item:e?this.#l(e):null,specialSlot:null,remove:e?this.#u({locationType:"normal",slotIndex:t,forceSpace:r,item:e}):()=>{}})}deleteItem(t,e=!1){if("number"!=typeof t||!Number.isInteger(t))throw new TypeError("`slotIndex` must be an integer.");if("boolean"!=typeof e)throw new TypeError("`forceSpace` must be a boolean.");this.setItem({slotIndex:t,item:null,forceSpace:e})}moveItem(t,e,i=!1){if("number"!=typeof t||!Number.isInteger(t))throw new TypeError("`fromIndex` must be an integer.");if("number"!=typeof e||!Number.isInteger(e))throw new TypeError("`toIndex` must be an integer.");if("boolean"!=typeof i)throw new TypeError("`forceSpace` must be a boolean.");const r=this.#r[t];if(!r)throw new Error(`No item found in slot ${t}.`);this.setItem({slotIndex:e,item:r,forceSpace:i}),this.setItem({slotIndex:t,item:null,forceSpace:i})}removeItem({itemId:t,metadata:e=null,quantity:i=1}){if("string"!=typeof t)throw new TypeError("`itemId` must be a string.");if(null!==e&&"object"!=typeof e)throw new TypeError("`metadata` must be an object or null.");if("number"!=typeof i||!Number.isFinite(i)||i<=0)throw new TypeError("`quantity` must be a positive number.");let r=i;const o=(t,e)=>JSON.stringify(t)===JSON.stringify(e);for(let i=0;i<this.#r.length;i++){const n=this.#r[i];if(n&&n.id===t&&(null===e||o(n.metadata,e))){const t=Math.min(n.quantity,r);n.quantity-=t,r-=t;const e=Number(i);if(n.quantity<=0&&(this.#r[i]=null),r<=0)return this._cleanNulls(),this.#m("remove",{index:e,item:this.#l(n),isCollection:!0,specialSlot:null,remove:this.#u({locationType:"normal",slotIndex:e,item:n})}),!0}}return this._cleanNulls(),this.#e.forEach((i,n)=>{if(r>0&&i.item&&i.item.id===t&&(null===e||o(i.item.metadata,e))){const t=Math.min(i.item.quantity,r);i.item.quantity-=t,i.item.quantity<0&&(i.item.quantity=0),r-=t,i.item.quantity<=0&&(i.item=null),this.#e.set(n,i),this.#m("remove",{index:null,item:i.item?this.#l(i.item):null,isCollection:!1,specialSlot:n,remove:i.item?this.#u({locationType:"special",specialSlot:n,item:i.item}):()=>{}})}}),r<=0}#u({locationType:t,specialSlot:e,slotIndex:i,item:r,forceSpace:o=!1}){if("normal"!==t&&"special"!==t)throw new TypeError("`locationType` must be 'normal' or 'special'.");if("boolean"!=typeof o)throw new TypeError("`forceSpace` must be boolean.");if(!r||"object"!=typeof r)throw new TypeError("`item` must be an InventoryItem object.");if("special"===t&&e&&"string"!=typeof e)throw new TypeError("`specialSlot` must be a string when locationType is 'special'.");if("normal"===t&&"number"!=typeof i)throw new TypeError("`slotIndex` must be a number when locationType is 'normal'.");return(n=o)=>{if("special"===t&&e){const t=this.#e.get(e);if(!t?.item)throw new Error(`Special slot '${e}' is empty.`);t.item.quantity>1?(t.item.quantity-=1,this.#e.set(e,t)):this.setSpecialSlot({slotId:e,item:null,forceSpace:n})}else{if("number"!=typeof i)throw new Error("Invalid remove operation: no valid slotIndex or specialSlot provided.");r.quantity>1?this.setItem({slotIndex:i,item:{...r,quantity:r.quantity-1},forceSpace:n}):this.setItem({slotIndex:i,item:null,forceSpace:n})}}}useItem({slotIndex:t,specialSlot:e,forceSpace:r=!1},...o){if(void 0!==t&&("number"!=typeof t||!Number.isInteger(t)))throw new TypeError("`slotIndex` must be an integer if provided.");if(void 0!==e&&"string"!=typeof e)throw new TypeError("`specialSlot` must be a string if provided.");if("boolean"!=typeof r)throw new TypeError("`forceSpace` must be boolean.");let n=null,s="normal",a=null;if(e){if(!this.#e.has(e))throw new Error(`Special slot '${e}' not found.`);n=this.#e.get(e).item,s="special"}else a=this.#r,n=a[t??-1]??null,s="normal";if(!n)throw new Error("special"===s?`No item found in special slot '${e}'.`:`No item found in slot ${t} of inventory.`);const l=i.getItem(n.id);if(l.onUse){const i={inventory:this,item:this.#l(n),index:t??null,specialSlot:e??null,isCollection:!!a,itemDef:l,remove:this.#u({locationType:s,specialSlot:e,slotIndex:t,forceSpace:r,item:n}),...o},m=l.onUse(i);return this.#m("use",i),m}return null}hasSpecialSlot(t){if("string"!=typeof t)throw new TypeError("`slotId` must be a string.");return this.#e.has(t)}getSpecialItem(t){if("string"!=typeof t)throw new TypeError("`slotId` must be a string.");if(!this.#e.has(t))throw new Error(`Special slot '${t}' does not exist.`);const e=this.#e.get(t);return e?.item?this.#l(e.item):null}getSpecialSlotType(t){if("string"!=typeof t)throw new TypeError("`slotId` must be a string.");if(!this.#e.has(t))throw new Error(`Special slot '${t}' does not exist.`);const e=this.#e.get(t);return e?.type??null}setSpecialSlot({slotId:t,item:e,forceSpace:r=!1}){if("string"!=typeof t)throw new TypeError("`slotId` must be a string.");if("boolean"!=typeof r)throw new TypeError("`forceSpace` must be boolean.");if(!this.#e.has(t))throw new Error(`Special slot '${t}' not found.`);const o=e&&"object"==typeof e&&"string"==typeof e.id&&"number"==typeof e.quantity&&!Number.isNaN(e.quantity)&&Number.isFinite(e.quantity)&&e.quantity>-1&&"object"==typeof e.metadata;if(null!==e&&!o)throw new Error("Invalid item type: must be null or a valid InventoryItem.");const n=e?i.#t.get(e.id):null;if(null!==e&&!n)throw new Error(`Item '${e?.id??"unknown"}' not defined in registry.`);const s=this.#e.get(t);if(!s)throw new Error(`Special slot ${t} out of range for slot '${t}'.`);const a=s.item?i.#t.get(s.item.id):null,l=(t,e)=>e?e.weight*(t?1:0):0,m=t=>t?1:0;if(!r&&!this.hasSpace({weight:l(e,n)-l(s.item,a),sizeLength:m(e)-m(s.item)}))throw new Error("Inventory is full or overweight.");s.item=e,this.#m("set",{index:null,item:e?this.#l(e):null,isCollection:!1,specialSlot:t,remove:e?this.#u({locationType:"special",specialSlot:t,forceSpace:r,item:e}):()=>{}})}deleteSpecialItem(t,e=!1){if("string"!=typeof t)throw new TypeError("`slotId` must be a string.");if("boolean"!=typeof e)throw new TypeError("`forceSpace` must be boolean.");this.setSpecialSlot({slotId:t,item:null,forceSpace:e})}equipItem({slotId:t,slotIndex:e,quantity:r=1,forceSpace:o=!1}){if("string"!=typeof t)throw new TypeError("`slotId` must be a string.");if("number"!=typeof e||!Number.isInteger(e))throw new TypeError("`slotIndex` must be an integer.");if("number"!=typeof r||!Number.isFinite(r)||r<=0)throw new TypeError("`quantity` must be a positive number.");if("boolean"!=typeof o)throw new TypeError("`forceSpace` must be boolean.");if(r<=0||!Number.isFinite(r))throw new Error(`Invalid quantity '${r}'.`);if(!this.#e.has(t))throw new Error(`Special slot '${t}' does not exist.`);const n=this.getItemFrom(e);if(!n)throw new Error(`No item found in inventory slot ${e}.`);if(n.quantity<r)throw new Error(`Not enough quantity of item '${n.id}' in inventory slot.`);const s=i.getItem(n.id),a=this.#e.get(t);if(!a)throw new Error(`Slot '${t}' not defined in registry.`);const l=a.type??null;if(null!==l&&s.type!==l)throw new Error(`Item '${n.id}' cannot be equipped in slot '${t}'.`);const m=Math.min(s.maxStack,this.#o);if(a.item&&a.item.id===n.id){const e=Math.max(0,m-a.item.quantity);if(e<=0)return r;const i=Math.min(r,e);return this.removeItem({itemId:n.id,quantity:i,metadata:null}),a.item.quantity+=i,this.#e.set(t,a),r-i}a.item&&this.unequipItem({slotId:t,forceSpace:o});const u=Math.min(r,m);return this.removeItem({itemId:n.id,quantity:u,metadata:null}),a.item={id:n.id,quantity:u,metadata:n.metadata},this.#e.set(t,a),r-u}unequipItem({slotId:t,quantity:e=null,forceSpace:i=!1}){if("string"!=typeof t)throw new TypeError("`slotId` must be a string.");if(null!==e&&("number"!=typeof e||!Number.isFinite(e)||e<=0))throw new TypeError("`quantity` must be a positive number or null.");if("boolean"!=typeof i)throw new TypeError("`forceSpace` must be boolean.");if(!this.#e.has(t))throw new Error(`Special slot '${t}' does not exist.`);const r=this.#e.get(t);if(!r)throw new Error(`Slot '${t}' not defined in registry.`);if(!r.item)return!1;const o=r.item,n=null===e?o.quantity:e;if(n<=0)throw new Error(`Invalid unequip quantity: ${n}`);if(n>o.quantity)throw new Error(`Not enough items in slot '${t}' to unequip.`);return this.addItem({itemId:o.id,quantity:n,metadata:o.metadata,forceSpace:i}),n===o.quantity?r.item=null:(o.quantity-=n,r.item=o),this.#e.set(t,r),!0}#l(t){if(!t||"object"!=typeof t)throw new TypeError("`item` must be an InventoryItem object.");if("string"!=typeof t.id)throw new TypeError("`item.id` must be a string.");if("number"!=typeof t.quantity||!Number.isFinite(t.quantity))throw new TypeError("`item.quantity` must be a finite number.");if(!t.metadata||"object"!=typeof t.metadata)throw new TypeError("`item.metadata` must be an object.");return{id:t.id,quantity:t.quantity,metadata:{...t.metadata}}}getItemList(){return[...this.#r].map((t,e)=>[t?this.#l(t):null,e]).filter(t=>null!==t[0])}getAllItems(){const t=[...this.#r].filter(t=>null!==t).map(this.#l);return this.#e.forEach(e=>{const i=e.item;i&&t.push(i)}),t}getItemsByMetadata(t){if("function"!=typeof t)throw new TypeError("`filterFn` must be a function.");return this.getAllItems().filter(e=>{const r=i.getItem(e.id);return t(r.metadata,e)})}findItem(t){if("function"!=typeof t)throw new TypeError("`predicate` must be a function.");return this.getAllItems().find(t)}findItems(t){if("function"!=typeof t)throw new TypeError("`predicate` must be a function.");return this.getAllItems().filter(t)}getItemCount(t){if("string"!=typeof t)throw new TypeError("`itemId` must be a string.");return this.getAllItems().filter(e=>e.id===t).reduce((t,e)=>t+e.quantity,0)}hasItem(t,e=1){if("string"!=typeof t)throw new TypeError("`itemId` must be a string.");if("number"!=typeof e||!Number.isFinite(e)||e<0)throw new TypeError("`quantity` must be a non-negative number.");return this.getItemCount(t)>=e}existsItemAt(t){if("number"!=typeof t||!Number.isInteger(t))throw new TypeError("`slotIndex` must be an integer.");return!!this.#r[t]}clear(){this.clearAllItems(),this.clearAllEvents()}clearAllEvents(){this.#i={add:[],remove:[],use:[],set:[]}}clearAllItems(){this.clearItems(),this.clearSpecialItems()}clearItems(){for(let t=this.#r.length-1;t>=0;t--)this.#r[t]&&this.deleteItem(t,!0)}clearSpecialItems(){for(const t of this.#e.keys()){const e=this.#e.get(t);e?.item&&this.deleteSpecialItem(t,!0)}}clone(){const t=this.toObject();return i.fromObject(t)}toObject(){const t={};for(const[e,i]of this.#e.entries())t[e]={type:i?.type??null,item:i?.item?this.#l(i.item):null};return{__schema:"TinyInventory",version:1,maxWeight:this.#a,maxSlots:this.#s,maxSize:this.#n,maxStack:this.#o,items:this.#r.map(t=>t?this.#l(t):null),specialSlots:t}}toJSON(t=0){if("number"!=typeof t||!Number.isFinite(t)||t<0)throw new TypeError("`space` must be a non-negative number.");return JSON.stringify(this.toObject(),null,t)}static fromObject(t){if(!t||"object"!=typeof t)throw new TypeError("Invalid state: expected object.");if("TinyInventory"!==t.__schema||"number"!=typeof t.version)throw new TypeError("Invalid or missing schema header.");if(1!==t.version)throw new TypeError(`Unsupported TinyInventory state version: ${t.version}`);const e={};if(t.specialSlots&&"object"==typeof t.specialSlots)for(const i of Object.keys(t.specialSlots))e[i]={type:t.specialSlots[i]?.type??null};const r=new i({maxWeight:t.maxWeight??null,maxSlots:t.maxSlots??null,maxSize:t.maxSize??null,maxStack:t.maxStack??null,specialSlots:e});if(Array.isArray(t.items))for(const e in t.items){const i=t.items[e];if(null!==i){const t={id:String(i.id),quantity:Math.max(1,Number(i.quantity)||1),metadata:i.metadata&&"object"==typeof i.metadata?i.metadata:{}};r.setItem({slotIndex:Number(e),item:t,forceSpace:!0})}else r.setItem({slotIndex:Number(e),item:null,forceSpace:!0})}if(t.specialSlots&&"object"==typeof t.specialSlots)for(const[e,i]of Object.entries(t.specialSlots)){if(!r.hasSpecialSlot(e))continue;const t=i?.item;if(t&&t.id){const i={id:String(t.id),quantity:Math.max(1,Number(t.quantity)||1),metadata:t.metadata&&"object"==typeof t.metadata?t.metadata:{}};r.setSpecialSlot({slotId:e,item:i,forceSpace:!0})}}return r}static fromJSON(t){if("string"!=typeof t)throw new TypeError("`json` must be a string.");const e=JSON.parse(t);return i.fromObject(e)}}const r=i;window.TinyInventory=e.TinyInventory})();