From e5e0d93ef1e01386b45f241931dd50ffe04e0652 Mon Sep 17 00:00:00 2001 From: expwnent Date: Mon, 2 Feb 2015 02:25:42 -0500 Subject: [PATCH] Added modtools/reaction-product-trigger. --- library/include/LuaTools.h | 16 +++ plugins/eventful.cpp | 29 ++-- plugins/lua/eventful.lua | 4 +- scripts/modtools/reaction-product-trigger.lua | 129 ++++++++++++++++++ scripts/modtools/reaction-trigger.lua | 6 +- 5 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 scripts/modtools/reaction-product-trigger.lua diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index d70e3ee33..042870273 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -500,3 +500,19 @@ namespace DFHack {namespace Lua { name##_event.invoke(out, 6); \ } \ } + +#define DEFINE_LUA_EVENT_7(name, handler, arg_type1, arg_type2, arg_type3, arg_type4, arg_type5,arg_type6,arg_type7) \ + static DFHack::Lua::Notification name##_event(df::wrap_function(handler, true)); \ + void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2, arg_type3 arg3, arg_type4 arg4,arg_type5 arg5, arg_type6 arg6, arg_type7 arg7) { \ + handler(out, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + if (auto state = name##_event.state_if_count()) { \ + DFHack::Lua::Push(state, arg1); \ + DFHack::Lua::Push(state, arg2); \ + DFHack::Lua::Push(state, arg3); \ + DFHack::Lua::Push(state, arg4); \ + DFHack::Lua::Push(state, arg5); \ + DFHack::Lua::Push(state, arg6); \ + DFHack::Lua::Push(state, arg7); \ + name##_event.invoke(out, 7); \ + } \ +} diff --git a/plugins/eventful.cpp b/plugins/eventful.cpp index 39b333326..f984ad579 100644 --- a/plugins/eventful.cpp +++ b/plugins/eventful.cpp @@ -94,7 +94,7 @@ static bool is_lua_hook(const std::string &name) static void handle_fillsidebar(color_ostream &out,df::building_workshopst*,bool *call_native){}; static void handle_postfillsidebar(color_ostream &out,df::building_workshopst*){}; -static void handle_reaction_done(color_ostream &out,df::reaction*, df::unit *unit, std::vector *in_items,std::vector *in_reag +static void handle_reaction_done(color_ostream &out,df::reaction*, df::reaction_product_itemst*, df::unit *unit, std::vector *in_items,std::vector *in_reag , std::vector *out_items,bool *call_native){}; static void handle_contaminate_wound(color_ostream &out,df::item_actual*,df::unit* unit, df::unit_wound* wound, uint8_t a1, int16_t a2){}; static void handle_projitem_ci(color_ostream &out,df::proj_itemst*,bool){}; @@ -105,7 +105,7 @@ static void handle_projunit_cm(color_ostream &out,df::proj_unitst*){}; DEFINE_LUA_EVENT_2(onWorkshopFillSidebarMenu, handle_fillsidebar, df::building_workshopst*,bool* ); DEFINE_LUA_EVENT_1(postWorkshopFillSidebarMenu, handle_postfillsidebar, df::building_workshopst*); -DEFINE_LUA_EVENT_6(onReactionComplete, handle_reaction_done,df::reaction*, df::unit *, std::vector *,std::vector *,std::vector *,bool *); +DEFINE_LUA_EVENT_7(onReactionComplete, handle_reaction_done,df::reaction*, df::reaction_product_itemst*, df::unit *, std::vector *,std::vector *,std::vector *,bool *); DEFINE_LUA_EVENT_5(onItemContaminateWound, handle_contaminate_wound, df::item_actual*,df::unit* , df::unit_wound* , uint8_t , int16_t ); //projectiles DEFINE_LUA_EVENT_2(onProjItemCheckImpact, handle_projitem_ci, df::proj_itemst*,bool ); @@ -298,18 +298,25 @@ struct product_hook : item_product { int32_t quantity, df::job_skill skill, df::historical_entity *entity, df::world_site *site) ) { - if (auto product = products[this]) - { - df::reaction* this_reaction=product->react; - CoreSuspendClaimer suspend; - color_ostream_proxy out(Core::getInstance().getConsole()); - bool call_native=true; - onReactionComplete(out,this_reaction,unit,in_items,in_reag,out_items,&call_native); - if(!call_native) - return; + color_ostream_proxy out(Core::getInstance().getConsole()); + auto product = products[this]; + if ( !product ) { + INTERPOSE_NEXT(produce)(unit, out_items, in_reag, in_items, quantity, skill, entity, site); + return; } + df::reaction* this_reaction=product->react; + CoreSuspendClaimer suspend; + bool call_native=true; + onReactionComplete(out,this_reaction,(df::reaction_product_itemst*)this,unit,in_items,in_reag,out_items,&call_native); + if(!call_native) + return; + size_t out_item_count = out_items->size(); INTERPOSE_NEXT(produce)(unit, out_items, in_reag, in_items, quantity, skill, entity, site); + if ( out_items->size() == out_item_count ) + return; + //if it produced something, call the scripts + onReactionComplete(out,this_reaction,(df::reaction_product_itemst*)this,unit,in_items,in_reag,out_items,NULL); } }; diff --git a/plugins/lua/eventful.lua b/plugins/lua/eventful.lua index f9725ba47..e8bd38827 100644 --- a/plugins/lua/eventful.lua +++ b/plugins/lua/eventful.lua @@ -44,9 +44,9 @@ local function unregall(state) _registeredStuff={} end end -local function onReact(reaction,unit,input_items,input_reagents,output_items,call_native) +local function onReact(reaction,reaction_product,unit,input_items,input_reagents,output_items,call_native) if _registeredStuff.reactionCallbacks and _registeredStuff.reactionCallbacks[reaction.code] then - _registeredStuff.reactionCallbacks[reaction.code](reaction,unit,input_items,input_reagents,output_items,call_native) + _registeredStuff.reactionCallbacks[reaction.code](reaction,reaction_product,unit,input_items,input_reagents,output_items,call_native) end end local function onPostSidebar(workshop) diff --git a/scripts/modtools/reaction-product-trigger.lua b/scripts/modtools/reaction-product-trigger.lua new file mode 100644 index 000000000..9ea1b4cfd --- /dev/null +++ b/scripts/modtools/reaction-product-trigger.lua @@ -0,0 +1,129 @@ +-- scripts/modtools/reaction-product-trigger.lua +-- author expwnent +-- trigger commands just before and after custom reactions produce items + +local eventful = require 'plugins.eventful' +local utils = require 'utils' + +--TODO: onUnload +productHooks = productHooks or {} + +reactionInputItems = reactionInputItems + +eventful.enableEvent(eventful.eventType.UNLOAD,1) +eventful.onUnload.reactionProductTrigger = function() + productHooks = {} +end + +--productHooks.before = productHooks.before or {} +--productHooks.after = productHooks.after or {} + +local function processArgs(args, reaction, reaction_product, unit, input_items, input_reagents, output_items, buildingId) + local result = {} + for _,arg in ipairs(args) do + if arg == '\\WORKER_ID' then + table.insert(result,tostring(unit.id)) + elseif arg == '\\REACTION' then + table.insert(result,reaction.code) +-- elseif arg == '\\REACTION_PRODUCT' then +-- table.insert(result,reaction_product) + elseif arg == '\\INPUT_ITEMS' then + --table.insert(result,'[') + for _,item in ipairs(input_items) do + table.insert(result,tostring(item.id)) + end + --table.insert(result,']') + elseif arg == '\\OUTPUT_ITEMS' then + --table.insert(result,'[') + for _,item in ipairs(output_items) do + table.insert(result,tostring(item.id)) + end + --table.insert(result,']') + elseif arg == '\\BUILDING_ID' then + table.insert(result,tostring(buildingId)) + elseif string.sub(arg,1,1) == '\\' then + table.insert(result,string.sub(arg,2)) + else + table.insert(result,arg) + end + end + return result +end + +local function afterProduce(reaction,reaction_product,unit,input_items,input_reagents,output_items) + --printall(unit.job.current_job) + local _,buildingId = dfhack.script_environment('modtools/reaction-trigger').getWorkerAndBuilding(unit.job.current_job) + for _,hook in ipairs(productHooks[reaction.code] or {}) do + local command = hook.command + local processed = processArgs(command, reaction, reaction_product, unit, input_items, input_reagents, output_items, buildingId) + dfhack.run_command(table.unpack(processed)) + end +end + +eventful.onReactionComplete.reactionProductTrigger = function(reaction,reaction_product,unit,input_items,input_reagents,output_items,call_native) + reactionInputItems = input_items + --print(reaction.code) + --print(#output_items) + --print('call_native exists? ' .. tostring(not not call_native)) + --print('\n') + if call_native then + --beforeProduce(reaction,unit,input_items,input_reagents,output_items,call_native) + else + afterProduce(reaction,reaction_product,unit,input_items,input_reagents,output_items) + end + reactionInputItems = nil +end + +validArgs = validArgs or utils.invert({ + 'help', + 'clear', + 'reactionName', + 'command', +}) + +if moduleMode then + return +end + +local args = {...} or {} +args = utils.processArgs(args, validArgs) + +if args.help then + print([[scripts/modtools/reaction-product-trigger.lua +arguments: + -help + print this help message + -clear + unregister all reaction hooks + -reactionName name + specify the name of the reaction + -command [ commandStrs ] + specify the command to be run on the target(s) + special args + \\WORKER_ID + \\REACTION + \\BUILDING_ID + \\LOCATION + \\INPUT_ITEMS + \\OUTPUT_ITEMS + \\anything -> \anything + anything -> anything +]]) + return +end + +if args.clear then + productHooks = {} +end + +if not args.reactionName then + error('No reactionName.') +end + +if not args.command then + error('No command.') +end + +productHooks[args.reactionName] = productHooks[args.reactionName] or {} +table.insert(productHooks[args.reactionName], args) + diff --git a/scripts/modtools/reaction-trigger.lua b/scripts/modtools/reaction-trigger.lua index f9ecee7c0..2e428c1d4 100644 --- a/scripts/modtools/reaction-trigger.lua +++ b/scripts/modtools/reaction-trigger.lua @@ -13,7 +13,7 @@ eventful.onUnload.reactionTrigger = function() reactionHooks = {} end -local function getWorkerAndBuilding(job) +function getWorkerAndBuilding(job) local workerId = -1 local buildingId = -1 for _,generalRef in ipairs(job.general_refs) do @@ -157,6 +157,10 @@ validArgs = validArgs or utils.invert({ 'allowNonworkerTargets', 'allowMultipleTargets' }) + +if moduleMode then + return +end local args = utils.processArgs({...}, validArgs) if args.help then