From 7232ede09db7f26d601ffb18459a6e4b399f072e Mon Sep 17 00:00:00 2001 From: Redo Date: Mon, 6 Oct 2025 23:03:12 -0500 Subject: [PATCH 1/4] make :members() not return index, add -DBLLUA_ALLOWFFI, allow reading modules/lualib/, bug fixes --- BlockLua.dll | Bin 378956 -> 379468 bytes readme.md | 23 ++++++++-------- src/bllua4.cpp | 21 ++++++++------- src/lua-env-safe.lua | 20 +++++++------- src/lua-env.lua | 4 +++ src/util/libbl.lua | 58 ++++++++++++++++++++++++----------------- src/util/libts-lua.lua | 5 ++-- src/util/std.lua | 2 +- 8 files changed, 76 insertions(+), 57 deletions(-) diff --git a/BlockLua.dll b/BlockLua.dll index a11bb18335f804d638bf3b4d7a73cee0418b6557..35465213ed3821161fb55ca61e8685df6c5fb5c0 100644 GIT binary patch delta 8998 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 Date: Mon, 13 Oct 2025 12:28:16 -0500 Subject: [PATCH 2/4] support more+empty args in hooks --- BlockLua.dll | Bin 379468 -> 379980 bytes readme.md | 13 +++++--- src/util/libbl.lua | 76 ++++++++++++++++++++++++++++----------------- src/util/std.lua | 24 ++++++++++++-- 4 files changed, 77 insertions(+), 36 deletions(-) diff --git a/BlockLua.dll b/BlockLua.dll index 35465213ed3821161fb55ca61e8685df6c5fb5c0..0935a5b166396e2c573a6e0d3e79eed191e84390 100644 GIT binary patch delta 8272 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 Ruy8l}TQ@p_-sKg4`9B$8lDq%_ diff --git a/readme.md b/readme.md index f54d2d9..24fce77 100644 --- a/readme.md +++ b/readme.md @@ -143,7 +143,9 @@ WIP `string.trim(str, charsToTrim=' \t\r\n')` `table.empty` `table.map(func, ...)` +`table.mapk(func, ...)` `table.map_list(func, ...)` +`table.mapi_list(func, ...)` `table.swap(tbl)` `table.reverse(list)` `table.islist(list)` @@ -173,22 +175,23 @@ TorqueScript stores no type information; all values in TorqueScript are strings. ### From Lua to TorqueScript - `nil` becomes the empty string "" - `true` and `false` become "1" and "0" respectively -- Torque containers become their object ID +- A Torque object container becomes its object ID - A `vector` becomes a string containing three numbers separated by spaces -- A table of two vectors becomes a string containing six numbers separated by spaces +- A table of two `vector`s becomes a string containing six numbers separated by spaces +- (WIP) A `matrix` is converted into an axis-angle (a "transform"), a string containing seven numbers separated by spaces - Any `string` is passed directly as a string - Tables cannot be passed and will throw an error ### From TorqueScript to Lua -- 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` +- 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. - A string containing two or three numbers separated by single spaces becomes a `vector` - A string containing six numbers separated by single spaces becomes a table of two vectors, usually defining the corners a bounding box -- (WIP) A string containing seven numbers separated by single spaces is treated as an axis-angle (a "transform" in TorqueScript parlance), and is converted into a `matrix` representing the translation and rotation. +- (WIP) A string containing seven numbers separated by single spaces is treated as an axis-angle (a "transform"), and is converted into a `matrix` representing the translation and rotation - Any other string is passed directly as a `string` For scenarios where the automatic TorqueScript->Lua conversion rules are insufficient or incorrect, use `bl.type`. -To convert objects by hand, use `bl.object`, `bl.boolean`, or `bl.string`. +To convert things by hand, use `bl.object`, `bl.boolean`, or `bl.string`. ## I/O and Safety All Lua code is sandboxed, and file access is confined to the default directories in the same way TorqueScript is. diff --git a/src/util/libbl.lua b/src/util/libbl.lua index 878522a..c84806e 100644 --- a/src/util/libbl.lua +++ b/src/util/libbl.lua @@ -6,15 +6,30 @@ local _bllua_ts = ts bl = bl or {} +-- Config +local tsMaxArgs = 16 +local tsArgsLocal = '%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p' +local tsArgsGlobal = + '$_bllua_hook_arg1,$_bllua_hook_arg2,$_bllua_hook_arg3,$_bllua_hook_arg4,'.. + '$_bllua_hook_arg5,$_bllua_hook_arg6,$_bllua_hook_arg7,$_bllua_hook_arg8,'.. + '$_bllua_hook_arg9,$_bllua_hook_arg10,$_bllua_hook_arg11,$_bllua_hook_arg12,'.. + '$_bllua_hook_arg13,$_bllua_hook_arg14,$_bllua_hook_arg15,$_bllua_hook_arg16' + -- Misc --- Apply a function to each element in a list, building a new list from the returns -local function map(t,f) - local u = {} - for i,v in ipairs(t) do - u[i] = f(v) +local function ipairsNilable(t) + local maxk = 0 + for k,_ in pairs(t) do + if k>maxk then maxk = k end + end + local i = 0 + return function() + i = i+1 + if i>maxk then return nil + else return i, t[i] end end - return u end + +-- Validation local function isValidFuncName(name) return type(name)=='string' and name:find('^[a-zA-Z_][a-zA-Z0-9_]*$') end @@ -184,13 +199,17 @@ local function valFromTs(val, name, name2) end local function arglistFromTs(name, argsS) local args = {} - for i,arg in ipairs(argsS) do + for i,arg in ipairsNilable(argsS) do args[i] = valFromTs(arg, name..':'..i) end return args end local function arglistToTs(args) - return map(args, valToTs) + local argsS = {} + for i,v in ipairsNilable(args) do + table.insert(argsS, valToTs(v)) + end + return argsS end local function classFromForceTypeStr(name) local class, rest = name:match('^([a-zA-Z0-9_]+)(::.+)$') @@ -549,14 +568,13 @@ end local function safeNamespaceName(name) return tostring(name:gsub(':', '_')) end -local nscallArgStr = '%a,%b,%c,%d,%e,%f,%g,%h' bl._cachedNamespaceCalls = {} local function tsNamespacedCallTfname(name) local tfname = bl._cachedNamespaceCalls[name] if not tfname then tfname = '_bllua_nscall_'..safeNamespaceName(name) - local tfcode = 'function '..tfname..'('..nscallArgStr..'){'.. - name..'('..nscallArgStr..');}' + local tfcode = 'function '..tfname..'('..tsArgsLocal..'){'.. + name..'('..tsArgsLocal..');}' _bllua_ts.eval(tfcode) bl._cachedNamespaceCalls[name] = tfname end @@ -753,9 +771,8 @@ local function addCmd(cmd, func) if not isValidFuncName(cmd) then error('addCmd: invalid function name \''..tostring(cmd)..'\'') end 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..');}') + _bllua_ts.eval('function '..cmd..'('..tsArgsLocal..'){'.. + '_bllua_luacall(_bllua_process_cmd,"'..cmd..'",'..tsArgsLocal..');}') end function bl.addServerCmd(name, func) name = name:lower() @@ -803,9 +820,6 @@ 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_before(pkgS, nameS, ...) local args = arglistFromTs(nameS, {...}) @@ -819,7 +833,7 @@ function _bllua_process_hook_before(pkgS, nameS, ...) _bllua_ts.setvar('_bllua_hook_abort', '1') _bllua_ts.setvar('_bllua_hook_return', valToTs(args._return)) end - for i=1,hookNargs do + for i=1,tsMaxArgs do _bllua_ts.setvar('_bllua_hook_arg'..i, valToTs(args[i])) end end @@ -836,13 +850,13 @@ function _bllua_process_hook_after(pkgS, nameS, resultS, ...) end local function updateHook(pkg, name, hk) local beforeCode = hk.before and - ('_bllua_luacall("_bllua_process_hook_before", "'..pkg..'","'..name.. - '",'..hookArglistLocal..');') or '' - local arglist = (hk.before and hookArglistGlobal or hookArglistLocal) + ('_bllua_luacall("_bllua_process_hook_before","'..pkg..'","'..name.. + '",'..tsArgsLocal..');') or '' + local arglist = (hk.before and tsArgsGlobal or tsArgsLocal) local parentCode = tsIsFunctionNsname(name) and -- only call parent if it exists (hk.before and - 'if($_bllua_hook_abort)return $_bllua_hook_return; else ' or '').. + 'if($_bllua_hook_abort)return $_bllua_hook_return;else ' or '').. ((hk.after and '%result=' or 'return ').. 'parent::'..name:match('[^:]+$').. '('..arglist..');') or '' @@ -851,10 +865,11 @@ local function updateHook(pkg, name, hk) arglist..');') or '' local code = 'package '..pkg..'{'.. - 'function '..name..'('..hookArglistLocal..'){'.. + 'function '..name..'('..tsArgsLocal..'){'.. beforeCode..parentCode..afterCode.. '}'.. '};' + print('bl.hook eval output: [['..code..']]') _bllua_ts.eval(code) end function bl.hook(pkg, name, time, func) @@ -880,9 +895,9 @@ 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 + if name and not isValidFuncNameNs(name) then error('bl.unhook: argument #2: invalid function name \''..tostring(name)..'\'', 2) end - if time~='before' and time~='after' then + if time and time~='before' and time~='after' then error('bl.unhook: argument #3: time must be \'before\' or \'after\'', 2) end if not name then @@ -909,10 +924,13 @@ function bl.unhook(pkg, name, time) 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 tableEmpty(bl._hooks[pkg][name]) and tableEmpty(bl._hooks[pkg]) then + if tableEmpty(bl._hooks[pkg][name]) then + bl._hooks[pkg][name] = nil + end + if tableEmpty(bl._hooks[pkg]) then bl._hooks[pkg] = nil - deactivatePackage(pkg) updateHook(pkg, name, {}) + deactivatePackage(pkg) else updateHook(pkg, name, bl._hooks[pkg][name]) end @@ -968,7 +986,7 @@ function bl.raycast(start, stop, mask, ignores) local stopS = vecToTs(start) local maskS = maskToTs(mask) local ignoresS = {} - for _,v in ipairs(ignores) do + for _,v in ipairsNilable(ignores) do table.insert(ignoresS, objToTs(v)) end @@ -1017,7 +1035,7 @@ end local maxTsArgLen = 8192 local function valsToString(vals) local strs = {} - for i,v in ipairs(vals) do + for i,v in ipairsNilable(vals) do local tstr = table.tostring(v) if #tstr>maxTsArgLen then tstr = tostring(v) diff --git a/src/util/std.lua b/src/util/std.lua index 53e9e84..16a2d92 100644 --- a/src/util/std.lua +++ b/src/util/std.lua @@ -13,8 +13,18 @@ function table.map(f, ...) local u = {} for k,_ in pairs(ts[1]) do local args = {} - for j=1,#ts do args[j] = ts[j][i] end - u[i] = f(unpack(args)) + for j=1,#ts do args[j] = ts[j][k] end + u[k] = f(unpack(args)) + end + return u +end +function table.mapk(f, ...) + local ts = {...} + local u = {} + for k,_ in pairs(ts[1]) do + local args = {} + for j=1,#ts do args[j] = ts[j][k] end + u[k] = f(k, unpack(args)) end return u end @@ -28,6 +38,16 @@ function table.map_list(f, ...) end return u end +function table.mapi_list(f, ...) + local ts = {...} + local u = {} + for i=1,#ts[1] do + local args = {} + for j=1,#ts do args[j] = ts[j][i] end + u[i] = f(i, unpack(args)) + end + return u +end -- Swap keys/values function table.swap(t) local u = {} From ae34bb8b7a45ed829ae032337e83431454ae40cc Mon Sep 17 00:00:00 2001 From: Redo Date: Sun, 7 Dec 2025 11:52:40 -0500 Subject: [PATCH 3/4] fix commandToClient, handle net strings when passed to lua, misc readme additions --- BlockLua.dll | Bin 379980 -> 379980 bytes readme.md | 28 ++++++++++++++-------------- src/util/libbl.lua | 11 ++++++++--- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/BlockLua.dll b/BlockLua.dll index 0935a5b166396e2c573a6e0d3e79eed191e84390..6ba6f6dedcd4450f964d2aedc0ec98bcc81f8a4f 100644 GIT binary patch delta 6885 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 delta 6775 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 local vec = multinumericFromTs(val) if vec then return vec end + -- net string + if val:sub(1,1)=='\x01' then + return _bllua_ts.call('getTaggedString', val) + end -- string return val end @@ -676,7 +680,7 @@ luaLookup = function(tbl, name, set, val) local first, rest = name:match('^([^%.:]+)%.(.+)$') if not isValidFuncName(first) then error('luaLookup: invalid name \''..tostring(first)..'\'', 3) end - if not tbl[first] then + if tbl[first]==nil then if set then tbl[first] = {} else return nil end end @@ -691,7 +695,7 @@ luaLookup = function(tbl, name, set, val) error('luacall: invalid method name \''..tostring(first)..'\'', 3) end if not tbl[first] then error('luacall: no object named \''..rest..'\'', 3) end - if not tbl[first][rest] then + if tbl[first][rest]==nil then error('luacall: no method named \''..rest..'\'', 3) end return function(...) tbl[first][rest](tbl[first], ...) @@ -790,8 +794,9 @@ function bl.commandToServer(cmd, ...) _bllua_ts.call('addTaggedString', cmd), unpack(arglistToTs({...}))) end -function bl.commandToClient(cmd, ...) +function bl.commandToClient(client, cmd, ...) _bllua_ts.call('commandToClient', + valToTs(client), _bllua_ts.call('addTaggedString', cmd), unpack(arglistToTs({...}))) end From 2191e004adfe98bc54f605a0b99f8198b40ca7cc Mon Sep 17 00:00:00 2001 From: Redo Date: Sun, 7 Dec 2025 12:02:56 -0500 Subject: [PATCH 4/4] recompile --- BlockLua.dll | Bin 379980 -> 379980 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/BlockLua.dll b/BlockLua.dll index 6ba6f6dedcd4450f964d2aedc0ec98bcc81f8a4f..e50fcb0886aa87405e149e92442cdbdd372bf20d 100644 GIT binary patch delta 6608 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 delta 6589 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 at#{tQ*4J={wOV1>LG-M*_#L8g5&s4XRnqAI