No Description

Redo 12b6f46365 remove module and file extension whitelists, update readme 1 year ago
Script_LuaTest e62f2f3ddf add relative file paths 2 years ago
lua a0da5b3bdc initial commit 2 years ago
tsfuncs a0da5b3bdc initial commit 2 years ago
bllua3.cpp 760dc1dc4d add asm and s extensions, bux fixes 2 years ago
bllua3.dll 12b6f46365 remove module and file extension whitelists, update readme 1 year ago
compile.bat 6270e29529 modify readme and gitignore 2 years ago
env.lua 12b6f46365 remove module and file extension whitelists, update readme 1 year ago
luainterp.cpp 160ea59a4f add stack trace to error messages, add relative file access 2 years ago
readme.md 12b6f46365 remove module and file extension whitelists, update readme 1 year ago
util.cs a0da5b3bdc initial commit 2 years ago
util.lua 24d6db3778 misc old updates 1 year ago

readme.md

BlLua3

Simple Lua interface for TorqueScript
by Redo (12878)

How to install

Easy way:

  1. Install RedBlocklandLoader from https://gitlab.com/Eagle517/redblocklandloader/-/releases
  2. Download and place bllua3.dll in the modules folder: https://notabug.org/redo/bllua3/raw/master/bllua3.dll

Hard way:

  1. Have GCC installed
  2. Compile and install RedBlocklandLoader
  3. Clone this repo
  4. Run compile.bat
  5. Put the resulting bllua3.dll in the modules folder

Documentation

In TorqueScript

The API exposed to TS consists of only five functions:

luaeval(string) - Execute Lua code and return the result (Slow, use luacall where possible)
    luaeval("print(\"Hello, world.\")"); -> Hello, world.
    echo(luaeval("return 5*5")); -> 25

luacall(name, args) - Call a global Lua function and return the result (Much faster than luaeval)
    luacall("print", "Hello, world."); -> Hello, world.
    echo(luacall("user_square_lua", 5)); -> 25
    echo(luacall("user_multiply_lua", 2, 3)); -> 6

luaexec(filename) - Execute a Lua code file within the Blockland game directory
    luaexec("Add-ons/Client_LuaTest/test.lua"); - Executes test.lua

luaset(name, value) - Set the value of a Lua global variable
    luaset("some_lua_var", "hello, world"); - set the Lua variable some_lua_var to "hello, world"

luaget(name) - Get the value of a Lua global variable
    echo(luaget("some_lua_var")); -> hello, world (assuming the above code was also run)

In Lua

There is also an API exposed to Lua. It provides the following functions:

ts.eval(string) - Eval TS code and return the result (Slow, use ts.call where possible)     ts.eval("echo(\"Hello, world.\")") -> Hello, world.
    print(ts.eval("mPow(5, 2);")) -> 25
    This can be used in conjunction with Lua's double bracket syntax to eval multi-line blocks of TS code,
    useful for writing glue code within Lua files.

ts.call(name, args...) - Call a TS function and return the result (Much faster than ts.eval)
    ts.call("echo", "Hello, world.") -> Hello, world.
    local client = ts.call("findClientByName", name) - Get a client with the given name
    All return values from TS calls are strings, so you can use     tonumber(numberFromTs) if you expect a numeric value,
    and ts.toBoolean(booleanFromTs) if you expect a boolean value.
    Object IDs are strings, but can be converted to numbers
    Returned object IDs or names can be can be passed straight into ts.call or ts.callobj without issue.

ts.callobj(object, name, args...) - Call a TS function on an object and return the result.
    ts.callobj("Sky", "delete") - Delete the sky - equivalent to Sky.delete(); in TS
    local color = tonumber(ts.callobj(brick, "getColorId")) - Get the color ID of a brick
    The object argument can be an object ID as a number or string, or an object name as a string.

ts.set(name, value) - Set the value of a TS global variable
    ts.set("Pref::server::adminPassword", "cake") - Set the admin password to cake

ts.get(name) - Get the value of a TS global variable
    print(ts.get("pi")) -> 3.14159 (The value of the TS global variable $pi)

ts.getobj(object, name) - Get the value of a field in a TS object
    if ts.getobj(client, "isAdmin")~="1" then return end - Abort if the client object is not admin
    Note: ts.getobj does not support tagged fields (fields defined within the engine), only script-defined fields.

ts.setobj(object, name, value) - Set the value of a field in a TS object
    ts.setobj(client, "isAdmin", 0) - Make client not admin
    Note: ts.setobj does not support tagged fields (fields defined within the engine), only script-defined fields.

schedule(time, function, [args...]) - Schedule a lua function call using the TS scheduler
    schedule(1000, print, "hi") - print hi after 1 second (1000 ms)
    Returns an identifier which can be used to cancel the schedule

cancel(schedule) - Cancel a lua schedule
    local quit_sched = schedule(5000, ts.call, "quit") - Quit after 5 seconds, unless...
    cancel(quit_sched) - Cancel that schedule and don't quit

For convenience, you can eval lua in the in-game console by prepending a ' (single quote).
    echo("hello world from ts"); -> hello world from ts
    'print("hello world from lua") -> hello world from lua

Notes about I/O in Lua

For safety, I/O functions are sanitized; io.open and io.lines
    accept Blockland-relative paths according to the same rules as for opening files in TS;
    with the exception that they can also open .lua files and some binary formats.
    local f = io.open("config/client/data.txt", "a"); f:write("some data\n"); f:close();
    for line in io.lines("saves/House.bls") do print(line) end

Lua I/O functions work on files inside zips, but can only read, not write.
    The current implementation also does not allow Lua to read binary files inside zips
    (though accessing binary files outside zips is fine), as it cannot handle null bytes
    or distinguish between LF and CRLF.

The normal Lua dofile function is also modified to accept Blockland-relative paths -
    it is implemented the same as the TS API's luaexec function.
    dofile("Add-ons/Script_LuaTest/test.lua") - Executes test.lua
    It is possible to exec lua files inside zips, just like normal.

All Lua I/O functions are able to use relative paths just like in TS.
    dofile("./test2.lua")
    local fi = io.open("./data/some_data.dat")
    luaexec also works with relative paths.
    luaexec("./component.lua");

Using Lua Packages

To use third-party Lua libraries, place them in a folder called luainc within the Blockland folder.
    You can then use the require function as normal.
    require("mylib")
    Unlike other locations within the Blockland folder, the luainc directory is read-only to bllua.

To use Lua C libraries (.dll files), configure LUA_CPATH as you would for normal Lua, and     use require as normal.
    You will also need to add the package's name to the list of allowed C packages,
    found on line 71 of env.lua, and recompile bllua3.

A recommended install is my collection of Lua libraries, found at https://notabug.org/redo/luainc
    Just clone these files directly into the luainc folder as described above.