rework hooks, proper arg conversion for luacall from ts, fix+rename bl.addServerCmd/addClientCmd, remove 'bool' from ts.type (only use 'boolean'), more dedefault typedefs, support typedefs on named objects, typedef inheritance, reorganize libts
This commit is contained in:
BIN
BlockLua.dll
BIN
BlockLua.dll
Binary file not shown.
30
readme.md
30
readme.md
@@ -40,24 +40,36 @@ Lua scripting for Blockland
|
||||
### Advanced
|
||||
`sched = bl.schedule(timeMs, function, args...)` - Schedule a Lua function to be called later, similar to schedule in Torque
|
||||
`sched:cancel()` - Cancel a previously scheduled timer
|
||||
|
||||
### Raycasts and Searches
|
||||
`hitObject, hitPos, hitNormal = bl.raycast(vector{startPosX,y,z}, vector{endPosX,y,z}, 'objtype'/{'objtypes',...}, ignoreObjects...?)` - Cast a ray in the world over objects of the specified type(s) (possibly excluding some objects), and return the object hit, the position of the hit, and the normal vector to the surface hit. See the Types section for a list of valid object types.
|
||||
`for object in bl.boxSearch(vector{centerX,y,z}, vector{sizeX,y,z}, 'objtype'/{'objtypes',...}) do` - Find all objects in the world of the specified type(s) whose bounding box overlaps with the specified box. See the Types section for a list of valid object types.
|
||||
`for object in bl.radiusSearch(vector{centerX,y,z}, radius, 'objtype'/{'objtypes',...}) do` - Find all objects of the specified type(s) whose bounding box overlaps with the specified sphere. See the Types section for a list of valid object types.
|
||||
`bl.serverCmd('commandName', function(client, args...) code() end)` - Register a /-command on the server
|
||||
`bl.clientCmd('commandName', function(args...) code() end)` - Register a client command on the client
|
||||
|
||||
### Server-Client Communication
|
||||
`bl.addServerCmd('commandName', function(client, args...) code() end)` - Register a /-command on the server
|
||||
`bl.addClientCmd('commandName', function(args...) code() end)` - Register a client command on the client
|
||||
`bl.commandToServer('commandName', args...)` - Execute a server command as a client
|
||||
`bl.commandToClient('commandName', args...)` - As the server, execute a client command on a specific client
|
||||
`bl.commandToAll('commandName', args...)` - As the server, execute a client command on all clients
|
||||
|
||||
### Packages/Hooks
|
||||
`bl.hook('packageName', 'functionName', 'before'/'after'/'override', function(args...) code() end)` - Hook a Torque function with a Lua function
|
||||
`bl.unhook('packageName', 'functionName', 'before'/'after'/'override')` - Remove a previously defined hook
|
||||
`bl.hook('packageName', 'functionName', 'before'/'after', function(args) code() end)` - Hook a Torque function with a Lua function.
|
||||
`args` is an array containing the arguments provided to the function. If the hook is `before`, these can be modified before being passed to the parent function.
|
||||
If `args._return` is set to anything other than nil by a `before` hook, the parent function will not be called, and the function will simply return that value. Also in this case, any `after` hook will not be executed.
|
||||
In an `after` hook, `args._return` is set to the value returned by the parent function, and can be modified.
|
||||
`bl.unhook('packageName', 'functionName', 'before'/'after')` - Remove a previously defined hook
|
||||
`bl.unhook('packageName', 'functionName')` - Remove any previously defined hooks on the function within the package
|
||||
`bl.unhook('packageName')` - Remove any previously defined hooks within the package
|
||||
|
||||
### Classes and Types
|
||||
`bl.bool(thing)` - Convert a Torque boolean (0 or 1) into a Lua boolean. Done automatically for all built-in functions that return bools.
|
||||
`bl.object(thing)` - Convert a Torque object reference (object ID or name) into a Lua object. Done automatically for all built-in functions that return objects.
|
||||
`bl.type('varName', 'type')` - Register the type of a Torque global variable, for conversion when accessing from Lua. Valid types are 'bool', 'object', and nil - all other conversion is automatic.
|
||||
`bl.type('funcName', 'type')` - Register the return type of a Torque function, for conversion when calling from Lua. Valid types are 'bool', 'object', and nil - all other conversion is automatic. Already done for all built-in functions that return objects.
|
||||
`bl.type('varName', 'type')` - Register the type of a Torque global variable, for conversion when accessing from Lua. Valid types are 'boolean', 'object', and nil (default is nil, which applies automatic conversion).
|
||||
`bl.type('funcName', 'type')` - Register the return type of a Torque function, for conversion when calling from Lua. Valid types are 'bool', 'object', and nil - all other conversion is automatic. Already done for all default functions.
|
||||
`bl.type('className::funcName', 'type')` - Register the return type of a Torque object method.
|
||||
`bl.class('className')` - Register a Torque class to be used from Lua (Already done for all built-in classes)
|
||||
`bl.class('className', 'parentClassName')` - Same as above, with inheritance
|
||||
`bl.bool(thing)` - Manually convert a Torque boolean (0 or 1) into a Lua boolean.
|
||||
`bl.object(thing)` - Manually convert a Torque object reference (object ID or name) into a Lua object.
|
||||
|
||||
### File I/O
|
||||
Lua's builtin file I/O is emulated, and is confined to the same directories as TorqueScript file I/O.
|
||||
@@ -95,7 +107,7 @@ Like in standard Lua, modules loaded using `require` are only executed the first
|
||||
When a TorqueScript function is called from Lua or vice-versa, the arguments and return value must be converted between the two languages' type systems.
|
||||
TorqueScript stores no type information; all values in TorqueScript are strings. So it's necessary to make some inferences when converting values between the two languages.
|
||||
### From TorqueScript to Lua
|
||||
- Any numeric value becomes a Lua `number`, except as specified with `ts.type`, which may convert a value into a `boolean` or a Torque object container.
|
||||
- Any numeric value becomes a Lua `number`, except as specified with `bl.type`, which may convert a value into a `boolean` or a Torque object container.
|
||||
- The empty string "" becomes `nil`
|
||||
- A string containing three numbers separated by spaces becomes a `vector`
|
||||
- A string containing six numbers separated by spaces becomes a table of two vectors
|
||||
|
||||
@@ -28,8 +28,8 @@ INCLUDE_BIN(bll_fileLuaEnv , "lua-env.lua");
|
||||
INCLUDE_BIN(bll_fileTsEnv , "ts-env.cs" );
|
||||
INCLUDE_BIN(bll_fileLuaStd , "util/std.lua");
|
||||
INCLUDE_BIN(bll_fileLuaVector , "util/vector.lua");
|
||||
INCLUDE_BIN(bll_fileLuaLibts , "util/libts.lua");
|
||||
INCLUDE_BIN(bll_fileTsLibtsSupport, "util/libts-support.cs");
|
||||
INCLUDE_BIN(bll_fileLuaLibts , "util/libts-lua.lua");
|
||||
INCLUDE_BIN(bll_fileTsLibts , "util/libts-ts.cs");
|
||||
INCLUDE_BIN(bll_fileLuaLibbl , "util/libbl.lua" );
|
||||
INCLUDE_BIN(bll_fileLuaLibblTypes , "util/libbl-types.lua");
|
||||
INCLUDE_BIN(bll_fileTsLibblSupport, "util/libbl-support.cs");
|
||||
@@ -68,7 +68,7 @@ bool init() {
|
||||
BLL_LOAD_LUA(gL, bll_fileLuaStd);
|
||||
BLL_LOAD_LUA(gL, bll_fileLuaVector);
|
||||
BLL_LOAD_LUA(gL, bll_fileLuaLibts);
|
||||
BlEval(bll_fileTsLibtsSupport);
|
||||
BlEval(bll_fileTsLibts);
|
||||
BLL_LOAD_LUA(gL, bll_fileLuaLibbl);
|
||||
BLL_LOAD_LUA(gL, bll_fileLuaLibblTypes);
|
||||
BlEval(bll_fileTsLibblSupport);
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// Built-in functions
|
||||
// Eval'd after BLLua4 has loaded the Lua environment and API
|
||||
|
||||
// Public Lua library for TS
|
||||
function luacall(%func, %a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall(%func, %a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p);
|
||||
}
|
||||
function luaexec(%fn) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall("_bllua_exec", %fn);
|
||||
}
|
||||
function luaeval(%code) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall("_bllua_eval", %code);
|
||||
}
|
||||
function luaget(%name) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall("_bllua_getvar", %name);
|
||||
}
|
||||
function luaset(%name, %val) {
|
||||
if($_bllua_active)
|
||||
_bllua_luacall("_bllua_setvar", %name, %val);
|
||||
}
|
||||
|
||||
echo(" Executed bllua-env.cs");
|
||||
|
||||
@@ -10,7 +10,7 @@ package _bllua_smartEval {
|
||||
if($_bllua_active) {
|
||||
%text = getSubStr(%text, 1, strLen(%text));
|
||||
echo("Lua ==> " @ %text);
|
||||
luacall("_bllua_smarteval", %text);
|
||||
_bllua_luacall("_bllua_smarteval", %text);
|
||||
} else {
|
||||
echo("Lua: not loaded");
|
||||
}
|
||||
@@ -36,7 +36,8 @@ package _bllua_objectDeletionHook {
|
||||
// note: no parent function exists by default,
|
||||
// and this is loaded before any addons
|
||||
//parent::onRemove(%obj);
|
||||
if($_bllua_active) luacall("_bllua_objectDeleted", %obj);
|
||||
// assuming obj is an ID and never a name
|
||||
if($_bllua_active) _bllua_luacall("_bllua_objectDeleted", %obj);
|
||||
}
|
||||
};
|
||||
activatePackage(_bllua_objectDeletionHook);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -106,22 +106,30 @@ local function valToTs(val)
|
||||
error('valToTs: could not convert '..type(val), 3)
|
||||
end
|
||||
end
|
||||
bl._forceType = bl._forceType or {}
|
||||
local function valFromTs(val, name)
|
||||
if type(val)~='string' then
|
||||
error('valFromTs: expected string, got '..type(val), 3) end
|
||||
if name then
|
||||
local nameL = name:lower()
|
||||
if bl._forceType[nameL] then
|
||||
local typ = bl._forceType[nameL]
|
||||
local function convertValFromTs(val, typ)
|
||||
if typ=='boolean' then
|
||||
return tsBool(val)
|
||||
elseif typ=='object' then
|
||||
return toTsObject(val)
|
||||
else
|
||||
error('valFromTs: invalid force type '..typ, 3)
|
||||
error('valFromTs: invalid force type '..typ, 4)
|
||||
end
|
||||
end
|
||||
bl._forceType = bl._forceType or {}
|
||||
local function valFromTs(val, name, name2) -- todo: ensure name and name2 are already lowercase
|
||||
if type(val)~='string' then
|
||||
error('valFromTs: expected string, got '..type(val), 3) end
|
||||
if name then
|
||||
name = name:lower()
|
||||
if bl._forceType[name] then
|
||||
return convertValFromTs(val, bl._forceType[name])
|
||||
end
|
||||
end
|
||||
if name2 then
|
||||
name2 = name2:lower()
|
||||
if bl._forceType[name2] then
|
||||
return convertValFromTs(val, bl._forceType[name2])
|
||||
end
|
||||
end
|
||||
-- '' -> nil
|
||||
if val=='' then return nil end
|
||||
@@ -151,22 +159,35 @@ end
|
||||
local function arglistToTs(args)
|
||||
return map(args, valToTs)
|
||||
end
|
||||
function bl.type(name, typ)
|
||||
if typ~='bool' and typ~='boolean' and typ~='object' and typ~=nil then
|
||||
error('bl.type: can only set type to \'bool\' or \'object\' or nil', 2) end
|
||||
if not isValidFuncNameNsArgn(name) then
|
||||
error('bl.type: invalid function or variable name \''..name..'\'', 2) end
|
||||
if typ=='bool' then typ='boolean' end
|
||||
|
||||
bl._forceType[name:lower()] = typ
|
||||
-- apply to children (wip)
|
||||
--local class, rest = name:match('^([a-zA-Z0-9_]+)(::.+)$')
|
||||
--if not class then
|
||||
-- class, rest = name:match('^([a-zA-Z0-9_]+)(%..+)$') end
|
||||
--if class then
|
||||
--
|
||||
--end
|
||||
local function classFromForceTypeStr(name)
|
||||
local class, rest = name:match('^([a-zA-Z0-9_]+)(::.+)$')
|
||||
if not class then
|
||||
class, rest = name:match('^([a-zA-Z0-9_]+)(%..+)$') end
|
||||
return class,rest
|
||||
end
|
||||
local setForceType
|
||||
setForceType = function(ftname, typ)
|
||||
if typ~='boolean' and typ~='object' and typ~=nil then
|
||||
error('bl.type: can only set type to \'boolean\', \'object\', or nil', 2) end
|
||||
if not isValidFuncNameNsArgn(ftname) then
|
||||
error('bl.type: invalid function or variable name \''..ftname..'\'', 2) end
|
||||
|
||||
ftname = ftname:lower()
|
||||
|
||||
bl._forceType[ftname] = typ
|
||||
|
||||
-- apply to child classes if present
|
||||
local cname, rest = classFromForceTypeStr(ftname)
|
||||
if cname then
|
||||
local meta = bl._objectUserMetas[cname]
|
||||
if meta then
|
||||
for chcname,_ in pairs(meta._children) do
|
||||
setForceType(chcname..rest, typ)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
bl.type = setForceType
|
||||
|
||||
|
||||
-- Value detection
|
||||
@@ -210,40 +231,47 @@ end
|
||||
local tsClassMeta = {
|
||||
__tostring = function(t)
|
||||
return 'torqueClass:'..t._name..
|
||||
(t._inherit and (':'..t._inherit) or '')
|
||||
(t._inherit and (':'..t._inherit._name) or '')
|
||||
end,
|
||||
}
|
||||
bl._objectUserMetas = bl._objectUserMetas or {}
|
||||
function bl.class(name, inherit)
|
||||
if not ( type(name)=='string' and isValidFuncName(name) ) then
|
||||
function bl.class(cname, inhname)
|
||||
if not ( type(cname)=='string' and isValidFuncName(cname) ) then
|
||||
error('bl.class: argument #1: invalid class name', 2) end
|
||||
if not ( inherit==nil or (type(inherit)=='string' and isValidFuncName(inherit)) ) then
|
||||
if not ( inhname==nil or (type(inhname)=='string' and isValidFuncName(inhname)) ) then
|
||||
error('bl.class: argument #2: inherit name must be a string or nil', 2) end
|
||||
name = name:lower()
|
||||
cname = cname:lower()
|
||||
|
||||
local met = bl._objectUserMetas[name] or {
|
||||
_name = name,
|
||||
local met = bl._objectUserMetas[cname] or {
|
||||
_name = cname,
|
||||
_inherit = nil,
|
||||
_children = {},
|
||||
}
|
||||
bl._objectUserMetas[name] = met
|
||||
bl._objectUserMetas[cname] = met
|
||||
setmetatable(met, tsClassMeta)
|
||||
|
||||
if inherit then
|
||||
inherit = inherit:lower()
|
||||
if inhname then
|
||||
inhname = inhname:lower()
|
||||
|
||||
local inh = bl._objectUserMetas[inherit]
|
||||
if not inh then error('bl.class: argument #2: \''..inherit..'\' is not the '..
|
||||
local inh = bl._objectUserMetas[inhname]
|
||||
if not inh then error('bl.class: argument #2: \''..inhname..'\' is not the '..
|
||||
'name of an existing class', 2) end
|
||||
|
||||
inh._children[name] = true
|
||||
inh._children[cname] = true
|
||||
|
||||
local inhI = met._inherit
|
||||
if inhI and inhI~=inh then
|
||||
error('bl.class: argument #2: class already exists and '..
|
||||
'inherits a different parent.', 2) end
|
||||
|
||||
met._inherit = inh
|
||||
|
||||
-- apply inherited method and field types
|
||||
for ftname, typ in pairs(bl._forceType) do
|
||||
local cname2, rest = classFromForceTypeStr(ftname)
|
||||
if cname2==inhname then
|
||||
setForceType(cname..rest, typ)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local function objectInheritedMetas(name)
|
||||
@@ -279,11 +307,15 @@ local tsObjectMeta = {
|
||||
return function(t, ...)
|
||||
local args = {...}
|
||||
local argsS = arglistToTs(args)
|
||||
return valFromTs(_bllua_ts.callobj(rawget(t,'_tsObjectId'), name, unpack(argsS)),
|
||||
return valFromTs(
|
||||
_bllua_ts.callobj(rawget(t,'_tsObjectId'), name, unpack(argsS)),
|
||||
rawget(t,'_tsName') and rawget(t,'_tsName')..'::'..name,
|
||||
rawget(t,'_tsNamespace')..'::'..name)
|
||||
end
|
||||
else
|
||||
return valFromTs(_bllua_ts.getfield(rawget(t,'_tsObjectId'), name),
|
||||
return valFromTs(
|
||||
_bllua_ts.getfield(rawget(t,'_tsObjectId'), name),
|
||||
rawget(t,'_tsName') and rawget(t,'_tsName')..'.'..name,
|
||||
rawget(t,'_tsNamespace')..'.'..name)
|
||||
end
|
||||
end
|
||||
@@ -489,7 +521,7 @@ local tsMeta = {
|
||||
-- bl.set(name, value)
|
||||
-- Used to set global variables
|
||||
function bl.set(name, val)
|
||||
_bllua_ts.call('_bllua_set_var', name, valToTs(val))
|
||||
_bllua_ts.setvar(name, valToTs(val))
|
||||
end
|
||||
|
||||
-- Utility functions
|
||||
@@ -499,7 +531,7 @@ function bl.call(func, ...)
|
||||
return _bllua_ts.call(func, unpack(argsS))
|
||||
end
|
||||
function bl.eval(code)
|
||||
return valFromTs(_bllua_ts.call('eval', code))
|
||||
return valFromTs(_bllua_ts.eval(code))
|
||||
end
|
||||
function bl.exec(file)
|
||||
return valFromTs(_bllua_ts.call('exec', file))
|
||||
@@ -524,8 +556,13 @@ function bl.array(name, ...)
|
||||
local rest = {...}
|
||||
return name..table.concat(rest, '_')
|
||||
end
|
||||
function _bllua_call(name, ...)
|
||||
-- todo: call ts->lua using this instead of directly
|
||||
function _bllua_call(fnameS, ...)
|
||||
local args = arglistFromTs(fnameS:lower(), {...})
|
||||
if not _G[fnameS] then
|
||||
error('luacall: no global lua function named \''..fnameS..'\'') end
|
||||
-- todo: library fields and object methods
|
||||
local res = _G[fnameS](args)
|
||||
return valToTs(res)
|
||||
end
|
||||
|
||||
-- bl.schedule: Use TS's schedule function to schedule lua calls
|
||||
@@ -544,7 +581,7 @@ function bl.schedule(time, cb, ...)
|
||||
bl._scheduleNextId = bl._scheduleNextId+1
|
||||
local args = {...}
|
||||
local handle = tonumber(_bllua_ts.call('schedule',
|
||||
time, 0, 'luacall', '_bllua_schedule_callback', id))
|
||||
time, 0, '_bllua_luacall', '_bllua_schedule_callback', id))
|
||||
local sch = {
|
||||
callback = cb,
|
||||
args = args,
|
||||
@@ -554,8 +591,9 @@ function bl.schedule(time, cb, ...)
|
||||
bl._scheduleTable[id] = sch
|
||||
return sch
|
||||
end
|
||||
function _bllua_schedule_callback(id)
|
||||
id = tonumber(id) or error('_bllua_schedule_callback: invalid id: '..tostring(id))
|
||||
function _bllua_schedule_callback(idS)
|
||||
local id = tonumber(idS) or
|
||||
error('_bllua_schedule_callback: invalid id: '..tostring(idS))
|
||||
local sch = bl._scheduleTable[id]
|
||||
if not sch then error('_bllua_schedule_callback: no schedule with id '..id) end
|
||||
bl._scheduleTable[id] = nil
|
||||
@@ -563,26 +601,48 @@ function _bllua_schedule_callback(id)
|
||||
end
|
||||
|
||||
-- serverCmd and clientCmd
|
||||
-- bl.serverCmd('suicide', function(client) client.player:kill() end)
|
||||
bl._cmds = bl._cmds or {}
|
||||
function _bllua_process_cmd(cmdS, clientS, ...)
|
||||
local client = toTsObject(clientS)
|
||||
local argsS = {...}
|
||||
local args = arglistFromTs(cmdS, argsS)
|
||||
local func = bl._cmds[cmdS]
|
||||
function _bllua_process_cmd(cmdS, ...)
|
||||
local cmd = cmdS:lower()
|
||||
local args = arglistFromTs(cmd, {...})
|
||||
local func = bl._cmds[cmd]
|
||||
if not func then error('_bllua_process_cmd: no cmd named \''..cmd..'\'') end
|
||||
pcall(func, client, unpack(args))
|
||||
func(unpack(args)) --pcall(func, unpack(args))
|
||||
end
|
||||
local function addCmd(cmd, func)
|
||||
if not isValidFuncName(cmd) then
|
||||
error('addCmd: invalid function name \''..tostring(cmd)..'\'') end
|
||||
bl._servercmds[cmd] = func
|
||||
local arglist = '%a,%b,%c,%d,%e,%f,%g,%h'
|
||||
_bllua_ts.eval('function '..cmd..'(%cl,'..arglist..'){'..
|
||||
'luacall(_bllua_process_cmd,"'..cmd..'",%cl,'..arglist..');}')
|
||||
bl._cmds[cmd] = func
|
||||
local arglist = '%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p'
|
||||
_bllua_ts.eval('function '..cmd..'('..arglist..'){'..
|
||||
'_bllua_luacall(_bllua_process_cmd,"'..cmd..'",'..arglist..');}')
|
||||
end
|
||||
function bl.addServerCmd(name, func)
|
||||
name = name:lower()
|
||||
addCmd('servercmd'..name, func)
|
||||
bl._forceType['servercmd'..name..':1'] = 'object'
|
||||
end
|
||||
function bl.addClientCmd(name, func)
|
||||
name = name:lower()
|
||||
addCmd('clientcmd'..name, func)
|
||||
end
|
||||
|
||||
-- commandToServer and commandToClient
|
||||
function bl.commandToServer(cmd, ...)
|
||||
_bllua_ts.call('commandToServer',
|
||||
_bllua_ts.call('addTaggedString', cmd),
|
||||
unpack(arglistToTs({...})))
|
||||
end
|
||||
function bl.commandToClient(cmd, ...)
|
||||
_bllua_ts.call('commandToClient',
|
||||
_bllua_ts.call('addTaggedString', cmd),
|
||||
unpack(arglistToTs({...})))
|
||||
end
|
||||
function bl.commandToAll(cmd, ...)
|
||||
_bllua_ts.call('commandToAll',
|
||||
_bllua_ts.call('addTaggedString', cmd),
|
||||
unpack(arglistToTs({...})))
|
||||
end
|
||||
function bl.serverCmd(name, func) addCmd('serverCmd'..name, func) end
|
||||
function bl.clientCmd(name, func) addCmd('clientCmd'..name, func) end
|
||||
|
||||
-- Hooks (using TS packages)
|
||||
local function isPackageActive(pkg)
|
||||
@@ -603,42 +663,67 @@ local function deactivatePackage(pkg)
|
||||
_bllua_ts.call('deactivatePackage', pkg)
|
||||
end
|
||||
end
|
||||
local hookNargs = 8
|
||||
local hookArglistLocal = '%a,%b,%c,%d,%e,%f,%g,%h'
|
||||
local hookArglistGlobal = '$_bllua_hook_arg1,$_bllua_hook_arg2,$_bllua_hook_arg3,$_bllua_hook_arg4,$_bllua_hook_arg5,$_bllua_hook_arg6,$_bllua_hook_arg7,$_bllua_hook_arg8'
|
||||
bl._hooks = bl._hooks or {}
|
||||
function _bllua_process_hook(pkgS, nameS, timeS, ...)
|
||||
local argsS = {...}
|
||||
local args = arglistFromTs(nameS, argsS)
|
||||
|
||||
function _bllua_process_hook_before(pkgS, nameS, ...)
|
||||
local args = arglistFromTs(nameS, {...})
|
||||
local func = bl._hooks[pkgS] and bl._hooks[pkgS][nameS] and
|
||||
bl._hooks[pkgS][nameS][timeS]
|
||||
bl._hooks[pkgS][nameS].before
|
||||
if not func then
|
||||
error('_bllua_process_hook: no hook for '..pkgS..':'..nameS..':'..timeS) end
|
||||
|
||||
pcall(func, args)
|
||||
error('_bllua_process_hook_before: no hook for '..pkgs..':'..nameS) end
|
||||
_bllua_ts.setvar('_bllua_hook_abort', '0')
|
||||
func(args) --pcall(func, args)
|
||||
if args._return then
|
||||
_bllua_ts.setvar('_bllua_hook_abort', '1')
|
||||
_bllua_ts.setvar('_bllua_hook_return', valToTs(args._return))
|
||||
end
|
||||
for i=1,hookNargs do
|
||||
_bllua_ts.setvar('_bllua_hook_arg'..i, valToTs(args[i]))
|
||||
end
|
||||
end
|
||||
function _bllua_process_hook_after(pkgS, nameS, resultS, ...)
|
||||
nameS = nameS:lower()
|
||||
local args = arglistFromTs(nameS, {...})
|
||||
args._return = valFromTs(resultS, nameS)
|
||||
local func = bl._hooks[pkgS] and bl._hooks[pkgS][nameS] and
|
||||
bl._hooks[pkgS][nameS].after
|
||||
if not func then
|
||||
error('_bllua_process_hook_after: no hook for '..pkgs..':'..nameS) end
|
||||
func(args) --pcall(func, args)
|
||||
return valToTs(args._return)
|
||||
end
|
||||
local function updateHook(pkg, name, hk)
|
||||
local arglist = '%a,%b,%c,%d,%e,%f,%g,%h'
|
||||
local beforeCode = hk.before and
|
||||
('luacall("_bllua_process_hook", "'..pkg..'", "'..name..
|
||||
'", "before", '..arglist..');') or ''
|
||||
local parentCode = hk.override and
|
||||
('luacall("_bllua_process_hook", "'..pkg..'", "'..name..
|
||||
'", "override", '..arglist..');') or
|
||||
(tsIsFunctionNsname(name) and
|
||||
('parent::'..name:match('[^:]+$')..'('..arglist..');') or '')
|
||||
('_bllua_luacall("_bllua_process_hook_before", "'..pkg..'","'..name..
|
||||
'",'..hookArglistLocal..');') or ''
|
||||
local arglist = (hk.before and hookArglistGlobal or hookArglistLocal)
|
||||
local parentCode =
|
||||
tsIsFunctionNsname(name) and -- only call parent if it exists
|
||||
(hk.before and
|
||||
'if($_bllua_hook_abort)return $_bllua_hook_return; else ' or '')..
|
||||
((hk.after and '%result=' or 'return ')..
|
||||
'parent::'..name:match('[^:]+$')..
|
||||
'('..arglist..');') or ''
|
||||
local afterCode = hk.after and
|
||||
('luacall("_bllua_process_hook", "'..pkg..'", "'..name..
|
||||
'", "after", '..arglist..');') or ''
|
||||
bl.eval('package '..pkg..'{function '..name..'('..arglist..'){'..
|
||||
beforeCode..parentCode..afterCode..'}};')
|
||||
('return _bllua_luacall("_bllua_process_hook_after","'..pkg..'","'..name..'",%result,'..
|
||||
arglist..');') or ''
|
||||
local code =
|
||||
'package '..pkg..'{'..
|
||||
'function '..name..'('..hookArglistLocal..'){'..
|
||||
beforeCode..parentCode..afterCode..
|
||||
'}'..
|
||||
'};'
|
||||
_bllua_ts.eval(code)
|
||||
end
|
||||
function bl.hook(pkg, name, time, func)
|
||||
if not isValidFuncName(pkg) then
|
||||
error('bl.hook: argument #1: invalid package name \''..tostring(pkg)..'\'', 2) end
|
||||
if not isValidFuncNameNs(name) then
|
||||
error('bl.hook: argument #2: invalid function name \''..tostring(name)..'\'', 2) end
|
||||
if time~='before' and time~='after' and time~='override' then
|
||||
error('bl.hook: argument #3: time must be one of '..
|
||||
'\'before\' \'after\' \'override\'', 2) end
|
||||
if time~='before' and time~='after' then
|
||||
error('bl.hook: argument #3: time must be \'before\' or \'after\'', 2) end
|
||||
if type(func)~='function' then
|
||||
error('bl.hook: argument #4: expected a function', 2) end
|
||||
|
||||
@@ -654,9 +739,8 @@ function bl.unhook(pkg, name, time)
|
||||
error('bl.unhook: argument #1: invalid package name \''..tostring(pkg)..'\'', 2) end
|
||||
if not isValidFuncNameNs(name) then
|
||||
error('bl.unhook: argument #2: invalid function name \''..tostring(name)..'\'', 2) end
|
||||
if time~='before' and time~='after' and time~='override' then
|
||||
error('bl.unhook: argument #3: time must be one of '..
|
||||
'\'before\' \'after\' \'override\'', 2) end
|
||||
if time~='before' and time~='after' then
|
||||
error('bl.unhook: argument #3: time must be \'before\' or \'after\'', 2) end
|
||||
|
||||
if not name then
|
||||
if bl._hooks[pkg] then
|
||||
@@ -679,16 +763,17 @@ function bl.unhook(pkg, name, time)
|
||||
end
|
||||
updateHook(pkg, name, {})
|
||||
else
|
||||
if time~='before' and time~='after' and time~='override' then
|
||||
error('bl.unhook: argument #3: time must be nil or one of '..
|
||||
'\'before\' \'after\' \'override\'', 2) end
|
||||
if time~='before' and time~='after' then
|
||||
error('bl.unhook: argument #3: time must be nil, \'before\', or \'after\'', 2) end
|
||||
bl._hooks[pkg][name][time] = nil
|
||||
if table.empty(bl._hooks[pkg][name]) and table.empty(bl._hooks[pkg]) then
|
||||
bl._hooks[pkg] = nil
|
||||
deactivatePackage(pkg)
|
||||
end
|
||||
updateHook(pkg, name, {})
|
||||
else
|
||||
updateHook(pkg, name, bl._hooks[pkg][name])
|
||||
end
|
||||
end
|
||||
else
|
||||
--error('bl.unhook: no hooks registered for function \''..name..
|
||||
-- '\' under package name \''..pkg..'\'', 2)
|
||||
|
||||
@@ -213,4 +213,8 @@ function _bllua_smarteval(code)
|
||||
end
|
||||
end
|
||||
|
||||
_bllua_ts.call('echo', ' Executed libts.lua')
|
||||
function ts.setvar(name, val)
|
||||
_bllua_ts.call('_bllua_set_var', name, val)
|
||||
end
|
||||
|
||||
_bllua_ts.call('echo', ' Executed libts-lua.lua')
|
||||
@@ -49,4 +49,26 @@ function _bllua_set_var(%name, %val) {
|
||||
return "";
|
||||
}
|
||||
|
||||
echo(" Executed libts-support.cs");
|
||||
// Public Lua library for TS
|
||||
function luacall(%func, %a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall("_bllua_call", %func, %a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p);
|
||||
}
|
||||
function luaexec(%fn) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall("_bllua_exec", %fn);
|
||||
}
|
||||
function luaeval(%code) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall("_bllua_eval", %code);
|
||||
}
|
||||
function luaget(%name) {
|
||||
if($_bllua_active)
|
||||
return _bllua_luacall("_bllua_getvar", %name);
|
||||
}
|
||||
function luaset(%name, %val) {
|
||||
if($_bllua_active)
|
||||
_bllua_luacall("_bllua_setvar", %name, %val);
|
||||
}
|
||||
|
||||
echo(" Executed libts-ts.cs");
|
||||
Reference in New Issue
Block a user