diff --git a/README.md b/README.md index 871f295..b709233 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Attach a wired modem to your turtle. Then add a chest on that wired network (it must be connected to a wired modem on that network). Make sure a monitor is next to the turtle. -Open `config.lua` and change `branding.title` to the name of your shop you want shown in the header. +Either use the ingame GUI editor on an advanced computer/turtle, or edit `config.lua` and change `branding.title` to the name of your shop you want shown in the header. Next change `currencies.name`, and `currencies.pkey` for the krist currency to your krist address, the krist name you will be using (or nil), and your krist address' private key, respectively. If you are using a kristwallet format password, change `currencies.pkeyFormat` to `"kristwallet"`. You can then either remove/comment out the tenebra currency, or fill in your respective details for that. @@ -39,7 +39,8 @@ - `sounds` controls the sounds that get played in various situations - `currencies` lists the currencies accepted by the shop. If you don't have a name on a given currency, you can leave it out or set it to nil to use nameless mode. - `peripherals` defines peripherals to be used for the shop. Most of these can be left at nil to be automatically set. `peripherals.outputChest` should generally be left on `"self"` as setting it to a chest will cause items to be inserted into the chest without dropping them, as chest dropping is not yet implemented in plethora 1.19 -- `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. + +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. # Layouts diff --git a/config.lua b/config.lua index 60035eb..3e630e7 100644 --- a/config.lua +++ b/config.lua @@ -256,14 +256,6 @@ -- NOTE: Chest dropping is NYI in plethora 1.19, so do not use unless -- the output chest can be accessed }, - hooks = { - start = nil, -- function(version, config, products) - prePurchase = nil, -- function(product, amount, refundAmount, transaction, transactionCurrency) returns continueTransaction, error, errorMessage - purchase = nil, -- function(product, amount, refundAmount, transaction, transactionCurrency) - failedPurchase = nil, -- function(transaction, transactionCurrency, product, errorMessage) - programError = nil, -- function(err) - blink = nil, -- function(blinkState) called every 3 seconds while shop is running - }, exchange = { -- Not yet implemented enabled = true, diff --git a/core/ConfigValidator.lua b/core/ConfigValidator.lua index 7c422e2..981216c 100644 --- a/core/ConfigValidator.lua +++ b/core/ConfigValidator.lua @@ -235,10 +235,15 @@ return validate(products, schemas.productsSchema, "products") end +local function validateHooks(hooks) + return validate(hooks, schemas.hooksSchema, "hooks") +end + return { typeCheck = typeCheck, validate = validate, + validationArrayToMap = validationArrayToMap, validateConfig = validateConfig, validateProducts = validateProducts, - validationArrayToMap = validationArrayToMap + validateHooks = validateHooks, } \ No newline at end of file diff --git a/core/ShopState.lua b/core/ShopState.lua index afb6e2f..42343a8 100644 --- a/core/ShopState.lua +++ b/core/ShopState.lua @@ -13,7 +13,7 @@ local ShopState = {} local ShopState_mt = { __index = ShopState } -function ShopState.new(config, products, peripherals, version, logs) +function ShopState.new(config, products, peripherals, version, logs, eventHooks) local self = setmetatable({}, ShopState_mt) self.running = false @@ -30,6 +30,7 @@ self.numCategories = 1 self.productsChanged = false self.logs = logs + self.eventHooks = eventHooks self.lastTouched = os.epoch("utc") return self @@ -113,8 +114,8 @@ local allowPurchase = true local err local errMessage - if state.config.hooks and state.config.hooks.prePurchase then - allowPurchase, err, errMessage = eventHook.execute(state.config.hooks.prePurchase, purchasedProduct, available, refundAmount, transaction, transactionCurrency) + if state.eventHooks and state.eventHooks.prePurchase then + allowPurchase, err, errMessage = eventHook.execute(state.eventHooks.prePurchase, purchasedProduct, available, refundAmount, transaction, transactionCurrency) end if allowPurchase ~= false then print("Purchased " .. available .. " of " .. purchasedProduct.name .. " for " .. transaction.from .. " for " .. transaction.value .. " " .. transactionCurrency.id .. " (refund " .. refundAmount .. ")") @@ -148,37 +149,37 @@ if state.config.settings.playSounds then sound.playSound(state.peripherals.speaker, state.config.sounds.purchase) end - if state.config.hooks and state.config.hooks.purchase then - eventHook.execute(state.config.hooks.purchase, purchasedProduct, available, refundAmount, transaction, transactionCurrency) + if state.eventHooks and state.eventHooks.purchase then + eventHook.execute(state.eventHooks.purchase, purchasedProduct, available, refundAmount, transaction, transactionCurrency) end else refund(transactionCurrency, transaction.from, meta, transaction.value, errMessage or state.config.lang.refundDenied, err) - if state.config.hooks and state.config.hooks.failedPurchase then - eventHook.execute(state.config.hooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, errMessage or state.config.lang.refundDenied, err) + if state.eventHooks and state.eventHooks.failedPurchase then + eventHook.execute(state.eventHooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, errMessage or state.config.lang.refundDenied, err) end end else refund(transactionCurrency, transaction.from, meta, transaction.value, state.config.lang.refundOutOfStock) - if state.config.hooks and state.config.hooks.failedPurchase then - eventHook.execute(state.config.hooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, state.config.lang.refundOutOfStock) + if state.eventHooks and state.eventHooks.failedPurchase then + eventHook.execute(state.eventHooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, state.config.lang.refundOutOfStock) end end else refund(transactionCurrency, transaction.from, meta, transaction.value, state.config.lang.refundOutOfStock) - if state.config.hooks and state.config.hooks.failedPurchase then - eventHook.execute(state.config.hooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, state.config.lang.refundOutOfStock) + if state.eventHooks and state.eventHooks.failedPurchase then + eventHook.execute(state.eventHooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, state.config.lang.refundOutOfStock) end end else refund(transactionCurrency, transaction.from, meta, transaction.value, state.config.lang.refundAtLeastOne, true) - if state.config.hooks and state.config.hooks.failedPurchase then - eventHook.execute(state.config.hooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, state.config.lang.refundAtLeastOne) + if state.eventHooks and state.eventHooks.failedPurchase then + eventHook.execute(state.eventHooks.failedPurchase, transaction, transactionCurrency, purchasedProduct, state.config.lang.refundAtLeastOne) end end else refund(transactionCurrency, transaction.from, meta, transaction.value, state.config.lang.refundInvalidProduct, true) - if state.config.hooks and state.config.hooks.failedPurchase then - eventHook.execute(state.config.hooks.failedPurchase, transaction, transactionCurrency, nil, state.config.lang.refundInvalidProduct) + if state.eventHooks and state.eventHooks.failedPurchase then + eventHook.execute(state.eventHooks.failedPurchase, transaction, transactionCurrency, nil, state.config.lang.refundInvalidProduct) end end end @@ -269,15 +270,15 @@ -- Success :D else refund(transactionCurrency, transaction.from, meta, transaction.value, state.config.lang.refundError, true) - if state.config.hooks and state.config.hooks.failedPurchase then - eventHook.execute(state.config.hooks.failedPurchase, transaction, transactionCurrency, nil, state.config.lang.refundError) + if state.eventHooks and state.eventHooks.failedPurchase then + eventHook.execute(state.eventHooks.failedPurchase, transaction, transactionCurrency, nil, state.config.lang.refundError) end error(err) end else refund(transactionCurrency, transaction.from, meta, transaction.value, state.config.lang.refundNoProduct, true) - if state.config.hooks and state.config.hooks.failedPurchase then - eventHook.execute(state.config.hooks.failedPurchase, transaction, transactionCurrency, nil, state.config.lang.refundNoProduct) + if state.eventHooks and state.eventHooks.failedPurchase then + eventHook.execute(state.eventHooks.failedPurchase, transaction, transactionCurrency, nil, state.config.lang.refundNoProduct) end end end @@ -310,8 +311,8 @@ if state.config.peripherals.blinker then redstone.setOutput(state.config.peripherals.blinker, blinkState) end - if state.config.hooks and state.config.hooks.blink then - eventHook.execute(state.config.hooks.blink, blinkState) + if state.eventHooks and state.eventHooks.blink then + eventHook.execute(state.eventHooks.blink, blinkState) end sleep(blinkFrequency) end diff --git a/core/schemas.lua b/core/schemas.lua index f85deb9..98460ec 100644 --- a/core/schemas.lua +++ b/core/schemas.lua @@ -184,30 +184,22 @@ exchangeChest = "chest?", outputChest = "chest", }, - hooks = { - start = "function?", - prePurchase = "function?", - purchase = "function?", - failedPurchase = "function?", - programError = "function?", - blink = "function?", - }, - shopSync = { - enabled = "boolean?", - name = "string?", - description = "string?", - owner = "string?", - location = { - coordinates = { - __type = "array?", - __min = 3, - __max = 3, - __entry = "number" - }, - description = "string?", - dimension = "enum<'overworld' | 'nether' | 'end'>?: dimension" - } - }, + -- shopSync = { + -- enabled = "boolean?", + -- name = "string?", + -- description = "string?", + -- owner = "string?", + -- location = { + -- coordinates = { + -- __type = "array?", + -- __min = 3, + -- __max = 3, + -- __entry = "number" + -- }, + -- description = "string?", + -- dimension = "enum<'overworld' | 'nether' | 'end'>?: dimension" + -- } + -- }, exchange = { enabled = "boolean", node = "string" @@ -233,6 +225,15 @@ } } +local hooksSchema = { + start = "function?", + prePurchase = "function?", + purchase = "function?", + failedPurchase = "function?", + programError = "function?", + blink = "function?", +} + local soundSchema = { name = "string", volume = "number", @@ -242,5 +243,6 @@ return { configSchema = configSchema, productsSchema = productsSchema, + hooksSchema = hooksSchema, soundSchema = soundSchema } \ No newline at end of file diff --git a/eventHooks.lua b/eventHooks.lua new file mode 100644 index 0000000..3a54cae --- /dev/null +++ b/eventHooks.lua @@ -0,0 +1,8 @@ +return { + start = nil, -- function(version, config, products) + prePurchase = nil, -- function(product, amount, refundAmount, transaction, transactionCurrency) returns continueTransaction, error, errorMessage + purchase = nil, -- function(product, amount, refundAmount, transaction, transactionCurrency) + failedPurchase = nil, -- function(transaction, transactionCurrency, product, errorMessage) + programError = nil, -- function(err) + blink = nil, -- function(blinkState) called every 3 seconds while shop is running +} \ No newline at end of file diff --git a/radon.lua b/radon.lua index 0b65c27..8c7d467 100644 --- a/radon.lua +++ b/radon.lua @@ -58,6 +58,10 @@ local configDefaults = require("configDefaults") local config = require("config") local products = require("products") +local eventHooks = {} +if fs.exists(fs.combine(fs.getDir(shell.getRunningProgram()), "eventHooks.lua")) then + eventHooks = require("eventHooks") +end --- End Imports configHelpers.loadDefaults(config, configDefaults) @@ -85,6 +89,7 @@ local configState = { config = config, products = products, + eventHooks = eventHooks, } local Main = Solyd.wrapComponent("Main", function(props) @@ -407,7 +412,7 @@ lastCanvas.hash = newCanvasHash end -local shopState = Core.ShopState.new(config, products, peripherals, version, logs) +local shopState = Core.ShopState.new(config, products, peripherals, version, logs, eventHooks) local Profiler = require("profile") @@ -416,8 +421,8 @@ local success, err = pcall(function() ShopRunner.launchShop(shopState, function() -- Profiler:activate() print("Radon " .. version .. " started") - if config.hooks and config.hooks.start then - eventHook.execute(config.hooks.start, version, config, products) + if eventHooks and eventHooks.start then + eventHook.execute(eventHooks.start, version, config, products) end while true do -- add t = t if we need animations @@ -549,8 +554,8 @@ os.pullEvent = oldPullEvent if not success then - if config.hooks and config.hooks.programError then - eventHook.execute(config.hooks.programError, err) + if eventHooks and eventHooks.programError then + eventHook.execute(eventHooks.programError, err) end error(err) end