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++
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
rem objdump -d BlockLua.dll > BlockLua.dll.dump.txt
rem objdump -d BlockLua-Unsafe.dll > BlockLua-Unsafe.dll.dump.txt
pause

Binary file not shown.

View File

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

View File

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

View File

@@ -40,7 +40,7 @@ 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
`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.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
@@ -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`.
### TBD
- bl.class
- bl.new
- bl.datablock
- vector
- Extended standard library functions
## 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.
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)
return map(args, valToTs)
end
function bl.type(name,typ)
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
end
@@ -199,6 +207,12 @@ function bl.isFunction(a1, a2)
end
-- 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 {}
function bl.class(name, inherit)
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
name = name:lower()
local met = bl._objectUserMetas[name] or {}
local met = bl._objectUserMetas[name] or {
_name = name,
_inherit = nil,
_children = {},
}
bl._objectUserMetas[name] = met
met._name = name
setmetatable(met, tsClassMeta)
if inherit then
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 '..
'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
error('bl.class: argument #2: class already exists and '..
'inherits a different parent.', 2) end
bl._objectUserMetas[name]._inherit = inh
met._inherit = inh
end
end
local function objectInheritedMetas(name)
@@ -418,7 +438,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 +458,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 +466,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
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)
@@ -491,7 +511,7 @@ function bl.tobool(val)
--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
@@ -535,9 +555,9 @@ function bl.schedule(time, cb, ...)
return sch
end
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]
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
@@ -653,7 +673,7 @@ function bl.unhook(pkg, name, time)
if bl._hooks[pkg][name] then
if not time then
bl._hooks[pkg][name] = nil
if table.isempty(bl._hooks[pkg]) then
if table.empty(bl._hooks[pkg]) then
bl._hooks[pkg] = nil
deactivatePackage(pkg)
end
@@ -663,7 +683,7 @@ function bl.unhook(pkg, name, time)
error('bl.unhook: argument #3: time must be nil or one of '..
'\'before\' \'after\' \'override\'', 2) end
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
deactivatePackage(pkg)
end

View File

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