1
0
forked from redo/BlockLua

Compare commits

...

3 Commits

17 changed files with 931 additions and 880 deletions

BIN
BlockLua.dll Normal file

Binary file not shown.

View File

@@ -9,6 +9,7 @@
#ifndef WINVER #ifndef WINVER
#define WINVER 0x0501 #define WINVER 0x0501
#endif #endif
#include <limits.h> #include <limits.h>
#include <stddef.h> #include <stddef.h>

View File

@@ -36,6 +36,8 @@ Lua scripting for Blockland
`object:method(args)` - Call a Torque object method `object:method(args)` - Call a Torque object method
`object[index]` - Access a member of a Torque set or group `object[index]` - Access a member of a Torque set or group
`for childIndex, child in object:members() do` - Iterate objects within of a Torque set or group. Indices start at 0 like in Torque. `for childIndex, child in object:members() do` - Iterate objects within of a Torque set or group. Indices start at 0 like in Torque.
`bl.isObject(object, objectID, or 'objectName')` - Check if an object exists
`object:exists()` - Check if an object exists
### Timing/Schedules ### Timing/Schedules
`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
@@ -101,10 +103,11 @@ When reading from outside ZIPs, binary files are fully supported.
`bl.type('className::funcName', 'type')` - Register the return type of a Torque object method. `bl.type('className::funcName', 'type')` - Register the return type of a Torque object method.
`bl.class('className')` - Register an existing Torque class to be used from Lua. Already done for all built-in classes. `bl.class('className')` - Register an existing Torque class to be used from Lua. Already done for all built-in classes.
`bl.class('className', 'parentClassName')` - Same as above, with inheritance `bl.class('className', 'parentClassName')` - Same as above, with inheritance
`bl.boolean(thing)` - Manually convert a Torque boolean (0 or 1) into a Lua boolean. `bl.boolean(arg)` - 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. `bl.object(arg)` - Manually convert a Torque object reference (object ID or name) into a Lua object.
`bl.string(arg)` - Manually convert any automatically-converted Torque value back into a string. This is not as reliable as using `bl.type` to specify the type as a string beforehand.
### Vectors ### Vector
`vec = vector{x,y,z}` - Create a vector. Can have any number of elements `vec = vector{x,y,z}` - Create a vector. Can have any number of elements
`vec1 + vec2` - Add `vec1 + vec2` - Add
`vec1 - vec2` - Subtract `vec1 - vec2` - Subtract
@@ -129,6 +132,9 @@ When reading from outside ZIPs, binary files are fully supported.
`vec1:distance(vec2)` - Distance between two points `vec1:distance(vec2)` - Distance between two points
`vec2 = vec:copy()` - Clone a vector so its elements can be modified without affecting the original. Usually not needed - the builtin vector functions never modify vectors in-place. `vec2 = vec:copy()` - Clone a vector so its elements can be modified without affecting the original. Usually not needed - the builtin vector functions never modify vectors in-place.
### Matrix
WIP
### Extended Standard Lua Library ### Extended Standard Lua Library
`string[index]` `string[index]`
`string[{start,stop}]` `string[{start,stop}]`
@@ -163,12 +169,7 @@ When reading from outside ZIPs, binary files are fully supported.
## 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.
### 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`
- 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
- Any other string is passed directly as a `string`
### From Lua to TorqueScript ### From Lua to TorqueScript
- `nil` becomes the empty string "" - `nil` becomes the empty string ""
- `true` and `false` become "1" and "0" respectively - `true` and `false` become "1" and "0" respectively
@@ -178,6 +179,17 @@ TorqueScript stores no type information; all values in TorqueScript are strings.
- Any `string` is passed directly as a string - Any `string` is passed directly as a string
- Tables cannot be passed and will throw an error - 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`
- 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.
- 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`.
## I/O and Safety ## I/O and Safety
All Lua code is sandboxed, and file access is confined to the default directories in the same way TorqueScript is. All Lua code is sandboxed, and file access is confined to the default directories in the same way TorqueScript is.
BlockLua also has access to any C libraries installed in the `modules/lualib` folder, so be careful throwing things in there. BlockLua also has access to any C libraries installed in the `modules/lualib` folder, so be careful throwing things in there.

View File

@@ -31,6 +31,7 @@ INCLUDE_BIN(bll_fileLuaEnv, "lua-env.lua");
INCLUDE_BIN(bll_fileTsEnv, "ts-env.cs"); INCLUDE_BIN(bll_fileTsEnv, "ts-env.cs");
INCLUDE_BIN(bll_fileLuaStd, "util/std.lua"); INCLUDE_BIN(bll_fileLuaStd, "util/std.lua");
INCLUDE_BIN(bll_fileLuaVector, "util/vector.lua"); INCLUDE_BIN(bll_fileLuaVector, "util/vector.lua");
INCLUDE_BIN(bll_fileLuaMatrix, "util/matrix.lua");
INCLUDE_BIN(bll_fileLuaLibts, "util/libts-lua.lua"); INCLUDE_BIN(bll_fileLuaLibts, "util/libts-lua.lua");
INCLUDE_BIN(bll_fileTsLibts, "util/libts-ts.cs"); INCLUDE_BIN(bll_fileTsLibts, "util/libts-ts.cs");
INCLUDE_BIN(bll_fileLuaLibbl, "util/libbl.lua"); INCLUDE_BIN(bll_fileLuaLibbl, "util/libbl.lua");
@@ -72,6 +73,7 @@ bool init() {
// Load utilities // Load utilities
BLL_LOAD_LUA(gL, bll_fileLuaStd); BLL_LOAD_LUA(gL, bll_fileLuaStd);
BLL_LOAD_LUA(gL, bll_fileLuaVector); BLL_LOAD_LUA(gL, bll_fileLuaVector);
BLL_LOAD_LUA(gL, bll_fileLuaMatrix);
BLL_LOAD_LUA(gL, bll_fileLuaLibts); BLL_LOAD_LUA(gL, bll_fileLuaLibts);
BlEval(bll_fileTsLibts); BlEval(bll_fileTsLibts);
BLL_LOAD_LUA(gL, bll_fileLuaLibbl); BLL_LOAD_LUA(gL, bll_fileLuaLibbl);

View File

@@ -143,4 +143,5 @@ debug = {
getfilename = old_debug.getfilename, -- defined in lua.env.lua getfilename = old_debug.getfilename, -- defined in lua.env.lua
} }
_bllua_ts.echo(' Executed bllua-env-safe.lua') print = _bllua_ts.echo
print(' Executed bllua-env-safe.lua')

View File

@@ -37,4 +37,5 @@ function _bllua_on_error(err)
return table.concat(tracelines, '\n') return table.concat(tracelines, '\n')
end end
_bllua_ts.echo(' Executed bllua-env.lua') print = _bllua_ts.echo
print(' Executed bllua-env.lua')

View File

@@ -5,6 +5,7 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lua.h" #include "lua.h"
#include <cstring> #include <cstring>
int bll_error_handler(lua_State *L) { int bll_error_handler(lua_State *L) {
lua_getfield(L, LUA_GLOBALSINDEX, "_bllua_on_error"); lua_getfield(L, LUA_GLOBALSINDEX, "_bllua_on_error");
if (!lua_isfunction(L, -1)) { if (!lua_isfunction(L, -1)) {

View File

@@ -3,6 +3,7 @@
#define _H_LUAINTERP_SHARED #define _H_LUAINTERP_SHARED
#include "lua.h" #include "lua.h"
#define BLL_ARG_COUNT 20 #define BLL_ARG_COUNT 20
#define BLL_ARG_MAX 8192 #define BLL_ARG_MAX 8192

View File

@@ -8,6 +8,7 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "lua.h" #include "lua.h"
#include "luainterp.hpp" #include "luainterp.hpp"
int bll_TsCall(lua_State *L, const char *oname, const char *fname, int argc, int bll_TsCall(lua_State *L, const char *oname, const char *fname, int argc,
int ofs) { int ofs) {
ADDR obj = (ADDR)NULL; ADDR obj = (ADDR)NULL;

View File

@@ -4,6 +4,7 @@
#include "BlFuncs.hpp" #include "BlFuncs.hpp"
#include "BlHooks.hpp" #include "BlHooks.hpp"
#include "luainterp.hpp" #include "luainterp.hpp"
bool bll_LuaCall(const char *fname, int argc, const char *argv[]) { bool bll_LuaCall(const char *fname, int argc, const char *argv[]) {
lua_getglobal(gL, fname); lua_getglobal(gL, fname);
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {

View File

@@ -42,4 +42,26 @@ package _bllua_objectDeletionHook {
}; };
activatePackage(_bllua_objectDeletionHook); activatePackage(_bllua_objectDeletionHook);
// 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 libbl-support.cs"); echo(" Executed libbl-support.cs");

File diff suppressed because it is too large Load Diff

View File

@@ -135,16 +135,16 @@ end
---@diagnostic disable-next-line: duplicate-set-field ---@diagnostic disable-next-line: duplicate-set-field
function io.lines(fn) function io.lines(fn)
local fi, err, fn2 = io.open(fn, 'r', 2) local fi, err, fn2 = io.open(fn, nil, 2)
if not fi then error('Error opening file \'' .. tostring(fn2) .. '\': ' .. tostring(err), 2) end if not fi then error('Error opening file \'' .. fn2 .. '\': ' .. err, 2) end
return fi:lines() return fi:lines()
end end
---@diagnostic disable-next-line: duplicate-set-field ---@diagnostic disable-next-line: duplicate-set-field
function io.type(f) function io.type(f)
---@diagnostic disable-next-line: undefined-field ---@diagnostic disable-next-line: undefined-field
if type(f) == 'table' and f._is_file then if type(f) == 'table' and f._is_file then
---@diagnostic disable-next-line: undefined-field ---@diagnostic disable-next-line: undefined-field
return f._is_open and 'file' or 'closed file' return f._is_open and 'file' or 'closed file'
else else
return _bllua_io_type(f) return _bllua_io_type(f)
@@ -156,7 +156,7 @@ function dofile(fn, errn)
errn = errn or 1 errn = errn or 1
local fi, err, fn2 = io.open(fn, 'r', errn + 1) local fi, err, fn2 = io.open(fn, 'r', errn + 1)
if not fi then error('Error executing file \'' .. tostring(fn2) .. '\': ' .. tostring(err), errn + 1) end if not fi then error('Error executing file \'' .. fn2 .. '\': ' .. err, errn + 1) end
print('Executing ' .. fn2) print('Executing ' .. fn2)
local text = fi:read('*a') local text = fi:read('*a')
@@ -183,14 +183,14 @@ function require(mod)
if require_memo[mod] then return unpack(require_memo[mod]) end if require_memo[mod] then return unpack(require_memo[mod]) end
local fp = mod:gsub('%.', '/') local fp = mod:gsub('%.', '/')
local fns = { local fns = {
'./' .. fp .. '.lua', -- local file './' .. fp .. '.lua', -- local file
'./' .. fp .. '/init.lua', -- local library './' .. fp .. '/init.lua', -- local library
fp .. '.lua', -- global file fp .. '.lua', -- global file
fp .. '/init.lua', -- global library fp .. '/init.lua', -- global library
} }
if fp:lower():find('^add-ons/') then if fp:lower():find('^add-ons/') then
local addonpath = fp:lower():match('^add-ons/[^/]+') .. '/' local addonpath = fp:lower():match('^add-ons/[^/]+') .. '/'
table.insert(fns, addonpath .. fp .. '.lua') -- add-on file table.insert(fns, addonpath .. fp .. '.lua') -- add-on file
table.insert(fns, addonpath .. fp .. '/init.lua') -- add-on library table.insert(fns, addonpath .. fp .. '/init.lua') -- add-on library
end end
for _, fn in ipairs(fns) do for _, fn in ipairs(fns) do
@@ -204,15 +204,6 @@ function require(mod)
return _bllua_requiresecure(mod) return _bllua_requiresecure(mod)
end end
-- Exposure to TS
function _bllua_getvar(name) return _G[name] end
function _bllua_setvar(name, val) _G[name] = val end
function _bllua_eval(code) return loadstring(code)() end
function _bllua_exec(fn) return dofile(fn, 2) end
local function isValidCode(code) local function isValidCode(code)
local f, e = loadstring(code) local f, e = loadstring(code)
return f ~= nil return f ~= nil

View File

@@ -49,26 +49,4 @@ function _bllua_set_var(%name, %val) {
return ""; return "";
} }
// 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"); echo(" Executed libts-ts.cs");

6
src/util/matrix.lua Normal file
View File

@@ -0,0 +1,6 @@
-- todo
-- Matrix class with math operators
print(' Executed matrix.lua')

View File

@@ -193,7 +193,7 @@ valueToString = function(v, tabLevel, seen)
return tostring(v) return tostring(v)
else else
--error('table.tostring: table contains a '..t..' value, cannot serialize') --error('table.tostring: table contains a '..t..' value, cannot serialize')
return 'nil --[[ cannot serialize ' .. t .. ': ' .. tostring(v) .. ' ]]' return 'nil --[[ cannot serialize ' .. tostring(v) .. ' ]]'
end end
end end
function table.tostring(t) function table.tostring(t)
@@ -372,3 +372,5 @@ end
function math.clamp(v, n, x) function math.clamp(v, n, x)
return math.min(x, math.max(v, n)) return math.min(x, math.max(v, n))
end end
print(' Executed std.lua')

View File

@@ -235,4 +235,7 @@ vector_new = function(vi)
end end
vector = vector_new vector = vector_new
print(' Executed vector.lua')
return vector_new return vector_new