- Joined
- Jan 3, 2022
- Messages
- 364
Update:
Use Bribe's library instead.Motivation
JassHelper has a feature that allows you to replace war3map.j's main() and config() functions, from its manual:main() is called during map loading and initialization.inject
Certain advanced users might use the world editor yet prefer to have more control over the map script, namely making their own main or config functions, the inject preprocessors allows to replace such functions.
config() is called in the lobby, a popular example is lobby music. Because your entire triggers and code are placed BEFORE the config/main() functions war3map.lua, there's a little more work to do to override them.
Unlike JassHelper, my goal was to extend both main() - to emulate what vJass is doing with onInit, and config() to allow modifications yet without replacing it - allow WorldEdit to generate as much as possible. Smooth integration.
Code
Lua:
-- version 1.0.0
--[[ injects two given functions into main() and config() similar to what JassHelper did
Injection point for main() is between the calls to InitBlizzard() and InitGlobals()
Injection point for config() is after its execution
]]
function luahelperInject(funcMain, funcConfig)
if InitGlobals then
local real_InitGlobals = InitGlobals
function InitGlobals()
funcMain()
real_InitGlobals()
end
end
local mt = getmetatable(_G) or {}
mt.__newindex = function(tbl, key, val)
if key == "config" then
--[[ intercept config and put a wrapper around ]]
rawset(tbl, key, function()
val()
funcConfig()
end)
--[[ remove this hook ]]
mt.__newindex = nil
else
--[[ pass through ]]
rawset(tbl, key, val)
end
end
setmetatable(_G, mt)
end
In other words, save this code to a script.lua somewhere and run it from Lua console. This is just to demonstrate how it works in principle.
Lua:
#!/usr/bin/env lua
function a(t)
print("t is: ", t)
return t
end
--[[ injects two given functions into main() and config()
similar to what JassHelper did
Injection point for main() is between the calls to
InitBlizzard() and InitGlobals()
Injection point for config() is after its execution
]]
---
function luahelperInject(funcMain, funcConfig)
if InitGlobals then
local real_InitGlobals = InitGlobals
function InitGlobals()
funcMain()
real_InitGlobals()
end
end
local mt = getmetatable(_G) or {}
mt.__newindex = function(tbl, key, val)
if key == "config" then
--[[ intercept config and put a wrapper around ]]
rawset(tbl, key, function()
val()
funcConfig()
end)
--[[ remove this hook ]]
mt.__newindex = nil
else
--[[ pass through ]]
rawset(tbl, key, val)
end
end
setmetatable(_G, mt)
end
function InitGlobals()
print("Dummy Globals")
end
luahelperInject(
function() print("MAIN INJECT") end,
function() print("CONFIG INJECT") end
)
function b(x)
print("x+1 is:", x+1)
return x+1
end
function InitBlizzard()
print("Dummy InitBlizzard")
end
function main()
print("start of main")
InitBlizzard()
InitGlobals()
print("end of main")
end
function config()
print("start of config")
print("end of config")
end
config()
main()
Lua:
do
local function luahelperInject(funcMain, funcConfig)
if InitGlobals then
local real_InitGlobals = InitGlobals
function InitGlobals()
funcMain()
real_InitGlobals()
end
end
local mt = getmetatable(_G) or {}
mt.__newindex = function(tbl, key, val)
if key == "config" then
--[[ intercept config and put a wrapper around ]]
rawset(tbl, key, function()
val()
funcConfig()
end)
--[[ remove this hook ]]
mt.__newindex = nil
else
--[[ pass through ]]
rawset(tbl, key, val)
end
end
setmetatable(_G, mt)
end
-- create our code functions for injection
local inject_into_main = function()
DidMainInject = "Yes, main() inject worked!"
end
local inject_into_config = function()
DidConfigInject = "Yes, config() inject worked!"
end
-- inject and enjoy the sunset
luahelperInject(inject_into_main, inject_into_config)
end
How to use
Create a custom code item in Trigger Editor. Paste the code. Call theluahelperInject(func_into_main, func_into_config)
function. First argument is a function to inject in main(), second argument is a function to inject in config().If you only want to inject one of them, supply an empty function like
luahelperInject(realFunctionIcreatedBefore, function() end)
It's preferable to put the created trigger at the very bottom of all triggers, because it intercepts the creation of all global variables until it finds config(), then does its job and disables itself.
Limitations
You cannot use this function multiple times to add more than one function to the hook. Only use it once. I think it's simple, easy and useful as it is without complexity. EDIT: If someone wants to use it for a system as a library, tell me and I will add the functionality.Overriden functions:
Incompatibility: __newindex metatable of _G is used until it the config function is defined. __newindex is set to defaultnil
after.Override: InitGlobals, config. Your code is "injected" inside rather than replacing them.
PS: Alternative to my code above - @Bribe's Global Initialization + Hook libraries (see post #6 below)
Attachments
Last edited: