/** * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once #include "script/scriptcontext.h" #include "item/inventory.h" #include "item/backpack.h" int moduleInventoryItemExists(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Expect inventory pointer and item ID if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventoryItemExists: Expected inventory pointer as first argument"); return 0; } if(!lua_isinteger(L, 2)) { luaL_error(L, "inventoryItemExists: Expected item ID as second argument"); return 0; } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); itemid_t item = (itemid_t)lua_tointeger(L, 2); assertNotNull(inventory, "Inventory pointer cannot be NULL."); // Error if item is ITEM_ID_NULL if(item == ITEM_ID_NULL) { luaL_error(L, "inventoryItemExists: Item ID cannot be ITEM_ID_NULL"); return 0; } bool_t hasItem = inventoryItemExists(inventory, item); lua_pushboolean(L, hasItem); return 1; } int moduleInventorySet(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Requires inventory pointer, item ID and quantity (uint8_t) if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventorySet: Expected inventory pointer as first argument"); return 0; } if(!lua_isinteger(L, 2)) { luaL_error(L, "inventorySet: Expected item ID as second argument"); return 0; } if(!lua_isinteger(L, 3)) { luaL_error(L, "inventorySet: Expected quantity as third argument"); return 0; } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); itemid_t item = (itemid_t)lua_tointeger(L, 2); uint8_t quantity = (uint8_t)lua_tointeger(L, 3); assertNotNull(inventory, "Inventory pointer cannot be NULL."); inventorySet(inventory, item, quantity); return 0; } int moduleInventoryAdd(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Requires inventory pointer, item ID and quantity (uint8_t) if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventoryAdd: Expected inventory pointer as first argument"); return 0; } if(!lua_isinteger(L, 2)) { luaL_error(L, "inventoryAdd: Expected item ID as second argument"); return 0; } if(!lua_isinteger(L, 3)) { luaL_error(L, "inventoryAdd: Expected quantity as third argument"); return 0; } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); itemid_t item = (itemid_t)lua_tointeger(L, 2); uint8_t quantity = (uint8_t)lua_tointeger(L, 3); assertNotNull(inventory, "Inventory pointer cannot be NULL."); inventoryAdd(inventory, item, quantity); return 0; } int moduleInventoryRemove(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Requires inventory pointer and item ID if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventoryRemove: Expected inventory pointer as first argument"); return 0; } if(!lua_isinteger(L, 2)) { luaL_error(L, "inventoryRemove: Expected item ID as second argument"); return 0; } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); itemid_t item = (itemid_t)lua_tointeger(L, 2); assertNotNull(inventory, "Inventory pointer cannot be NULL."); // if there is a third argument (quantity), then we are actually doing a // partial removal. if(lua_gettop(L) >= 3) { if(!lua_isinteger(L, 3)) { luaL_error(L, "inventoryRemove: Expected quantity as third argument"); return 0; } uint8_t amount = (uint8_t)lua_tointeger(L, 3); uint8_t currentQuantity = inventoryGetCount(inventory, item); if(amount >= currentQuantity) { // Remove entire stack inventoryRemove(inventory, item); return 0; } // Set new quantity inventorySet(inventory, item, currentQuantity - amount); return 0; } inventoryRemove(inventory, item); return 0; } int moduleInventoryGetCount(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Requires inventory pointer and item ID if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventoryGetCount: Expected inventory pointer as first argument"); return 0; } if(!lua_isinteger(L, 2)) { luaL_error(L, "inventoryGetCount: Expected item ID as second argument"); return 0; } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); itemid_t item = (itemid_t)lua_tointeger(L, 2); assertNotNull(inventory, "Inventory pointer cannot be NULL."); uint8_t count = inventoryGetCount(inventory, item); lua_pushinteger(L, count); return 1; } int moduleInventoryIsFull(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Requires inventory pointer if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventoryIsFull: Expected inventory pointer as first argument"); return 0; } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); assertNotNull(inventory, "Inventory pointer cannot be NULL."); bool_t isFull = inventoryIsFull(inventory); lua_pushboolean(L, isFull); return 1; } int moduleInventoryItemFull(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Requires inventory pointer and item ID if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventoryItemFull: Expected inventory pointer as first argument"); return 0; } if(!lua_isinteger(L, 2)) { luaL_error(L, "inventoryItemFull: Expected item ID as second argument"); return 0; } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); itemid_t item = (itemid_t)lua_tointeger(L, 2); assertNotNull(inventory, "Inventory pointer cannot be NULL."); bool_t isFull = inventoryItemFull(inventory, item); lua_pushboolean(L, isFull); return 1; } int moduleInventorySort(lua_State *L) { assertNotNull(L, "Lua state cannot be NULL"); // Requires inventory pointer, sort type and reverse flag if(!lua_islightuserdata(L, 1)) { luaL_error(L, "inventorySort: Expected inventory pointer as first argument"); return 0; } if(!lua_isinteger(L, 2)) { luaL_error(L, "inventorySort: Expected sort type as second argument"); return 0; } // Optional, reverse bool_t reverse = false; if(lua_gettop(L) >= 3) { if(!lua_isboolean(L, 3)) { luaL_error(L, "inventorySort: Expected reverse flag as third argument"); return 0; } reverse = (bool_t)lua_toboolean(L, 3); } inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); inventorysort_t sortBy = (inventorysort_t)lua_tointeger(L, 2); assertNotNull(inventory, "Inventory pointer cannot be NULL."); inventorySort(inventory, sortBy, reverse); return 0; } void moduleItem(scriptcontext_t *context) { assertNotNull(context, "Script context cannot be NULL"); // Item information // Bind BACKPACK const pointer scriptContextRegPointer(context, "BACKPACK", (void *)&BACKPACK); // Bind Methods scriptContextRegFunc( context, "inventoryItemExists", moduleInventoryItemExists ); scriptContextRegFunc(context, "inventoryAdd", moduleInventoryAdd); scriptContextRegFunc(context, "inventorySet", moduleInventorySet); scriptContextRegFunc(context, "inventoryRemove", moduleInventoryRemove); scriptContextRegFunc(context, "inventoryGetCount", moduleInventoryGetCount); scriptContextRegFunc(context, "inventoryIsFull", moduleInventoryIsFull); scriptContextRegFunc(context, "inventoryItemFull", moduleInventoryItemFull); scriptContextRegFunc(context, "inventorySort", moduleInventorySort); }