diff --git a/changelog.txt b/changelog.txt index 0b508b09a6..9ebefd8425 100644 --- a/changelog.txt +++ b/changelog.txt @@ -14,6 +14,7 @@ that repo. # Future ## New Scripts +- `devel/eventful-client`: useful for testing eventful events ## Removed diff --git a/devel/eventful-client.lua b/devel/eventful-client.lua new file mode 100644 index 0000000000..081237257a --- /dev/null +++ b/devel/eventful-client.lua @@ -0,0 +1,145 @@ +-- Testing script for eventful events + +--[====[ +devel/eventful-client +===================== + +Usage:: + + devel/eventful-client help + devel/eventful-client add + devel/eventful-client add all + devel/eventful-client list + devel/eventful-client clear + +:help: shows this help text and a list of valid event types +:add: add a handler for the named event type at the requested tick frequency +:list: lists active handlers and their frequencies +:clear: unregisters all handlers + +Note this script does not handle the eventful reaction or workshop events. +]====] + +local eventful = require('plugins.eventful') + +local utils = require('utils') + +rng = rng or dfhack.random.new() + +handlers = handlers or {} + +local function get_event_fn_name(event_type_name) + local fn_name = 'on' + for word in event_type_name:gmatch('[^_]+') do + fn_name = fn_name .. word:sub(1,1) .. word:sub(2):lower() + end + if eventful[fn_name] then return fn_name end + fn_name = fn_name .. 'CreatedDestroyed' + if eventful[fn_name] then return fn_name end + return nil +end + +local function get_event_registry() + local registry = {} + local event_list = utils.invert(eventful.eventType) + for i=0,#event_list do + local event_type_name = event_list[i] + if event_type_name == 'EVENT_MAX' then + return registry + end + registry[i+1] = {etype=event_type_name, + fn=get_event_fn_name(event_type_name)} + end +end + +local function help() + print(dfhack.script_help()) + print() + print('Event types (and the eventful event functions they map to):') + for _,v in ipairs(get_event_registry()) do + print((' %s -> %s'):format(v.etype, v.fn)) + end +end + +local function make_handler_fn(registry_entry, freq) + return function() + print(('eventful-client: %s received %s event (freq=%d)') + :format(os.date("%X"), registry_entry.etype, freq)) + end +end + +-- adds a new handler for the specified event type. uses a unique handler name +-- each time so multiple handlers can be registered for the same event. +local function add_one(registry_entry, freq) + if not registry_entry.fn then + print(('no eventful event function for %s events; skipping') + :format(registry_entry.etype)) + return + end + eventful.enableEvent(eventful.eventType[registry_entry.etype], freq) + local handler_name = 'eventful-client.'..tostring(rng:random()) + local handler = make_handler_fn(registry_entry, freq) + print(('eventful-client registering new %s handler at freq %d: %s') + :format(registry_entry.etype, freq, handler_name)) + eventful[registry_entry.fn][handler_name] = handler + handlers[handler_name] = freq +end + +local function add(spec, freq) + for _,v in ipairs(get_event_registry()) do + if spec == 'all' or spec == v.etype then + add_one(v, freq) + end + end +end + +local function iterate_handlers(fn) + local count = 0 + for _,v in ipairs(get_event_registry()) do + if not eventful[v.fn] then goto continue end + for k in pairs(eventful[v.fn]) do + if k:startswith('eventful-client.') then + count = count + 1 + fn(v, k) + end + end + ::continue:: + end + return count +end + +local function list_fn(registry_entry, handler_name) + print((' %s -> %s (freq=%s)') + :format(registry_entry.etype, handler_name, + handlers[handler_name] or 'unknown')) +end + +local function list() + print('Active handlers:') + if 0 == iterate_handlers(list_fn) then + print(' None') + end +end + +local function clear_fn(registry_entry, handler_name) + list_fn(registry_entry, handler_name) + eventful[registry_entry.fn][handler_name] = nil + handlers[handler_name] = nil +end + +local function clear() + print('Clearing handlers:') + iterate_handlers(clear_fn) +end + +local action_switch = { + add=add, + list=list, + clear=clear, +} +setmetatable(action_switch, {__index=function() return help end}) + +local args = {...} +local action = table.remove(args, 1) or 'help' + +action_switch[action](table.unpack(args))