Compare commits

...

2 Commits

Author SHA1 Message Date
Redo
9c349a9352 bug and warning fixes from auios 2025-10-03 19:32:54 -05:00
Redo
34345a7eeb wip allow inheriting object method types 2025-10-03 17:47:26 -05:00
9 changed files with 53 additions and 23 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -4,10 +4,13 @@ cd /d %~dp0
set buildargs=-Wall -Werror -m32 -shared -Isrc -Iinc/tsfuncs -Iinc/lua -lpsapi -L. -llua5.1 -static-libgcc -static-libstdc++ set buildargs=-Wall -Werror -m32 -shared -Isrc -Iinc/tsfuncs -Iinc/lua -lpsapi -L. -llua5.1 -static-libgcc -static-libstdc++
echo on echo on
g++ src/bllua4.cpp %buildargs% -o BlockLua.dll && g++ -DBLLUA_UNSAFE src/bllua4.cpp %buildargs% -o BlockLua-Unsafe.dll
g++ src/bllua4.cpp %buildargs% -o BlockLua.dll
@rem && g++ -DBLLUA_UNSAFE src/bllua4.cpp %buildargs% -o BlockLua-Unsafe.dll
@rem objdump -d BlockLua.dll > BlockLua.dll.dump.txt
@rem objdump -d BlockLua-Unsafe.dll > BlockLua-Unsafe.dll.dump.txt
@echo off @echo off
rem objdump -d BlockLua.dll > BlockLua.dll.dump.txt
rem objdump -d BlockLua-Unsafe.dll > BlockLua-Unsafe.dll.dump.txt
pause pause

Binary file not shown.

View File

@@ -38,7 +38,7 @@ end
-- chains a bunch of filters together -- chains a bunch of filters together
-- (thanks to Wim Couwenberg) -- (thanks to Wim Couwenberg)
function filter.chain(...) function filter.chain(...)
local n = table.getn(arg) local n = #arg
local top, index = 1, 1 local top, index = 1, 1
local retry = "" local retry = ""
return function(chunk) return function(chunk)

View File

@@ -254,7 +254,7 @@ function parse_path(path)
path = path or "" path = path or ""
--path = string.gsub(path, "%s", "") --path = string.gsub(path, "%s", "")
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
for i = 1, table.getn(parsed) do for i = 1, #parsed do
parsed[i] = unescape(parsed[i]) parsed[i] = unescape(parsed[i])
end end
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
@@ -272,7 +272,7 @@ end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
function build_path(parsed, unsafe) function build_path(parsed, unsafe)
local path = "" local path = ""
local n = table.getn(parsed) local n = #parsed
if unsafe then if unsafe then
for i = 1, n-1 do for i = 1, n-1 do
path = path .. parsed[i] path = path .. parsed[i]

View File

@@ -40,7 +40,7 @@ Lua scripting for Blockland
### Advanced ### Advanced
`sched = bl.schedule(timeMs, function, args...)` - Schedule a Lua function to be called later, similar to schedule in Torque `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 `sched:cancel()` - Cancel a previously scheduled timer
`hitObject, hisPos, 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. `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.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. `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.serverCmd('commandName', function(client, args...) code() end)` - Register a /-command on the server
@@ -84,6 +84,13 @@ Require replaces `.` with `/` in the path, and then searches for files in the fo
Like in standard Lua, modules loaded using `require` are only executed the first time `require` is called with that path. Subsequent calls simply return the result from the initial execution. To allow hot reloading, use `dofile`. Like in standard Lua, modules loaded using `require` are only executed the first time `require` is called with that path. Subsequent calls simply return the result from the initial execution. To allow hot reloading, use `dofile`.
### TBD
- bl.class
- bl.new
- bl.datablock
- vector
- Extended standard library functions
## Type Conversion ## Type Conversion
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. 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. 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.

View File

@@ -151,13 +151,21 @@ end
local function arglistToTs(args) local function arglistToTs(args)
return map(args, valToTs) return map(args, valToTs)
end end
function bl.type(name,typ) function bl.type(name, typ)
if typ~='bool' and typ~='boolean' and typ~='object' and typ~=nil then 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 error('bl.type: can only set type to \'bool\' or \'object\' or nil', 2) end
if not isValidFuncNameNsArgn(name) then if not isValidFuncNameNsArgn(name) then
error('bl.type: invalid function or variable name \''..name..'\'', 2) end error('bl.type: invalid function or variable name \''..name..'\'', 2) end
if typ=='bool' then typ='boolean' end if typ=='bool' then typ='boolean' end
bl._forceType[name:lower()] = typ 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
end end
@@ -199,6 +207,12 @@ function bl.isFunction(a1, a2)
end end
-- Torque object pseudo-class -- Torque object pseudo-class
local tsClassMeta = {
__tostring = function(t)
return 'torqueClass:'..t._name..
(t._inherit and (':'..t._inherit) or '')
end,
}
bl._objectUserMetas = bl._objectUserMetas or {} bl._objectUserMetas = bl._objectUserMetas or {}
function bl.class(name, inherit) function bl.class(name, inherit)
if not ( type(name)=='string' and isValidFuncName(name) ) then if not ( type(name)=='string' and isValidFuncName(name) ) then
@@ -207,9 +221,13 @@ function bl.class(name, inherit)
error('bl.class: argument #2: inherit name must be a string or nil', 2) end error('bl.class: argument #2: inherit name must be a string or nil', 2) end
name = name:lower() name = name:lower()
local met = bl._objectUserMetas[name] or {} local met = bl._objectUserMetas[name] or {
_name = name,
_inherit = nil,
_children = {},
}
bl._objectUserMetas[name] = met bl._objectUserMetas[name] = met
met._name = name setmetatable(met, tsClassMeta)
if inherit then if inherit then
inherit = inherit:lower() inherit = inherit:lower()
@@ -218,12 +236,14 @@ function bl.class(name, inherit)
if not inh then error('bl.class: argument #2: \''..inherit..'\' is not the '.. if not inh then error('bl.class: argument #2: \''..inherit..'\' is not the '..
'name of an existing class', 2) end 'name of an existing class', 2) end
local inhI = bl._objectUserMetas[name]._inherit inh._children[name] = true
local inhI = met._inherit
if inhI and inhI~=inh then if inhI and inhI~=inh then
error('bl.class: argument #2: class already exists and '.. error('bl.class: argument #2: class already exists and '..
'inherits a different parent.', 2) end 'inherits a different parent.', 2) end
bl._objectUserMetas[name]._inherit = inh met._inherit = inh
end end
end end
local function objectInheritedMetas(name) local function objectInheritedMetas(name)
@@ -418,7 +438,7 @@ toTsObject = function(idiS)
_tsObjectId = _bllua_ts.callobj(idiS, 'getId' ), _tsObjectId = _bllua_ts.callobj(idiS, 'getId' ),
_tsName = _bllua_ts.callobj(idiS, 'getName' ), _tsName = _bllua_ts.callobj(idiS, 'getName' ),
_tsNamespace = className, _tsNamespace = className,
_tsClassName = className:lower() _tsClassName = className:lower(),
} }
setmetatable(obj, tsObjectMeta) setmetatable(obj, tsObjectMeta)
@@ -438,7 +458,7 @@ local tsMeta = {
__index = function(t, name) __index = function(t, name)
if getmetatable(t)[name] then if getmetatable(t)[name] then
return getmetatable(t)[name] 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()] return bl._objectUserMetas[name:lower()]
else else
if type(name)=='number' then if type(name)=='number' then
@@ -446,7 +466,7 @@ local tsMeta = {
elseif name:find('::') then elseif name:find('::') then
local ns, rest = name:match('^([^:]+)::(.+)$') local ns, rest = name:match('^([^:]+)::(.+)$')
if not ns then error('ts index: invalid name \''..name..'\'', 2) end if not ns then error('ts index: invalid name \''..name..'\'', 2) end
if not rest:find('::') and tsIsFunction(ns, rest) then if not rest:find('::') and tsIsFunctionNs(ns, rest) then
error('ts index: can\'t call a namespaced function from lua', 2) error('ts index: can\'t call a namespaced function from lua', 2)
else else
return valFromTs(_bllua_ts.getvar(name), name) return valFromTs(_bllua_ts.getvar(name), name)
@@ -491,7 +511,7 @@ function bl.tobool(val)
--val~='0' and --val~='0' and
val~=0 val~=0
end end
function bl.toobject(id) function bl.object(id)
if type(id)=='table' and id._tsObjectId then if type(id)=='table' and id._tsObjectId then
return id return id
elseif type(id)=='string' or type(id)=='number' then elseif type(id)=='string' or type(id)=='number' then
@@ -535,9 +555,9 @@ function bl.schedule(time, cb, ...)
return sch return sch
end end
function _bllua_schedule_callback(id) function _bllua_schedule_callback(id)
id = tonumber(id) id = tonumber(id) or error('_bllua_schedule_callback: invalid id: '..tostring(id))
local sch = bl._scheduleTable[id] 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 bl._scheduleTable[id] = nil
sch.callback(unpack(sch.args)) sch.callback(unpack(sch.args))
end end
@@ -653,7 +673,7 @@ function bl.unhook(pkg, name, time)
if bl._hooks[pkg][name] then if bl._hooks[pkg][name] then
if not time then if not time then
bl._hooks[pkg][name] = nil bl._hooks[pkg][name] = nil
if table.isempty(bl._hooks[pkg]) then if table.empty(bl._hooks[pkg]) then
bl._hooks[pkg] = nil bl._hooks[pkg] = nil
deactivatePackage(pkg) deactivatePackage(pkg)
end end
@@ -663,7 +683,7 @@ function bl.unhook(pkg, name, time)
error('bl.unhook: argument #3: time must be nil or one of '.. error('bl.unhook: argument #3: time must be nil or one of '..
'\'before\' \'after\' \'override\'', 2) end '\'before\' \'after\' \'override\'', 2) end
bl._hooks[pkg][name][time] = nil bl._hooks[pkg][name][time] = nil
if table.isempty(bl._hooks[pkg][name]) and table.empty(bl._hooks[pkg]) then if table.empty(bl._hooks[pkg][name]) and table.empty(bl._hooks[pkg]) then
bl._hooks[pkg] = nil bl._hooks[pkg] = nil
deactivatePackage(pkg) deactivatePackage(pkg)
end end

View File

@@ -116,13 +116,13 @@ function io.open(fn, mode, errn)
local relfn = curfn and fn:find('^%./') and local relfn = curfn and fn:find('^%./') and
curfn:gsub('[^/]+$', '')..fn:gsub('^%./', '') curfn:gsub('[^/]+$', '')..fn:gsub('^%./', '')
if relfn then if relfn then
local fi, err = io_open_absolute(relfn, mode, errn+1) local fi, err = io_open_absolute(relfn, mode)
return fi, err, relfn return fi, err, relfn
else else
return nil, 'Invalid path', fn return nil, 'Invalid path', fn
end end
else else
local fi, err = io_open_absolute(fn, mode, errn+1) local fi, err = io_open_absolute(fn, mode)
return fi, err, fn return fi, err, fn
end end
end end