diff --git a/README.md b/README.md index 2212f4b..096947c 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ For custom logic, you can define functions in `eventHooks.lua`, hooks define event hook functions to be executed when their respective event happens. Use this when you need additional functional (such as posting to webhooks) when the shop starts, a purchase happens or fails, an error occurs, and other events. +**IMPORTANT:** If you modify products' predicates in code (in event hooks), call `ScanInventory.clearNbtCache` as products cache which item nbt hashes match the predicates. + # Layouts Radon has support for custom layouts in lua. While shops like Xenon are easier to configure, Radon offers a lot of flexibility, you get to write the code that renders the layout. diff --git a/core/ShopState.lua b/core/ShopState.lua index 313545c..b1c1c95 100644 --- a/core/ShopState.lua +++ b/core/ShopState.lua @@ -298,6 +298,7 @@ self.currencies = {} self.kryptonListeners = {} self:setupKrypton() + ScanInventory.clearNbtCache() parallel.waitForAny(function() while true do local event, transactionEvent = os.pullEvent("transaction") diff --git a/core/inventory/ScanInventory.lua b/core/inventory/ScanInventory.lua index 9de2271..4750319 100644 --- a/core/inventory/ScanInventory.lua +++ b/core/inventory/ScanInventory.lua @@ -1,6 +1,7 @@ local eventHook = require("util.eventHook") local itemCache = {} +local nbtHashCache = {} local partialObjectMatches local function partialArrayMatches(partialArray, array) @@ -55,12 +56,30 @@ local matchingProducts = {} for i = 1, #products do local product = products[i] + if product.predicates and not product.predicatesString then + product.predicatesString = textutils.serialize(product.predicates) + end if item.name == product.modid then - if not product.predicates or predicateMatches(product.predicates, item, true) then - table.insert(matchingProducts, product) + if product.predicates and item.nbt and nbtHashCache[item.name .. "." .. item.nbt] then + for j = 1, #nbtHashCache[item.name .. "." .. item.nbt] do + if nbtHashCache[item.name .. "." .. item.nbt][j] == product.predicatesString then + table.insert(matchingProducts, product) + break + end + end + else + if not product.predicates or predicateMatches(product.predicates, item, true) then + table.insert(matchingProducts, product) + end end end end + if item.nbt and not nbtHashCache[item.name .. "." .. item.nbt] then + nbtHashCache[item.name .. "." .. item.nbt] = {} + for i = 1, #matchingProducts do + table.insert(nbtHashCache[item.name .. "." .. item.nbt], matchingProducts[i].predicatesString) + end + end return matchingProducts end @@ -139,6 +158,7 @@ itemCache = items for i = 1, #products do local product = products[i] + product.predicatesString = nil product.quantity = product.newQty if product.bundle and #product.bundle > 0 then if not product.modid then @@ -216,11 +236,19 @@ items = getItemCache() sources, amount = findProductItemsFrom(product, quantity, items) end + for i = 1, #products do + products[i].predicatesString = nil + end return sources, amount end +function clearNbtCache() + nbtHashCache = {} +end + return { updateProductInventory = updateProductInventory, getItemCache = getItemCache, - findProductItems = findProductItems + findProductItems = findProductItems, + clearNbtCache = clearNbtCache } \ No newline at end of file diff --git a/radon.lua b/radon.lua index 9b1f50d..648d5b9 100644 --- a/radon.lua +++ b/radon.lua @@ -1,6 +1,7 @@ -local version = "1.3.22" +local version = "1.3.23" local configHelpers = require "util.configHelpers" local schemas = require "core.schemas" +local ScanInventory = require("core.inventory.ScanInventory") local oldPullEvent = os.pullEvent os.pullEvent = os.pullEventRaw local oldPrint = print @@ -323,6 +324,7 @@ if (not props.terminalState.configErrors or #props.terminalState.configErrors == 0) and (not props.terminalState.productsErrors or #props.terminalState.productsErrors == 0) then props.configState.config.ready = true end + ScanInventory.clearNbtCache() local f = fs.open("products.lua", "w") f.write("return " .. textutils.serialize(newConfig)) f.close()