|
|
|
|
@@ -106,21 +106,29 @@ local function valToTs(val)
|
|
|
|
|
error('valToTs: could not convert '..type(val), 3)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
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, 4)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
bl._forceType = bl._forceType or {}
|
|
|
|
|
local function valFromTs(val, name)
|
|
|
|
|
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
|
|
|
|
|
local nameL = name:lower()
|
|
|
|
|
if bl._forceType[nameL] then
|
|
|
|
|
local typ = bl._forceType[nameL]
|
|
|
|
|
if typ=='boolean' then
|
|
|
|
|
return tsBool(val)
|
|
|
|
|
elseif typ=='object' then
|
|
|
|
|
return toTsObject(val)
|
|
|
|
|
else
|
|
|
|
|
error('valFromTs: invalid force type '..typ, 3)
|
|
|
|
|
end
|
|
|
|
|
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
|
|
|
|
|
@@ -151,14 +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
|
|
|
|
|
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
|
|
|
|
|
@@ -199,31 +228,50 @@ function bl.isFunction(a1, a2)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Torque object pseudo-class
|
|
|
|
|
local tsClassMeta = {
|
|
|
|
|
__tostring = function(t)
|
|
|
|
|
return 'torqueClass:'..t._name..
|
|
|
|
|
(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 {}
|
|
|
|
|
bl._objectUserMetas[name] = met
|
|
|
|
|
met._name = name
|
|
|
|
|
local met = bl._objectUserMetas[cname] or {
|
|
|
|
|
_name = cname,
|
|
|
|
|
_inherit = nil,
|
|
|
|
|
_children = {},
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
local inhI = bl._objectUserMetas[name]._inherit
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
bl._objectUserMetas[name]._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)
|
|
|
|
|
@@ -259,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
|
|
|
|
|
@@ -418,7 +470,7 @@ toTsObject = function(idiS)
|
|
|
|
|
_tsObjectId = _bllua_ts.callobj(idiS, 'getId' ),
|
|
|
|
|
_tsName = _bllua_ts.callobj(idiS, 'getName' ),
|
|
|
|
|
_tsNamespace = className,
|
|
|
|
|
_tsClassName = className:lower()
|
|
|
|
|
_tsClassName = className:lower(),
|
|
|
|
|
}
|
|
|
|
|
setmetatable(obj, tsObjectMeta)
|
|
|
|
|
|
|
|
|
|
@@ -438,7 +490,7 @@ local tsMeta = {
|
|
|
|
|
__index = function(t, name)
|
|
|
|
|
if getmetatable(t)[name] then
|
|
|
|
|
return getmetatable(t)[name]
|
|
|
|
|
elseif bl._objectUserMetas[name:lower()] then
|
|
|
|
|
elseif type(name)=='string' and bl._objectUserMetas[name:lower()] then
|
|
|
|
|
return bl._objectUserMetas[name:lower()]
|
|
|
|
|
else
|
|
|
|
|
if type(name)=='number' then
|
|
|
|
|
@@ -446,7 +498,7 @@ local tsMeta = {
|
|
|
|
|
elseif name:find('::') then
|
|
|
|
|
local ns, rest = name:match('^([^:]+)::(.+)$')
|
|
|
|
|
if not ns then error('ts index: invalid name \''..name..'\'', 2) end
|
|
|
|
|
if not rest:find('::') and tsIsFunction(ns, rest) then -- tsIsFunction is only defined with one argument
|
|
|
|
|
if not rest:find('::') and tsIsFunctionNs(ns, rest) then
|
|
|
|
|
error('ts index: can\'t call a namespaced function from lua', 2)
|
|
|
|
|
else
|
|
|
|
|
return valFromTs(_bllua_ts.getvar(name), name)
|
|
|
|
|
@@ -469,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
|
|
|
|
|
@@ -479,19 +531,19 @@ 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))
|
|
|
|
|
end
|
|
|
|
|
function bl.tobool(val)
|
|
|
|
|
function bl.boolean(val)
|
|
|
|
|
return val~=nil and
|
|
|
|
|
val~=false and
|
|
|
|
|
--val~='' and
|
|
|
|
|
--val~='0' and
|
|
|
|
|
val~=0
|
|
|
|
|
end
|
|
|
|
|
function bl.toobject(id)
|
|
|
|
|
function bl.object(id)
|
|
|
|
|
if type(id)=='table' and id._tsObjectId then
|
|
|
|
|
return id
|
|
|
|
|
elseif type(id)=='string' or type(id)=='number' then
|
|
|
|
|
@@ -504,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
|
|
|
|
|
@@ -524,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,
|
|
|
|
|
@@ -534,38 +591,58 @@ function bl.schedule(time, cb, ...)
|
|
|
|
|
bl._scheduleTable[id] = sch
|
|
|
|
|
return sch
|
|
|
|
|
end
|
|
|
|
|
function _bllua_schedule_callback(id)
|
|
|
|
|
id = tonumber(id)
|
|
|
|
|
if id == nil then
|
|
|
|
|
error('_ts_schedule_callback: invalid id')
|
|
|
|
|
end
|
|
|
|
|
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('_ts_schedule_callback: no schedule with id '..id) end
|
|
|
|
|
if not sch then error('_bllua_schedule_callback: no schedule with id '..id) end
|
|
|
|
|
bl._scheduleTable[id] = nil
|
|
|
|
|
sch.callback(unpack(sch.args))
|
|
|
|
|
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)
|
|
|
|
|
@@ -586,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
|
|
|
|
|
|
|
|
|
|
@@ -632,14 +734,16 @@ function bl.hook(pkg, name, time, func)
|
|
|
|
|
updateHook(pkg, name, bl._hooks[pkg][name])
|
|
|
|
|
activatePackage(pkg)
|
|
|
|
|
end
|
|
|
|
|
local function tableEmpty(t)
|
|
|
|
|
return next(t)~=nil
|
|
|
|
|
end
|
|
|
|
|
function bl.unhook(pkg, name, time)
|
|
|
|
|
if not isValidFuncName(pkg) then
|
|
|
|
|
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
|
|
|
|
|
@@ -662,15 +766,16 @@ 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
|
|
|
|
|
if tableEmpty(bl._hooks[pkg][name]) and tableEmpty(bl._hooks[pkg]) then
|
|
|
|
|
bl._hooks[pkg] = nil
|
|
|
|
|
deactivatePackage(pkg)
|
|
|
|
|
updateHook(pkg, name, {})
|
|
|
|
|
else
|
|
|
|
|
updateHook(pkg, name, bl._hooks[pkg][name])
|
|
|
|
|
end
|
|
|
|
|
updateHook(pkg, name, bl._hooks[pkg][name])
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
--error('bl.unhook: no hooks registered for function \''..name..
|
|
|
|
|
@@ -769,10 +874,15 @@ function bl.radiusSearch(pos, radius, mask)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Print/Talk/Echo
|
|
|
|
|
local maxTsArgLen = 8192
|
|
|
|
|
local function valsToString(vals)
|
|
|
|
|
local strs = {}
|
|
|
|
|
for i,v in ipairs(vals) do
|
|
|
|
|
strs[i] = table.tostring(v)
|
|
|
|
|
local tstr = table.tostring(v)
|
|
|
|
|
if #tstr>maxTsArgLen then
|
|
|
|
|
tstr = tostring(v)
|
|
|
|
|
end
|
|
|
|
|
strs[i] = tstr
|
|
|
|
|
end
|
|
|
|
|
return table.concat(strs, ' ')
|
|
|
|
|
end
|
|
|
|
|
@@ -787,11 +897,12 @@ bl.talk = function(...)
|
|
|
|
|
_bllua_ts.call('talk', str)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- bl.new and bl.datablock
|
|
|
|
|
local function createTsObj(keyword, class, name, inherit, props)
|
|
|
|
|
local propsT = {}
|
|
|
|
|
for k,v in pairs(props) do
|
|
|
|
|
if not isValidFuncName(k) then
|
|
|
|
|
error('bl.new/datablock: invalid property name \''..k..'\'') end
|
|
|
|
|
error('bl.new/bl.datablock: invalid property name \''..k..'\'') end
|
|
|
|
|
table.insert(propsT, k..'="'..valToTs(v)..'";')
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@@ -801,7 +912,7 @@ local function createTsObj(keyword, class, name, inherit, props)
|
|
|
|
|
table.concat(propsT)..'};')
|
|
|
|
|
local obj = toTsObject(objS)
|
|
|
|
|
if not obj then
|
|
|
|
|
error('bl.new/datablock: failed to create object', 3) end
|
|
|
|
|
error('bl.new/bl.datablock: failed to create object', 3) end
|
|
|
|
|
|
|
|
|
|
return obj
|
|
|
|
|
end
|
|
|
|
|
@@ -824,7 +935,7 @@ local function parseTsDecl(decl)
|
|
|
|
|
isValidFuncName(class) and
|
|
|
|
|
(name==nil or isValidFuncName(name)) and
|
|
|
|
|
(inherit==nil or isValidFuncName(inherit)) ) then
|
|
|
|
|
error('bl.new/datablock: invalid decl \''..decl..'\'\n'..
|
|
|
|
|
error('bl.new/bl.datablock: invalid decl \''..decl..'\'\n'..
|
|
|
|
|
'must be of the format: \'className\', \'className name\', '..
|
|
|
|
|
'\'className :inherit\', or \'className name:inherit\'', 3) end
|
|
|
|
|
return class, name, inherit
|
|
|
|
|
@@ -835,6 +946,7 @@ function bl.new(decl, props)
|
|
|
|
|
end
|
|
|
|
|
function bl.datablock(decl, props)
|
|
|
|
|
local class, name, inherit = parseTsDecl(decl)
|
|
|
|
|
if not name then error('bl.datablock: must specify a name', 2) end
|
|
|
|
|
return createTsObj('datablock', class, name, inherit, props)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|