Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b328f0b21a | |||
| 71b73c816b | |||
| c5dc8b15f9 | |||
| d494f02fe3 | |||
| a7db0d8e81 | |||
| 33f5ec9bbe | |||
| f6bf18efaa | |||
| 4f42801da6 | |||
| 15f67e0eef | |||
| 5885dcbed3 | |||
| d9a416f5d5 | |||
| ed5c254480 | |||
| 5718ba8e6b | |||
| a4f78b7425 | |||
| e47f6d4651 | |||
| 93a47d54be | |||
| 87e199ea5c | |||
| 66ed695010 | |||
| e309e2427b | |||
| ee784869f1 | |||
| 0815a6d229 | |||
| cbd0c29495 | |||
| 01f216f31e | |||
| f447c039c7 | |||
| 30fa81f513 | |||
| 1144504ac3 | |||
| ce3f7c8b3f | |||
| 4d74df209e |
42
.clang-format
Normal file
42
.clang-format
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
# Include sorting and grouping
|
||||||
|
SortIncludes: CaseSensitive
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '<Windows\.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '<Psapi\.h>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '"BlHooks\\.hpp"'
|
||||||
|
Priority: 3
|
||||||
|
- Regex: '"BlFuncs\\.hpp"'
|
||||||
|
Priority: 4
|
||||||
|
- Regex: ".*"
|
||||||
|
Priority: 5
|
||||||
|
|
||||||
|
# Indentation settings
|
||||||
|
IndentWidth: 2
|
||||||
|
UseTab: Never
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
AccessModifierOffset: 0
|
||||||
|
NamespaceIndentation: All
|
||||||
|
|
||||||
|
# Line breaking and wrapping
|
||||||
|
ColumnLimit: 120
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
|
||||||
|
# Alignment
|
||||||
|
AlignOperands: DontAlign
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
PointerAlignment: Left
|
||||||
|
|
||||||
|
# Parameter formatting
|
||||||
|
BinPackParameters: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
|
||||||
|
# Code organization
|
||||||
|
SeparateDefinitionBlocks: Always
|
||||||
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
.*
|
build/
|
||||||
!.gitignore
|
.cache/
|
||||||
|
|||||||
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"Lua.diagnostics.globals": [
|
||||||
|
"_bllua_ts",
|
||||||
|
"_bllua_requiresecure",
|
||||||
|
"_bllua_on_unload"
|
||||||
|
],
|
||||||
|
"Lua.runtime.version": "Lua 5.1",
|
||||||
|
"Lua.diagnostics.disable": ["lowercase-global", "undefined-global"],
|
||||||
|
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||||
|
"C_Cpp.default.compilerPath": "C:/msys64/mingw32/bin/g++.exe"
|
||||||
|
}
|
||||||
BIN
BlockLua.dll
BIN
BlockLua.dll
Binary file not shown.
56
CMakeLists.txt
Normal file
56
CMakeLists.txt
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(BlockLua CXX)
|
||||||
|
|
||||||
|
# Export compile_commands.json for VSCode IntelliSense
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
# Output directories to mirror build.bat's build folder
|
||||||
|
set(OUTPUT_DIR ${CMAKE_SOURCE_DIR}/build)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||||
|
|
||||||
|
# Global build options to mirror build.bat
|
||||||
|
add_compile_options(
|
||||||
|
-Wall
|
||||||
|
-Werror
|
||||||
|
-m32
|
||||||
|
-static-libgcc
|
||||||
|
-static-libstdc++
|
||||||
|
)
|
||||||
|
|
||||||
|
# Include paths
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_SOURCE_DIR}/src
|
||||||
|
${CMAKE_SOURCE_DIR}/inc/tsfuncs
|
||||||
|
${CMAKE_SOURCE_DIR}/inc/lua
|
||||||
|
)
|
||||||
|
|
||||||
|
# Link directories (for -L.) and libraries from build.bat
|
||||||
|
link_directories(
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Safe DLL
|
||||||
|
add_library(BlockLua SHARED src/bllua4.cpp)
|
||||||
|
# Ensure output name matches build.bat
|
||||||
|
set_target_properties(BlockLua PROPERTIES OUTPUT_NAME "BlockLua")
|
||||||
|
# Linker flags and libraries
|
||||||
|
if(MSVC)
|
||||||
|
# Not expected with mingw, but keep placeholder
|
||||||
|
else()
|
||||||
|
target_link_libraries(BlockLua PRIVATE psapi lua5.1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Unsafe DLL (with BLLUA_UNSAFE definition)
|
||||||
|
add_library(BlockLuaUnsafe SHARED src/bllua4.cpp)
|
||||||
|
set_target_properties(BlockLuaUnsafe PROPERTIES OUTPUT_NAME "BlockLua-Unsafe")
|
||||||
|
|
||||||
|
target_compile_definitions(BlockLuaUnsafe PRIVATE BLLUA_UNSAFE)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
# Not expected with mingw, but keep placeholder
|
||||||
|
else()
|
||||||
|
target_link_libraries(BlockLuaUnsafe PRIVATE psapi lua5.1)
|
||||||
|
endif()
|
||||||
27
build.bat
Normal file
27
build.bat
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
@echo off
|
||||||
|
cd /d %~dp0
|
||||||
|
|
||||||
|
REM Ensure MinGW32 toolchain is first in PATH
|
||||||
|
set "PATH=C:\msys64\mingw32\bin;%PATH%"
|
||||||
|
|
||||||
|
REM Configure CMake (generate into build/)
|
||||||
|
cmake -S . -B build -G "MinGW Makefiles"
|
||||||
|
if errorlevel 1 goto :error
|
||||||
|
|
||||||
|
REM Build (Release by default)
|
||||||
|
cmake --build build --config Release -j
|
||||||
|
if errorlevel 1 goto :error
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Build completed.
|
||||||
|
echo Outputs in .\build :
|
||||||
|
echo - BlockLua.dll
|
||||||
|
|
||||||
|
echo - BlockLua-Unsafe.dll
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
|
:error
|
||||||
|
echo.
|
||||||
|
echo Build failed. See errors above.
|
||||||
|
exit /b 1
|
||||||
52
compiling.md
Normal file
52
compiling.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
## Compiling on Windows with MSYS2 (32-bit)
|
||||||
|
|
||||||
|
Follow these steps to build `BlockLua.dll` for 32-bit Windows using MSYS2's MinGW-w64 i686 toolchain.
|
||||||
|
|
||||||
|
### 1) Install MSYS2
|
||||||
|
|
||||||
|
- Download and install MSYS2 from `https://www.msys2.org/`.
|
||||||
|
- After installing, open the "MSYS2 MSYS" terminal once and update the package database if prompted.
|
||||||
|
|
||||||
|
### 2) Install required packages (i686 / 32-bit)
|
||||||
|
|
||||||
|
Run this in the "MSYS2 MSYS" or "MSYS2 MinGW 32-bit" terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pacman -Sy --needed mingw-w64-i686-toolchain mingw-w64-i686-binutils mingw-w64-i686-lua51
|
||||||
|
```
|
||||||
|
|
||||||
|
What these packages are for:
|
||||||
|
|
||||||
|
- mingw-w64-i686-toolchain: 32-bit C/C++ compiler suite (g++, libstdc++, runtime libs) to build Windows binaries.
|
||||||
|
- mingw-w64-i686-binutils: Linker and binary utilities (ld, as, objdump) used by the compiler and for optional inspection.
|
||||||
|
- mingw-w64-i686-lua51: Lua 5.1 development files for 32-bit (import library). We use its import library to link; at runtime you can use the provided `lua5.1.dll`.
|
||||||
|
|
||||||
|
### 3) Build (PowerShell, recommended)
|
||||||
|
|
||||||
|
- Open PowerShell in the repo root.
|
||||||
|
- Run the script:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
build.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
What the script does:
|
||||||
|
|
||||||
|
- Temporarily prepends `C:\\msys64\\mingw32\\bin` to PATH so the 32-bit toolchain is used.
|
||||||
|
- Compiles the project with `-m32` and links against `lua5.1`.
|
||||||
|
- Produces `build\BlockLua.dll` and `build\BlockLua-Unsafe.dll`.
|
||||||
|
|
||||||
|
### 4) Optional: Verify 32-bit output
|
||||||
|
|
||||||
|
If you installed binutils, you can check the architecture:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
objdump -f build\BlockLua.dll | Select-String i386
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see `architecture: i386` in the output.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- Ensure you installed the i686 (32-bit) variants of the packages; x86_64 packages won't work for a 32-bit build.
|
||||||
|
- If the linker cannot find `-llua5.1`, confirm `mingw-w64-i686-lua51` is installed and you are using the `mingw32` toolchain (not `x86_64`).
|
||||||
@@ -4,17 +4,14 @@
|
|||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef lauxlib_h
|
#ifndef lauxlib_h
|
||||||
#define lauxlib_h
|
#define lauxlib_h
|
||||||
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
||||||
/* extra error code for `luaL_load' */
|
/* extra error code for `luaL_load' */
|
||||||
#define LUA_ERRFILE (LUA_ERRERR + 1)
|
#define LUA_ERRFILE (LUA_ERRERR + 1)
|
||||||
|
|
||||||
@@ -23,24 +20,19 @@ typedef struct luaL_Reg {
|
|||||||
lua_CFunction func;
|
lua_CFunction func;
|
||||||
} luaL_Reg;
|
} luaL_Reg;
|
||||||
|
|
||||||
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
|
LUALIB_API void(luaL_openlib)(lua_State* L, const char* libname, const luaL_Reg* l, int nup);
|
||||||
const luaL_Reg *l, int nup);
|
LUALIB_API void(luaL_register)(lua_State* L, const char* libname, const luaL_Reg* l);
|
||||||
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
|
||||||
const luaL_Reg *l);
|
|
||||||
LUALIB_API int(luaL_getmetafield)(lua_State* L, int obj, const char* e);
|
LUALIB_API int(luaL_getmetafield)(lua_State* L, int obj, const char* e);
|
||||||
LUALIB_API int(luaL_callmeta)(lua_State* L, int obj, const char* e);
|
LUALIB_API int(luaL_callmeta)(lua_State* L, int obj, const char* e);
|
||||||
LUALIB_API int(luaL_typerror)(lua_State* L, int narg, const char* tname);
|
LUALIB_API int(luaL_typerror)(lua_State* L, int narg, const char* tname);
|
||||||
LUALIB_API int(luaL_argerror)(lua_State* L, int numarg, const char* extramsg);
|
LUALIB_API int(luaL_argerror)(lua_State* L, int numarg, const char* extramsg);
|
||||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
|
LUALIB_API const char*(luaL_checklstring)(lua_State * L, int numArg, size_t* l);
|
||||||
size_t *l);
|
LUALIB_API const char*(luaL_optlstring)(lua_State * L, int numArg, const char* def, size_t* l);
|
||||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
|
|
||||||
const char *def, size_t *l);
|
|
||||||
LUALIB_API lua_Number(luaL_checknumber)(lua_State* L, int numArg);
|
LUALIB_API lua_Number(luaL_checknumber)(lua_State* L, int numArg);
|
||||||
LUALIB_API lua_Number(luaL_optnumber)(lua_State* L, int nArg, lua_Number def);
|
LUALIB_API lua_Number(luaL_optnumber)(lua_State* L, int nArg, lua_Number def);
|
||||||
|
|
||||||
LUALIB_API lua_Integer(luaL_checkinteger)(lua_State* L, int numArg);
|
LUALIB_API lua_Integer(luaL_checkinteger)(lua_State* L, int numArg);
|
||||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
|
LUALIB_API lua_Integer(luaL_optinteger)(lua_State* L, int nArg, lua_Integer def);
|
||||||
lua_Integer def);
|
|
||||||
|
|
||||||
LUALIB_API void(luaL_checkstack)(lua_State* L, int sz, const char* msg);
|
LUALIB_API void(luaL_checkstack)(lua_State* L, int sz, const char* msg);
|
||||||
LUALIB_API void(luaL_checktype)(lua_State* L, int narg, int t);
|
LUALIB_API void(luaL_checktype)(lua_State* L, int narg, int t);
|
||||||
@@ -52,8 +44,7 @@ LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
|||||||
LUALIB_API void(luaL_where)(lua_State* L, int lvl);
|
LUALIB_API void(luaL_where)(lua_State* L, int lvl);
|
||||||
LUALIB_API int(luaL_error)(lua_State* L, const char* fmt, ...);
|
LUALIB_API int(luaL_error)(lua_State* L, const char* fmt, ...);
|
||||||
|
|
||||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
LUALIB_API int(luaL_checkoption)(lua_State* L, int narg, const char* def, const char* const lst[]);
|
||||||
const char *const lst[]);
|
|
||||||
|
|
||||||
/* pre-defined references */
|
/* pre-defined references */
|
||||||
#define LUA_NOREF (-2)
|
#define LUA_NOREF (-2)
|
||||||
@@ -63,43 +54,33 @@ LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
|||||||
LUALIB_API void(luaL_unref)(lua_State* L, int t, int ref);
|
LUALIB_API void(luaL_unref)(lua_State* L, int t, int ref);
|
||||||
|
|
||||||
LUALIB_API int(luaL_loadfile)(lua_State* L, const char* filename);
|
LUALIB_API int(luaL_loadfile)(lua_State* L, const char* filename);
|
||||||
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
|
LUALIB_API int(luaL_loadbuffer)(lua_State* L, const char* buff, size_t sz, const char* name);
|
||||||
const char *name);
|
|
||||||
LUALIB_API int(luaL_loadstring)(lua_State* L, const char* s);
|
LUALIB_API int(luaL_loadstring)(lua_State* L, const char* s);
|
||||||
|
|
||||||
LUALIB_API lua_State*(luaL_newstate)(void);
|
LUALIB_API lua_State*(luaL_newstate)(void);
|
||||||
|
|
||||||
|
LUALIB_API const char*(luaL_gsub)(lua_State * L, const char* s, const char* p, const char* r);
|
||||||
|
|
||||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
LUALIB_API const char*(luaL_findtable)(lua_State * L, int idx, const char* fname, int szhint);
|
||||||
const char *r);
|
|
||||||
|
|
||||||
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
|
|
||||||
const char *fname, int szhint);
|
|
||||||
|
|
||||||
/* From Lua 5.2. */
|
/* From Lua 5.2. */
|
||||||
LUALIB_API int luaL_fileresult(lua_State* L, int stat, const char* fname);
|
LUALIB_API int luaL_fileresult(lua_State* L, int stat, const char* fname);
|
||||||
LUALIB_API int luaL_execresult(lua_State* L, int stat);
|
LUALIB_API int luaL_execresult(lua_State* L, int stat);
|
||||||
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
LUALIB_API int(luaL_loadfilex)(lua_State* L, const char* filename, const char* mode);
|
||||||
const char *mode);
|
LUALIB_API int(luaL_loadbufferx)(lua_State* L, const char* buff, size_t sz, const char* name, const char* mode);
|
||||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
LUALIB_API void luaL_traceback(lua_State* L, lua_State* L1, const char* msg, int level);
|
||||||
const char *name, const char *mode);
|
|
||||||
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
|
||||||
int level);
|
|
||||||
LUALIB_API void(luaL_setfuncs)(lua_State* L, const luaL_Reg* l, int nup);
|
LUALIB_API void(luaL_setfuncs)(lua_State* L, const luaL_Reg* l, int nup);
|
||||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
LUALIB_API void(luaL_pushmodule)(lua_State* L, const char* modname, int sizehint);
|
||||||
int sizehint);
|
|
||||||
LUALIB_API void*(luaL_testudata)(lua_State * L, int ud, const char* tname);
|
LUALIB_API void*(luaL_testudata)(lua_State * L, int ud, const char* tname);
|
||||||
LUALIB_API void(luaL_setmetatable)(lua_State* L, const char* tname);
|
LUALIB_API void(luaL_setmetatable)(lua_State* L, const char* tname);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** ===============================================================
|
** ===============================================================
|
||||||
** some useful macros
|
** some useful macros
|
||||||
** ===============================================================
|
** ===============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define luaL_argcheck(L, cond,numarg,extramsg) \
|
#define luaL_argcheck(L, cond, numarg, extramsg) ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
|
||||||
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
|
|
||||||
#define luaL_checkstring(L, n) (luaL_checklstring(L, (n), NULL))
|
#define luaL_checkstring(L, n) (luaL_checklstring(L, (n), NULL))
|
||||||
#define luaL_optstring(L, n, d) (luaL_optlstring(L, (n), (d), NULL))
|
#define luaL_optstring(L, n, d) (luaL_optlstring(L, (n), (d), NULL))
|
||||||
#define luaL_checkint(L, n) ((int)luaL_checkinteger(L, (n)))
|
#define luaL_checkint(L, n) ((int)luaL_checkinteger(L, (n)))
|
||||||
@@ -109,19 +90,16 @@ LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
|||||||
|
|
||||||
#define luaL_typename(L, i) lua_typename(L, lua_type(L, (i)))
|
#define luaL_typename(L, i) lua_typename(L, lua_type(L, (i)))
|
||||||
|
|
||||||
#define luaL_dofile(L, fn) \
|
#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
|
||||||
|
|
||||||
#define luaL_dostring(L, s) \
|
#define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||||
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
|
||||||
|
|
||||||
#define luaL_getmetatable(L, n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
#define luaL_getmetatable(L, n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
||||||
|
|
||||||
#define luaL_opt(L, f, n, d) (lua_isnoneornil(L, (n)) ? (d) : f(L, (n)))
|
#define luaL_opt(L, f, n, d) (lua_isnoneornil(L, (n)) ? (d) : f(L, (n)))
|
||||||
|
|
||||||
/* From Lua 5.2. */
|
/* From Lua 5.2. */
|
||||||
#define luaL_newlibtable(L, l) \
|
#define luaL_newlibtable(L, l) lua_createtable(L, 0, sizeof(l) / sizeof((l)[0]) - 1)
|
||||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
|
||||||
#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0))
|
#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -130,8 +108,6 @@ LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
|||||||
** =======================================================
|
** =======================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct luaL_Buffer {
|
typedef struct luaL_Buffer {
|
||||||
char* p; /* current position in buffer */
|
char* p; /* current position in buffer */
|
||||||
int lvl; /* number of strings in the stack (level) */
|
int lvl; /* number of strings in the stack (level) */
|
||||||
@@ -140,8 +116,7 @@ typedef struct luaL_Buffer {
|
|||||||
} luaL_Buffer;
|
} luaL_Buffer;
|
||||||
|
|
||||||
#define luaL_addchar(B, c) \
|
#define luaL_addchar(B, c) \
|
||||||
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
|
((void)((B)->p < ((B)->buffer + LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), (*(B)->p++ = (char)(c)))
|
||||||
(*(B)->p++ = (char)(c)))
|
|
||||||
|
|
||||||
/* compatibility only */
|
/* compatibility only */
|
||||||
#define luaL_putchar(B, c) luaL_addchar(B, c)
|
#define luaL_putchar(B, c) luaL_addchar(B, c)
|
||||||
@@ -155,7 +130,6 @@ LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
|
|||||||
LUALIB_API void(luaL_addvalue)(luaL_Buffer* B);
|
LUALIB_API void(luaL_addvalue)(luaL_Buffer* B);
|
||||||
LUALIB_API void(luaL_pushresult)(luaL_Buffer* B);
|
LUALIB_API void(luaL_pushresult)(luaL_Buffer* B);
|
||||||
|
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,31 +5,26 @@
|
|||||||
** See Copyright Notice at the end of this file
|
** See Copyright Notice at the end of this file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef lua_h
|
#ifndef lua_h
|
||||||
#define lua_h
|
#define lua_h
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
#include "luaconf.h"
|
#include "luaconf.h"
|
||||||
|
|
||||||
|
|
||||||
#define LUA_VERSION "Lua 5.1"
|
#define LUA_VERSION "Lua 5.1"
|
||||||
#define LUA_RELEASE "Lua 5.1.4"
|
#define LUA_RELEASE "Lua 5.1.4"
|
||||||
#define LUA_VERSION_NUM 501
|
#define LUA_VERSION_NUM 501
|
||||||
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
|
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
|
||||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
||||||
|
|
||||||
|
|
||||||
/* mark for precompiled code (`<esc>Lua') */
|
/* mark for precompiled code (`<esc>Lua') */
|
||||||
#define LUA_SIGNATURE "\033Lua"
|
#define LUA_SIGNATURE "\033Lua"
|
||||||
|
|
||||||
/* option for multiple returns in `lua_pcall' and `lua_call' */
|
/* option for multiple returns in `lua_pcall' and `lua_call' */
|
||||||
#define LUA_MULTRET (-1)
|
#define LUA_MULTRET (-1)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** pseudo-indices
|
** pseudo-indices
|
||||||
*/
|
*/
|
||||||
@@ -38,7 +33,6 @@
|
|||||||
#define LUA_GLOBALSINDEX (-10002)
|
#define LUA_GLOBALSINDEX (-10002)
|
||||||
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX - (i))
|
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX - (i))
|
||||||
|
|
||||||
|
|
||||||
/* thread status */
|
/* thread status */
|
||||||
#define LUA_OK 0
|
#define LUA_OK 0
|
||||||
#define LUA_YIELD 1
|
#define LUA_YIELD 1
|
||||||
@@ -47,12 +41,10 @@
|
|||||||
#define LUA_ERRMEM 4
|
#define LUA_ERRMEM 4
|
||||||
#define LUA_ERRERR 5
|
#define LUA_ERRERR 5
|
||||||
|
|
||||||
|
|
||||||
typedef struct lua_State lua_State;
|
typedef struct lua_State lua_State;
|
||||||
|
|
||||||
typedef int (*lua_CFunction)(lua_State* L);
|
typedef int (*lua_CFunction)(lua_State* L);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** functions that read/write blocks when loading/dumping Lua chunks
|
** functions that read/write blocks when loading/dumping Lua chunks
|
||||||
*/
|
*/
|
||||||
@@ -60,13 +52,11 @@ typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
|
|||||||
|
|
||||||
typedef int (*lua_Writer)(lua_State* L, const void* p, size_t sz, void* ud);
|
typedef int (*lua_Writer)(lua_State* L, const void* p, size_t sz, void* ud);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** prototype for memory-allocation functions
|
** prototype for memory-allocation functions
|
||||||
*/
|
*/
|
||||||
typedef void* (*lua_Alloc)(void* ud, void* ptr, size_t osize, size_t nsize);
|
typedef void* (*lua_Alloc)(void* ud, void* ptr, size_t osize, size_t nsize);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** basic types
|
** basic types
|
||||||
*/
|
*/
|
||||||
@@ -82,12 +72,9 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
|||||||
#define LUA_TUSERDATA 7
|
#define LUA_TUSERDATA 7
|
||||||
#define LUA_TTHREAD 8
|
#define LUA_TTHREAD 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* minimum Lua stack available to a C function */
|
/* minimum Lua stack available to a C function */
|
||||||
#define LUA_MINSTACK 20
|
#define LUA_MINSTACK 20
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** generic extra include file
|
** generic extra include file
|
||||||
*/
|
*/
|
||||||
@@ -95,16 +82,12 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
|||||||
#include LUA_USER_H
|
#include LUA_USER_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* type of numbers in Lua */
|
/* type of numbers in Lua */
|
||||||
typedef LUA_NUMBER lua_Number;
|
typedef LUA_NUMBER lua_Number;
|
||||||
|
|
||||||
|
|
||||||
/* type for integer functions */
|
/* type for integer functions */
|
||||||
typedef LUA_INTEGER lua_Integer;
|
typedef LUA_INTEGER lua_Integer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** state manipulation
|
** state manipulation
|
||||||
*/
|
*/
|
||||||
@@ -114,7 +97,6 @@ LUA_API lua_State *(lua_newthread) (lua_State *L);
|
|||||||
|
|
||||||
LUA_API lua_CFunction(lua_atpanic)(lua_State* L, lua_CFunction panicf);
|
LUA_API lua_CFunction(lua_atpanic)(lua_State* L, lua_CFunction panicf);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** basic stack manipulation
|
** basic stack manipulation
|
||||||
*/
|
*/
|
||||||
@@ -128,7 +110,6 @@ LUA_API int (lua_checkstack) (lua_State *L, int sz);
|
|||||||
|
|
||||||
LUA_API void(lua_xmove)(lua_State* from, lua_State* to, int n);
|
LUA_API void(lua_xmove)(lua_State* from, lua_State* to, int n);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** access functions (stack -> C)
|
** access functions (stack -> C)
|
||||||
*/
|
*/
|
||||||
@@ -154,7 +135,6 @@ LUA_API void *(lua_touserdata) (lua_State *L, int idx);
|
|||||||
LUA_API lua_State*(lua_tothread)(lua_State * L, int idx);
|
LUA_API lua_State*(lua_tothread)(lua_State * L, int idx);
|
||||||
LUA_API const void*(lua_topointer)(lua_State * L, int idx);
|
LUA_API const void*(lua_topointer)(lua_State * L, int idx);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** push functions (C -> stack)
|
** push functions (C -> stack)
|
||||||
*/
|
*/
|
||||||
@@ -163,15 +143,13 @@ LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
|
|||||||
LUA_API void(lua_pushinteger)(lua_State* L, lua_Integer n);
|
LUA_API void(lua_pushinteger)(lua_State* L, lua_Integer n);
|
||||||
LUA_API void(lua_pushlstring)(lua_State* L, const char* s, size_t l);
|
LUA_API void(lua_pushlstring)(lua_State* L, const char* s, size_t l);
|
||||||
LUA_API void(lua_pushstring)(lua_State* L, const char* s);
|
LUA_API void(lua_pushstring)(lua_State* L, const char* s);
|
||||||
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
|
LUA_API const char*(lua_pushvfstring)(lua_State * L, const char* fmt, va_list argp);
|
||||||
va_list argp);
|
|
||||||
LUA_API const char*(lua_pushfstring)(lua_State * L, const char* fmt, ...);
|
LUA_API const char*(lua_pushfstring)(lua_State * L, const char* fmt, ...);
|
||||||
LUA_API void(lua_pushcclosure)(lua_State* L, lua_CFunction fn, int n);
|
LUA_API void(lua_pushcclosure)(lua_State* L, lua_CFunction fn, int n);
|
||||||
LUA_API void(lua_pushboolean)(lua_State* L, int b);
|
LUA_API void(lua_pushboolean)(lua_State* L, int b);
|
||||||
LUA_API void(lua_pushlightuserdata)(lua_State* L, void* p);
|
LUA_API void(lua_pushlightuserdata)(lua_State* L, void* p);
|
||||||
LUA_API int(lua_pushthread)(lua_State* L);
|
LUA_API int(lua_pushthread)(lua_State* L);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** get functions (Lua -> stack)
|
** get functions (Lua -> stack)
|
||||||
*/
|
*/
|
||||||
@@ -184,7 +162,6 @@ LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
|
|||||||
LUA_API int(lua_getmetatable)(lua_State* L, int objindex);
|
LUA_API int(lua_getmetatable)(lua_State* L, int objindex);
|
||||||
LUA_API void(lua_getfenv)(lua_State* L, int idx);
|
LUA_API void(lua_getfenv)(lua_State* L, int idx);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** set functions (stack -> Lua)
|
** set functions (stack -> Lua)
|
||||||
*/
|
*/
|
||||||
@@ -195,19 +172,16 @@ LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
|
|||||||
LUA_API int(lua_setmetatable)(lua_State* L, int objindex);
|
LUA_API int(lua_setmetatable)(lua_State* L, int objindex);
|
||||||
LUA_API int(lua_setfenv)(lua_State* L, int idx);
|
LUA_API int(lua_setfenv)(lua_State* L, int idx);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** `load' and `call' functions (load and run Lua code)
|
** `load' and `call' functions (load and run Lua code)
|
||||||
*/
|
*/
|
||||||
LUA_API void(lua_call)(lua_State* L, int nargs, int nresults);
|
LUA_API void(lua_call)(lua_State* L, int nargs, int nresults);
|
||||||
LUA_API int(lua_pcall)(lua_State* L, int nargs, int nresults, int errfunc);
|
LUA_API int(lua_pcall)(lua_State* L, int nargs, int nresults, int errfunc);
|
||||||
LUA_API int(lua_cpcall)(lua_State* L, lua_CFunction func, void* ud);
|
LUA_API int(lua_cpcall)(lua_State* L, lua_CFunction func, void* ud);
|
||||||
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
|
LUA_API int(lua_load)(lua_State* L, lua_Reader reader, void* dt, const char* chunkname);
|
||||||
const char *chunkname);
|
|
||||||
|
|
||||||
LUA_API int(lua_dump)(lua_State* L, lua_Writer writer, void* data);
|
LUA_API int(lua_dump)(lua_State* L, lua_Writer writer, void* data);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** coroutine functions
|
** coroutine functions
|
||||||
*/
|
*/
|
||||||
@@ -231,7 +205,6 @@ LUA_API int (lua_status) (lua_State *L);
|
|||||||
|
|
||||||
LUA_API int(lua_gc)(lua_State* L, int what, int data);
|
LUA_API int(lua_gc)(lua_State* L, int what, int data);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** miscellaneous functions
|
** miscellaneous functions
|
||||||
*/
|
*/
|
||||||
@@ -245,8 +218,6 @@ LUA_API void (lua_concat) (lua_State *L, int n);
|
|||||||
LUA_API lua_Alloc(lua_getallocf)(lua_State* L, void** ud);
|
LUA_API lua_Alloc(lua_getallocf)(lua_State* L, void** ud);
|
||||||
LUA_API void lua_setallocf(lua_State* L, lua_Alloc f, void* ud);
|
LUA_API void lua_setallocf(lua_State* L, lua_Alloc f, void* ud);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** ===============================================================
|
** ===============================================================
|
||||||
** some useful macros
|
** some useful macros
|
||||||
@@ -272,16 +243,13 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
|
|||||||
#define lua_isnone(L, n) (lua_type(L, (n)) == LUA_TNONE)
|
#define lua_isnone(L, n) (lua_type(L, (n)) == LUA_TNONE)
|
||||||
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
|
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
|
||||||
|
|
||||||
#define lua_pushliteral(L, s) \
|
#define lua_pushliteral(L, s) lua_pushlstring(L, "" s, (sizeof(s) / sizeof(char)) - 1)
|
||||||
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
|
|
||||||
|
|
||||||
#define lua_setglobal(L, s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
|
#define lua_setglobal(L, s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
|
||||||
#define lua_getglobal(L, s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
|
#define lua_getglobal(L, s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
|
||||||
|
|
||||||
#define lua_tostring(L, i) lua_tolstring(L, (i), NULL)
|
#define lua_tostring(L, i) lua_tolstring(L, (i), NULL)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** compatibility macros and functions
|
** compatibility macros and functions
|
||||||
*/
|
*/
|
||||||
@@ -295,18 +263,15 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
|
|||||||
#define lua_Chunkreader lua_Reader
|
#define lua_Chunkreader lua_Reader
|
||||||
#define lua_Chunkwriter lua_Writer
|
#define lua_Chunkwriter lua_Writer
|
||||||
|
|
||||||
|
|
||||||
/* hack */
|
/* hack */
|
||||||
LUA_API void lua_setlevel(lua_State* from, lua_State* to);
|
LUA_API void lua_setlevel(lua_State* from, lua_State* to);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** {======================================================================
|
** {======================================================================
|
||||||
** Debug API
|
** Debug API
|
||||||
** =======================================================================
|
** =======================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Event codes
|
** Event codes
|
||||||
*/
|
*/
|
||||||
@@ -316,7 +281,6 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to);
|
|||||||
#define LUA_HOOKCOUNT 3
|
#define LUA_HOOKCOUNT 3
|
||||||
#define LUA_HOOKTAILRET 4
|
#define LUA_HOOKTAILRET 4
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Event masks
|
** Event masks
|
||||||
*/
|
*/
|
||||||
@@ -327,11 +291,9 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to);
|
|||||||
|
|
||||||
typedef struct lua_Debug lua_Debug; /* activation record */
|
typedef struct lua_Debug lua_Debug; /* activation record */
|
||||||
|
|
||||||
|
|
||||||
/* Functions to be called by the debuger in specific events */
|
/* Functions to be called by the debuger in specific events */
|
||||||
typedef void (*lua_Hook)(lua_State* L, lua_Debug* ar);
|
typedef void (*lua_Hook)(lua_State* L, lua_Debug* ar);
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_getstack(lua_State* L, int level, lua_Debug* ar);
|
LUA_API int lua_getstack(lua_State* L, int level, lua_Debug* ar);
|
||||||
LUA_API int lua_getinfo(lua_State* L, const char* what, lua_Debug* ar);
|
LUA_API int lua_getinfo(lua_State* L, const char* what, lua_Debug* ar);
|
||||||
LUA_API const char* lua_getlocal(lua_State* L, const lua_Debug* ar, int n);
|
LUA_API const char* lua_getlocal(lua_State* L, const lua_Debug* ar, int n);
|
||||||
@@ -346,8 +308,7 @@ LUA_API int lua_gethookcount (lua_State *L);
|
|||||||
/* From Lua 5.2. */
|
/* From Lua 5.2. */
|
||||||
LUA_API void* lua_upvalueid(lua_State* L, int idx, int n);
|
LUA_API void* lua_upvalueid(lua_State* L, int idx, int n);
|
||||||
LUA_API void lua_upvaluejoin(lua_State* L, int idx1, int n1, int idx2, int n2);
|
LUA_API void lua_upvaluejoin(lua_State* L, int idx1, int n1, int idx2, int n2);
|
||||||
LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *dt,
|
LUA_API int lua_loadx(lua_State* L, lua_Reader reader, void* dt, const char* chunkname, const char* mode);
|
||||||
const char *chunkname, const char *mode);
|
|
||||||
LUA_API const lua_Number* lua_version(lua_State* L);
|
LUA_API const lua_Number* lua_version(lua_State* L);
|
||||||
LUA_API void lua_copy(lua_State* L, int fromidx, int toidx);
|
LUA_API void lua_copy(lua_State* L, int fromidx, int toidx);
|
||||||
LUA_API lua_Number lua_tonumberx(lua_State* L, int idx, int* isnum);
|
LUA_API lua_Number lua_tonumberx(lua_State* L, int idx, int* isnum);
|
||||||
@@ -356,7 +317,6 @@ LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum);
|
|||||||
/* From Lua 5.3. */
|
/* From Lua 5.3. */
|
||||||
LUA_API int lua_isyieldable(lua_State* L);
|
LUA_API int lua_isyieldable(lua_State* L);
|
||||||
|
|
||||||
|
|
||||||
struct lua_Debug {
|
struct lua_Debug {
|
||||||
int event;
|
int event;
|
||||||
const char* name; /* (n) */
|
const char* name; /* (n) */
|
||||||
@@ -374,7 +334,6 @@ struct lua_Debug {
|
|||||||
|
|
||||||
/* }====================================================================== */
|
/* }====================================================================== */
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -398,5 +357,4 @@ struct lua_Debug {
|
|||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// C++ wrapper for LuaJIT header files.
|
// C++ wrapper for LuaJIT header files.
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "lua.h"
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lua.h"
|
||||||
#include "luajit.h"
|
#include "luajit.h"
|
||||||
|
#include "lualib.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
@@ -20,10 +21,8 @@
|
|||||||
*/
|
*/
|
||||||
#define LUA_LDIR "!\\lua\\"
|
#define LUA_LDIR "!\\lua\\"
|
||||||
#define LUA_CDIR "!\\"
|
#define LUA_CDIR "!\\"
|
||||||
#define LUA_PATH_DEFAULT \
|
#define LUA_PATH_DEFAULT ".\\?.lua;" LUA_LDIR "?.lua;" LUA_LDIR "?\\init.lua;"
|
||||||
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;"
|
#define LUA_CPATH_DEFAULT ".\\?.dll;" LUA_CDIR "?.dll;" LUA_CDIR "loadall.dll"
|
||||||
#define LUA_CPATH_DEFAULT \
|
|
||||||
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
|
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
** Note to distribution maintainers: do NOT patch the following lines!
|
** Note to distribution maintainers: do NOT patch the following lines!
|
||||||
@@ -77,9 +76,7 @@
|
|||||||
#define LUA_PATH_MARK "?"
|
#define LUA_PATH_MARK "?"
|
||||||
#define LUA_EXECDIR "!"
|
#define LUA_EXECDIR "!"
|
||||||
#define LUA_IGMARK "-"
|
#define LUA_IGMARK "-"
|
||||||
#define LUA_PATH_CONFIG \
|
#define LUA_PATH_CONFIG LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" LUA_EXECDIR "\n" LUA_IGMARK "\n"
|
||||||
LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \
|
|
||||||
LUA_EXECDIR "\n" LUA_IGMARK "\n"
|
|
||||||
|
|
||||||
/* Quoting in error messages. */
|
/* Quoting in error messages. */
|
||||||
#define LUA_QL(x) "'" x "'"
|
#define LUA_QL(x) "'" x "'"
|
||||||
@@ -144,9 +141,16 @@
|
|||||||
#define lua_assert(x) assert(x)
|
#define lua_assert(x) assert(x)
|
||||||
#endif
|
#endif
|
||||||
#ifdef LUA_USE_APICHECK
|
#ifdef LUA_USE_APICHECK
|
||||||
#define luai_apicheck(L, o) { (void)L; assert(o); }
|
#define luai_apicheck(L, o) \
|
||||||
|
{ \
|
||||||
|
(void)L; \
|
||||||
|
assert(o); \
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#define luai_apicheck(L, o) { (void)L; }
|
#define luai_apicheck(L, o) \
|
||||||
|
{ \
|
||||||
|
(void)L; \
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -65,13 +65,10 @@ enum {
|
|||||||
LUA_API int luaJIT_setmode(lua_State* L, int idx, int mode);
|
LUA_API int luaJIT_setmode(lua_State* L, int idx, int mode);
|
||||||
|
|
||||||
/* Low-overhead profiling API. */
|
/* Low-overhead profiling API. */
|
||||||
typedef void (*luaJIT_profile_callback)(void *data, lua_State *L,
|
typedef void (*luaJIT_profile_callback)(void* data, lua_State* L, int samples, int vmstate);
|
||||||
int samples, int vmstate);
|
LUA_API void luaJIT_profile_start(lua_State* L, const char* mode, luaJIT_profile_callback cb, void* data);
|
||||||
LUA_API void luaJIT_profile_start(lua_State *L, const char *mode,
|
|
||||||
luaJIT_profile_callback cb, void *data);
|
|
||||||
LUA_API void luaJIT_profile_stop(lua_State* L);
|
LUA_API void luaJIT_profile_stop(lua_State* L);
|
||||||
LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt,
|
LUA_API const char* luaJIT_profile_dumpstack(lua_State* L, const char* fmt, int depth, size_t* len);
|
||||||
int depth, size_t *len);
|
|
||||||
|
|
||||||
/* Enforce (dynamic) linker error for version mismatches. Call from main. */
|
/* Enforce (dynamic) linker error for version mismatches. Call from main. */
|
||||||
LUA_API void LUAJIT_VERSION_SYM(void);
|
LUA_API void LUAJIT_VERSION_SYM(void);
|
||||||
|
|||||||
@@ -2,15 +2,18 @@
|
|||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
// BlFuncs Version 1.0
|
// BlFuncs Version 1.0
|
||||||
|
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#include "BlHooks.hpp"
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
#include "BlFuncs.hpp"
|
#include "BlFuncs.hpp"
|
||||||
|
#include <Windows.h>
|
||||||
|
#include "BlHooks.hpp"
|
||||||
|
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <cstring>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
// Scanned structures
|
// Scanned structures
|
||||||
|
|
||||||
ADDR tsf_mCacheSequence;
|
ADDR tsf_mCacheSequence;
|
||||||
@@ -33,7 +36,6 @@ BlFunctionDefIntern(tsf_BlSimObject__getDataField );
|
|||||||
BlFunctionDefIntern(tsf_BlSimObject__setDataField);
|
BlFunctionDefIntern(tsf_BlSimObject__setDataField);
|
||||||
BlFunctionDefIntern(tsf_BlCon__getReturnBuffer);
|
BlFunctionDefIntern(tsf_BlCon__getReturnBuffer);
|
||||||
|
|
||||||
|
|
||||||
// C->TS Args
|
// C->TS Args
|
||||||
|
|
||||||
char* tsf_GetIntArg(signed int value) {
|
char* tsf_GetIntArg(signed int value) {
|
||||||
@@ -41,21 +43,21 @@ char* tsf_GetIntArg(signed int value) {
|
|||||||
snprintf(ret, 16, "%d", value);
|
snprintf(ret, 16, "%d", value);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* tsf_GetFloatArg(float value) {
|
char* tsf_GetFloatArg(float value) {
|
||||||
char* ret = tsf_BlStringStack__getArgBuffer(32);
|
char* ret = tsf_BlStringStack__getArgBuffer(32);
|
||||||
snprintf(ret, 32, "%g", value);
|
snprintf(ret, 32, "%g", value);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* tsf_GetStringArg(char* value) {
|
char* tsf_GetStringArg(char* value) {
|
||||||
int len = strlen(value) + 1;
|
int len = strlen(value) + 1;
|
||||||
char* ret = tsf_BlStringStack__getArgBuffer(len);
|
char* ret = tsf_BlStringStack__getArgBuffer(len);
|
||||||
memcpy(ret, value, len);
|
memcpy(ret, value, len);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
char* tsf_GetThisArg(ADDR obj) {
|
|
||||||
return tsf_GetIntArg(*(signed int *)(obj + 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
char* tsf_GetThisArg(ADDR obj) { return tsf_GetIntArg(*(signed int*)(obj + 32)); }
|
||||||
|
|
||||||
// Eval
|
// Eval
|
||||||
|
|
||||||
@@ -74,24 +76,23 @@ const char* tsf_Evalf(const char *fmt, ...) {
|
|||||||
return tsf_Eval((const char*)code);
|
return tsf_Eval((const char*)code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
|
|
||||||
ADDR tsf_FindObject(unsigned int id) {
|
ADDR tsf_FindObject(unsigned int id) {
|
||||||
ADDR obj = *(ADDR*)(*(ADDR*)(tsf_gIdDictionary) + 4 * (id & 0xFFF));
|
ADDR obj = *(ADDR*)(*(ADDR*)(tsf_gIdDictionary) + 4 * (id & 0xFFF));
|
||||||
if(!obj) return 0;
|
if (!obj)
|
||||||
|
return 0;
|
||||||
|
|
||||||
while (obj && *(unsigned int*)(obj + 32) != id) {
|
while (obj && *(unsigned int*)(obj + 32) != id) {
|
||||||
obj = *(ADDR*)(obj + 16);
|
obj = *(ADDR*)(obj + 16);
|
||||||
if(!obj) return 0;
|
if (!obj)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADDR tsf_FindObject(const char* name) {
|
ADDR tsf_FindObject(const char* name) { return (ADDR)tsf_BlSim__findObject_name(name); }
|
||||||
return (ADDR)tsf_BlSim__findObject_name(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
ADDR tsf_LookupNamespace(const char* ns, const char* package) {
|
ADDR tsf_LookupNamespace(const char* ns, const char* package) {
|
||||||
const char* ste_package;
|
const char* ste_package;
|
||||||
@@ -108,10 +109,8 @@ ADDR tsf_LookupNamespace(const char* ns, const char* package) {
|
|||||||
return tsf_BlNamespace__find(nullptr, ste_package);
|
return tsf_BlNamespace__find(nullptr, ste_package);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ADDR tsf_LookupNamespace(const char* ns) {
|
|
||||||
return tsf_LookupNamespace(ns, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ADDR tsf_LookupNamespace(const char* ns) { return tsf_LookupNamespace(ns, nullptr); }
|
||||||
|
|
||||||
// Object Fields
|
// Object Fields
|
||||||
|
|
||||||
@@ -137,34 +136,32 @@ void tsf_SetDataField(ADDR simObject, const char* slotName, const char* array, c
|
|||||||
tsf_BlSimObject__setDataField(simObject, ste_slotName, array, value);
|
tsf_BlSimObject__setDataField(simObject, ste_slotName, array, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TS Global Variables
|
// TS Global Variables
|
||||||
|
|
||||||
const char *tsf_GetVar(const char* name) {
|
const char* tsf_GetVar(const char* name) { return tsf_BlCon__getVariable(name); }
|
||||||
return tsf_BlCon__getVariable(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsf_AddVarInternal(const char* name, signed int varType, void* data) {
|
void tsf_AddVarInternal(const char* name, signed int varType, void* data) {
|
||||||
tsf_BlDictionary__addVariable((ADDR*)tsf_gEvalState_globalVars, name, varType, data);
|
tsf_BlDictionary__addVariable((ADDR*)tsf_gEvalState_globalVars, name, varType, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tsf_AddVar(const char* name, const char** data) {
|
void tsf_AddVar(const char* name, const char** data) { tsf_AddVarInternal(name, 10, data); }
|
||||||
tsf_AddVarInternal(name, 10, data);
|
|
||||||
}
|
|
||||||
void tsf_AddVar(const char* name, signed int* data) {
|
|
||||||
tsf_AddVarInternal(name, 4, data);
|
|
||||||
}
|
|
||||||
void tsf_AddVar(const char* name, float* data) {
|
|
||||||
tsf_AddVarInternal(name, 8, data);
|
|
||||||
}
|
|
||||||
void tsf_AddVar(const char* name, bool* data) {
|
|
||||||
tsf_AddVarInternal(name, 6, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void tsf_AddVar(const char* name, signed int* data) { tsf_AddVarInternal(name, 4, data); }
|
||||||
|
|
||||||
|
void tsf_AddVar(const char* name, float* data) { tsf_AddVarInternal(name, 8, data); }
|
||||||
|
|
||||||
|
void tsf_AddVar(const char* name, bool* data) { tsf_AddVarInternal(name, 6, data); }
|
||||||
|
|
||||||
// TS->C Functions
|
// TS->C Functions
|
||||||
|
|
||||||
ADDR tsf_AddConsoleFuncInternal(const char* pname, const char* cname, const char* fname, signed int cbtype, const char* usage, signed int mina, signed int maxa) {
|
ADDR tsf_AddConsoleFuncInternal(
|
||||||
|
const char* pname,
|
||||||
|
const char* cname,
|
||||||
|
const char* fname,
|
||||||
|
signed int cbtype,
|
||||||
|
const char* usage,
|
||||||
|
signed int mina,
|
||||||
|
signed int maxa) {
|
||||||
const char* ste_fname = tsf_BlStringTable__insert(fname, 0);
|
const char* ste_fname = tsf_BlStringTable__insert(fname, 0);
|
||||||
ADDR ns = tsf_LookupNamespace(cname, pname);
|
ADDR ns = tsf_LookupNamespace(cname, pname);
|
||||||
ADDR ent = tsf_BlNamespace__createLocalEntry(ns, ste_fname);
|
ADDR ent = tsf_BlNamespace__createLocalEntry(ns, ste_fname);
|
||||||
@@ -180,50 +177,121 @@ ADDR tsf_AddConsoleFuncInternal(const char* pname, const char* cname, const char
|
|||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tsf_AddConsoleFunc(const char* pname, const char* cname, const char* fname, tsf_StringCallback sc, const char* usage, signed int mina, signed int maxa) {
|
void tsf_AddConsoleFunc(
|
||||||
|
const char* pname,
|
||||||
|
const char* cname,
|
||||||
|
const char* fname,
|
||||||
|
tsf_StringCallback sc,
|
||||||
|
const char* usage,
|
||||||
|
signed int mina,
|
||||||
|
signed int maxa) {
|
||||||
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 1, usage, mina, maxa);
|
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 1, usage, mina, maxa);
|
||||||
*(tsf_StringCallback*)(ent + 40) = sc;
|
*(tsf_StringCallback*)(ent + 40) = sc;
|
||||||
}
|
}
|
||||||
void tsf_AddConsoleFunc(const char* pname, const char* cname, const char* fname, tsf_IntCallback ic, const char* usage, signed int mina, signed int maxa) {
|
|
||||||
|
void tsf_AddConsoleFunc(
|
||||||
|
const char* pname,
|
||||||
|
const char* cname,
|
||||||
|
const char* fname,
|
||||||
|
tsf_IntCallback ic,
|
||||||
|
const char* usage,
|
||||||
|
signed int mina,
|
||||||
|
signed int maxa) {
|
||||||
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 2, usage, mina, maxa);
|
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 2, usage, mina, maxa);
|
||||||
*(tsf_IntCallback*)(ent + 40) = ic;
|
*(tsf_IntCallback*)(ent + 40) = ic;
|
||||||
}
|
}
|
||||||
void tsf_AddConsoleFunc(const char* pname, const char* cname, const char* fname, tsf_FloatCallback fc, const char* usage, signed int mina, signed int maxa) {
|
|
||||||
|
void tsf_AddConsoleFunc(
|
||||||
|
const char* pname,
|
||||||
|
const char* cname,
|
||||||
|
const char* fname,
|
||||||
|
tsf_FloatCallback fc,
|
||||||
|
const char* usage,
|
||||||
|
signed int mina,
|
||||||
|
signed int maxa) {
|
||||||
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 3, usage, mina, maxa);
|
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 3, usage, mina, maxa);
|
||||||
*(tsf_FloatCallback*)(ent + 40) = fc;
|
*(tsf_FloatCallback*)(ent + 40) = fc;
|
||||||
}
|
}
|
||||||
void tsf_AddConsoleFunc(const char* pname, const char* cname, const char* fname, tsf_VoidCallback vc, const char* usage, signed int mina, signed int maxa) {
|
|
||||||
|
void tsf_AddConsoleFunc(
|
||||||
|
const char* pname,
|
||||||
|
const char* cname,
|
||||||
|
const char* fname,
|
||||||
|
tsf_VoidCallback vc,
|
||||||
|
const char* usage,
|
||||||
|
signed int mina,
|
||||||
|
signed int maxa) {
|
||||||
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 4, usage, mina, maxa);
|
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 4, usage, mina, maxa);
|
||||||
*(tsf_VoidCallback*)(ent + 40) = vc;
|
*(tsf_VoidCallback*)(ent + 40) = vc;
|
||||||
}
|
}
|
||||||
void tsf_AddConsoleFunc(const char* pname, const char* cname, const char* fname, tsf_BoolCallback bc, const char* usage, signed int mina, signed int maxa) {
|
|
||||||
|
void tsf_AddConsoleFunc(
|
||||||
|
const char* pname,
|
||||||
|
const char* cname,
|
||||||
|
const char* fname,
|
||||||
|
tsf_BoolCallback bc,
|
||||||
|
const char* usage,
|
||||||
|
signed int mina,
|
||||||
|
signed int maxa) {
|
||||||
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 5, usage, mina, maxa);
|
ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 5, usage, mina, maxa);
|
||||||
*(tsf_BoolCallback*)(ent + 40) = bc;
|
*(tsf_BoolCallback*)(ent + 40) = bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
||||||
bool tsf_InitInternal() {
|
bool tsf_InitInternal() {
|
||||||
BlScanFunctionText(tsf_BlStringTable__insert, "83 EC 0C 80 3D ? ? ? ? ?");
|
BlScanFunctionText(tsf_BlStringTable__insert, "83 EC 0C 80 3D ? ? ? ? ?");
|
||||||
BlScanFunctionText(tsf_BlNamespace__find , "55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 83 EC 0C 53 56 57 A1 ? ? ? ? 33 C5 50 8D 45 F4 64 A3 ? ? ? ? 8B DA 8B D1" );
|
BlScanFunctionText(
|
||||||
BlScanFunctionText(tsf_BlNamespace__createLocalEntry, "55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 83 EC 08 53 56 57 A1 ? ? ? ? 33 C5 50 8D 45 F4 64 A3 ? ? ? ? 89 4D F0" );
|
tsf_BlNamespace__find,
|
||||||
BlScanFunctionText(tsf_BlDataChunker__freeBlocks , "55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 51 53 56 57 A1 ? ? ? ? 33 C5 50 8D 45 F4 64 A3 ? ? ? ? 8B D9 8B 33" );
|
"55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 83 EC 0C 53 56 57 A1 ? ? ? ? "
|
||||||
BlScanFunctionText(tsf_BlCon__evaluate , "55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 56 57 A1 ? ? ? ? 33 C5 50 8D 45 F4 64 A3 ? ? ? ? 8B 75 10" );
|
"33 C5 50 8D 45 F4 64 A3 ? ? ? ? 8B DA 8B D1");
|
||||||
BlScanFunctionText(tsf_BlCon__executef , "81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 53 55 56 8B B4 24 ? ? ? ? 33 C9" );
|
BlScanFunctionText(
|
||||||
BlScanFunctionText(tsf_BlCon__executefSimObj , "81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 53 56 8B B4 24 ? ? ? ? 33 C9" );
|
tsf_BlNamespace__createLocalEntry,
|
||||||
|
"55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 83 EC 08 53 56 57 A1 ? ? ? ? "
|
||||||
|
"33 C5 50 8D 45 F4 64 A3 ? ? ? ? 89 4D F0");
|
||||||
|
BlScanFunctionText(
|
||||||
|
tsf_BlDataChunker__freeBlocks,
|
||||||
|
"55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 51 53 56 57 "
|
||||||
|
"A1 ? ? ? ? 33 C5 50 8D 45 F4 64 A3 ? ? ? ? 8B D9 8B 33");
|
||||||
|
BlScanFunctionText(
|
||||||
|
tsf_BlCon__evaluate,
|
||||||
|
"55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 56 57 A1 ? ? "
|
||||||
|
"? ? 33 C5 50 8D 45 F4 64 A3 ? ? ? ? 8B 75 10");
|
||||||
|
BlScanFunctionText(
|
||||||
|
tsf_BlCon__executef,
|
||||||
|
"81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 53 55 56 "
|
||||||
|
"8B B4 24 ? ? ? ? 33 C9");
|
||||||
|
BlScanFunctionText(
|
||||||
|
tsf_BlCon__executefSimObj,
|
||||||
|
"81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 53 56 8B "
|
||||||
|
"B4 24 ? ? ? ? 33 C9");
|
||||||
BlScanFunctionText(tsf_BlCon__getVariable, "53 56 8B F1 57 85 F6 0F 84 ? ? ? ?");
|
BlScanFunctionText(tsf_BlCon__getVariable, "53 56 8B F1 57 85 F6 0F 84 ? ? ? ?");
|
||||||
BlScanFunctionText(tsf_BlDictionary__addVariable, "8B 44 24 04 56 57 8B F9");
|
BlScanFunctionText(tsf_BlDictionary__addVariable, "8B 44 24 04 56 57 8B F9");
|
||||||
BlScanFunctionText(tsf_BlSim__findObject_name, "57 8B F9 8A 17");
|
BlScanFunctionText(tsf_BlSim__findObject_name, "57 8B F9 8A 17");
|
||||||
BlScanFunctionText(tsf_BlStringStack__getArgBuffer , "55 8B EC 83 E4 F8 8B 0D ? ? ? ? A1 ? ? ? ? 56 57 8B 7D 08 8D 14 01 03 D7 3B 15 ? ? ? ? 72 2C 8B 0D" );
|
BlScanFunctionText(
|
||||||
|
tsf_BlStringStack__getArgBuffer,
|
||||||
|
"55 8B EC 83 E4 F8 8B 0D ? ? ? ? A1 ? ? ? ? 56 57 8B 7D "
|
||||||
|
"08 8D 14 01 03 D7 3B 15 ? ? ? ? 72 2C 8B 0D");
|
||||||
BlScanFunctionText(tsf_BlSimObject__getDataField, "51 53 8B D9 55 56 8B 74 24 14");
|
BlScanFunctionText(tsf_BlSimObject__getDataField, "51 53 8B D9 55 56 8B 74 24 14");
|
||||||
BlScanFunctionText(tsf_BlSimObject__setDataField , "81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 8B 84 24 ? ? ? ? 53 8B D9 89 44 24 04" );
|
BlScanFunctionText(
|
||||||
|
tsf_BlSimObject__setDataField,
|
||||||
|
"81 EC ? ? ? ? A1 ? ? ? ? 33 C4 89 84 24 ? ? ? ? 8B 84 24 "
|
||||||
|
"? ? ? ? 53 8B D9 89 44 24 04");
|
||||||
BlScanFunctionText(tsf_BlCon__getReturnBuffer, "81 F9 ? ? ? ? 76 2B");
|
BlScanFunctionText(tsf_BlCon__getReturnBuffer, "81 F9 ? ? ? ? 76 2B");
|
||||||
|
|
||||||
ADDR BlScanText (tsf_mCacheSequenceLoc , "FF 05 ? ? ? ? B9 ? ? ? ? 8B F8 E8 ? ? ? ? 8B 44 24 1C 89 47 18 8B 44 24 14" );
|
ADDR BlScanText(
|
||||||
ADDR BlScanText (tsf_mCacheAllocatorLoc , "89 35 ? ? ? ? C7 06 ? ? ? ? A1 ? ? ? ? 68 ? ? ? ? C7 40 ? ? ? ? ? E8 ? ? ? ? 83 C4 04 8B 4D F4 64 89 0D ? ? ? ? 59 5E 8B E5 5D C3");
|
tsf_mCacheSequenceLoc,
|
||||||
|
"FF 05 ? ? ? ? B9 ? ? ? ? 8B F8 E8 ? ? ? ? 8B 44 24 1C 89 47 "
|
||||||
|
"18 8B 44 24 14");
|
||||||
|
ADDR BlScanText(
|
||||||
|
tsf_mCacheAllocatorLoc,
|
||||||
|
"89 35 ? ? ? ? C7 06 ? ? ? ? A1 ? ? ? ? 68 ? ? ? ? C7 40 ? ? ? ? ? E8 ? "
|
||||||
|
"? ? ? 83 C4 04 8B 4D F4 64 89 0D ? ? ? ? 59 5E 8B E5 5D C3");
|
||||||
ADDR BlScanText(tsf_gIdDictionaryLoc, "89 15 ? ? ? ? E8 ? ? ? ? 8B F0 89 75 F0");
|
ADDR BlScanText(tsf_gIdDictionaryLoc, "89 15 ? ? ? ? E8 ? ? ? ? 8B F0 89 75 F0");
|
||||||
ADDR BlScanText (tsf_gEvalState_globalVarsLoc , "B9 ? ? ? ? E8 ? ? ? ? 68 ? ? ? ? 6A 0A 68 ? ? ? ? B9 ? ? ? ? E8 ? ? ? ? E8 ? ? ? ?" );
|
ADDR BlScanText(
|
||||||
|
tsf_gEvalState_globalVarsLoc,
|
||||||
|
"B9 ? ? ? ? E8 ? ? ? ? 68 ? ? ? ? 6A 0A 68 ? ? ? ? B9 ? ? ? "
|
||||||
|
"? E8 ? ? ? ? E8 ? ? ? ?");
|
||||||
|
|
||||||
tsf_mCacheSequence = *(ADDR*)(tsf_mCacheSequenceLoc + 2);
|
tsf_mCacheSequence = *(ADDR*)(tsf_mCacheSequenceLoc + 2);
|
||||||
tsf_mCacheAllocator = *(ADDR*)(tsf_mCacheAllocatorLoc + 2);
|
tsf_mCacheAllocator = *(ADDR*)(tsf_mCacheAllocatorLoc + 2);
|
||||||
@@ -233,6 +301,4 @@ bool tsf_InitInternal() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tsf_DeinitInternal() {
|
bool tsf_DeinitInternal() { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#ifndef _H_BLFUNCS
|
#ifndef _H_BLFUNCS
|
||||||
#define _H_BLFUNCS
|
#define _H_BLFUNCS
|
||||||
|
|
||||||
// Require BlHooks to be included before this header
|
// Ensure BlHooks is available (include it if not already included)
|
||||||
#ifndef _H_BLHOOKS
|
#ifndef _H_BLHOOKS
|
||||||
#error "BlFuncs.hpp: You must include BlHooks.hpp first"
|
#include "BlHooks.hpp"
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
typedef const char* (*tsf_StringCallback)(ADDR, signed int, const char*[]);
|
typedef const char* (*tsf_StringCallback)(ADDR, signed int, const char*[]);
|
||||||
typedef signed int (*tsf_IntCallback)(ADDR, signed int, const char*[]);
|
typedef signed int (*tsf_IntCallback)(ADDR, signed int, const char*[]);
|
||||||
@@ -71,7 +71,6 @@ BlFunctionDefExtern(const char *, __thiscall, tsf_BlSimObject__getDataField, ADD
|
|||||||
BlFunctionDefExtern(void, __thiscall, tsf_BlSimObject__setDataField, ADDR, const char*, const char*, const char*);
|
BlFunctionDefExtern(void, __thiscall, tsf_BlSimObject__setDataField, ADDR, const char*, const char*, const char*);
|
||||||
BlFunctionDefExtern(char*, __fastcall, tsf_BlCon__getReturnBuffer, unsigned int);
|
BlFunctionDefExtern(char*, __fastcall, tsf_BlCon__getReturnBuffer, unsigned int);
|
||||||
|
|
||||||
|
|
||||||
// Function short names
|
// Function short names
|
||||||
|
|
||||||
#define BlEval tsf_Eval
|
#define BlEval tsf_Eval
|
||||||
@@ -94,16 +93,21 @@ BlFunctionDefExtern(char *, __fastcall, tsf_BlCon__getReturnBuffer, unsigned int
|
|||||||
|
|
||||||
#define BlAddFunction tsf_AddConsoleFunc
|
#define BlAddFunction tsf_AddConsoleFunc
|
||||||
|
|
||||||
#define __22ND_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, ...) a22
|
#define __22ND_ARGUMENT( \
|
||||||
#define __NUM_LIST(...) __22ND_ARGUMENT(dummy, ##__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, ...) \
|
||||||
#define BlCall(...) \
|
a22
|
||||||
tsf_BlCon__executef(__NUM_LIST(__VA_ARGS__), __VA_ARGS__)
|
#define __NUM_LIST(...) \
|
||||||
#define BlCallObj(obj, ...) \
|
__22ND_ARGUMENT(dummy, ##__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||||
tsf_BlCon__executefSimObj((ADDR*)obj, __NUM_LIST(__VA_ARGS__), __VA_ARGS__)
|
#define BlCall(...) tsf_BlCon__executef(__NUM_LIST(__VA_ARGS__), __VA_ARGS__)
|
||||||
|
#define BlCallObj(obj, ...) tsf_BlCon__executefSimObj((ADDR*)obj, __NUM_LIST(__VA_ARGS__), __VA_ARGS__)
|
||||||
#define BlFuncsInit() if(!tsf_InitInternal()) { return false; }
|
|
||||||
#define BlFuncsDeinit() if(!tsf_DeinitInternal()) { return false; }
|
|
||||||
|
|
||||||
|
#define BlFuncsInit() \
|
||||||
|
if (!tsf_InitInternal()) { \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
#define BlFuncsDeinit() \
|
||||||
|
if (!tsf_DeinitInternal()) { \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -2,21 +2,22 @@
|
|||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
// RedoBlHooks Version 3.0
|
// RedoBlHooks Version 3.0
|
||||||
|
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <cstdlib>
|
||||||
|
#endif
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
// #include <map>
|
// #include <map>
|
||||||
|
|
||||||
#include "BlHooks.hpp"
|
#include "BlHooks.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Scanned structures
|
// Scanned structures
|
||||||
|
|
||||||
BlFunctionDefIntern(tsh_BlPrintf);
|
BlFunctionDefIntern(tsh_BlPrintf);
|
||||||
|
|
||||||
|
|
||||||
// Sig Scanning
|
// Sig Scanning
|
||||||
|
|
||||||
ADDR ImageBase;
|
ADDR ImageBase;
|
||||||
@@ -87,7 +88,6 @@ void tsh_i_PatternTextToCode(char* text, char** opatt, char** omask) {
|
|||||||
*omask = mask;
|
*omask = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Public functions for sig scanning
|
// Public functions for sig scanning
|
||||||
|
|
||||||
// Scan using code-style pattern
|
// Scan using code-style pattern
|
||||||
@@ -109,7 +109,6 @@ ADDR tsh_ScanText(char* text) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Call Patching and Hooking
|
// Call Patching and Hooking
|
||||||
|
|
||||||
// Remove protection from address
|
// Remove protection from address
|
||||||
@@ -127,21 +126,13 @@ void tsh_PatchBytes(ADDR length, ADDR location, BYTE* repl) {
|
|||||||
memcpy((void*)location, (void*)repl, (size_t)length);
|
memcpy((void*)location, (void*)repl, (size_t)length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tsh_PatchByte(ADDR location, BYTE value) {
|
void tsh_PatchByte(ADDR location, BYTE value) { tsh_PatchBytes(location, 1, &value); }
|
||||||
tsh_PatchBytes(location, 1, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsh_ReplaceInt(ADDR addr, int rval) {
|
void tsh_ReplaceInt(ADDR addr, int rval) { tsh_PatchBytes(4, addr, (BYTE*)(&rval)); }
|
||||||
tsh_PatchBytes(4, addr, (BYTE*)(&rval));
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsh_i_CallOffset(ADDR instr, ADDR func) {
|
int tsh_i_CallOffset(ADDR instr, ADDR func) { return func - (instr + 4); }
|
||||||
return func - (instr+4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsh_i_ReplaceCall(ADDR instr, ADDR target) {
|
void tsh_i_ReplaceCall(ADDR instr, ADDR target) { tsh_ReplaceInt(instr, tsh_i_CallOffset(instr, target)); }
|
||||||
tsh_ReplaceInt(instr, tsh_i_CallOffset(instr, target));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsh_i_PatchCopy(ADDR dest, ADDR src, unsigned int len) {
|
void tsh_i_PatchCopy(ADDR dest, ADDR src, unsigned int len) {
|
||||||
for (unsigned int i = 0; i < len; i++) {
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
@@ -165,7 +156,8 @@ int tsh_PatchAllMatchesCode(ADDR len, char* patt, char* mask, char* replace, boo
|
|||||||
int numpatched = 0;
|
int numpatched = 0;
|
||||||
for (ADDR i = ImageBase; i < ImageBase + ImageSize - len; i++) {
|
for (ADDR i = ImageBase; i < ImageBase + ImageSize - len; i++) {
|
||||||
if (tsh_i_CompareData((BYTE*)i, (BYTE*)patt, mask)) {
|
if (tsh_i_CompareData((BYTE*)i, (BYTE*)patt, mask)) {
|
||||||
if(debugprint) BlPrintf("RedoBlHooks: Patching call at %08x", i);
|
if (debugprint)
|
||||||
|
BlPrintf("RedoBlHooks: Patching call at %08x", i);
|
||||||
|
|
||||||
numpatched++;
|
numpatched++;
|
||||||
tsh_DeprotectAddress(i, len);
|
tsh_DeprotectAddress(i, len);
|
||||||
@@ -190,7 +182,6 @@ int tsh_PatchAllMatchesHex(ADDR len, char* text, char* replace, bool debugprint)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
||||||
bool tsh_InitInternal() {
|
bool tsh_InitInternal() {
|
||||||
@@ -201,7 +192,4 @@ bool tsh_InitInternal(){
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tsh_DeinitInternal() {
|
bool tsh_DeinitInternal() { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,11 @@
|
|||||||
#ifndef _H_BLHOOKS
|
#ifndef _H_BLHOOKS
|
||||||
#define _H_BLHOOKS
|
#define _H_BLHOOKS
|
||||||
|
|
||||||
|
|
||||||
// Typedefs
|
// Typedefs
|
||||||
|
|
||||||
typedef unsigned char BYTE;
|
typedef unsigned char BYTE;
|
||||||
typedef unsigned int ADDR;
|
typedef unsigned int ADDR;
|
||||||
|
|
||||||
|
|
||||||
// Prototypes
|
// Prototypes
|
||||||
|
|
||||||
bool tsh_InitInternal();
|
bool tsh_InitInternal();
|
||||||
@@ -25,7 +23,6 @@ void tsh_PatchByte(ADDR, BYTE);
|
|||||||
void tsh_PatchBytes(unsigned int, ADDR, BYTE*);
|
void tsh_PatchBytes(unsigned int, ADDR, BYTE*);
|
||||||
void tsh_PatchInt(ADDR, int);
|
void tsh_PatchInt(ADDR, int);
|
||||||
|
|
||||||
|
|
||||||
// Debug print settings
|
// Debug print settings
|
||||||
|
|
||||||
#ifndef TSH_NO_DEBUG_PRINT
|
#ifndef TSH_NO_DEBUG_PRINT
|
||||||
@@ -34,29 +31,31 @@ void tsh_PatchInt(ADDR, int);
|
|||||||
#define tsh_DEBUGPRINT true
|
#define tsh_DEBUGPRINT true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Function short names
|
// Function short names
|
||||||
|
|
||||||
// Use in code when the def is not shared in a header
|
// Use in code when the def is not shared in a header
|
||||||
#define BlFunctionDef(returnType, convention, name, ...) \
|
#define BlFunctionDef(returnType, convention, name, ...) \
|
||||||
typedef returnType(convention* tsh_##name##FnT)(__VA_ARGS__); \
|
typedef returnType(convention* tsh_##name##FnT)(__VA_ARGS__); \
|
||||||
tsh_##name##FnT name;
|
tsh_##name##FnT name;
|
||||||
// Use in header for shared function defs when a BlFunctionDefIntern exists in code
|
// Use in header for shared function defs when a BlFunctionDefIntern exists in
|
||||||
|
// code
|
||||||
#define BlFunctionDefExtern(returnType, convention, name, ...) \
|
#define BlFunctionDefExtern(returnType, convention, name, ...) \
|
||||||
typedef returnType(convention* tsh_##name##FnT)(__VA_ARGS__); \
|
typedef returnType(convention* tsh_##name##FnT)(__VA_ARGS__); \
|
||||||
extern tsh_##name##FnT name;
|
extern tsh_##name##FnT name;
|
||||||
// Use in code for shared function defs when a BlFunctionDefExtern exists in header
|
// Use in code for shared function defs when a BlFunctionDefExtern exists in
|
||||||
#define BlFunctionDefIntern(name) \
|
// header
|
||||||
tsh_##name##FnT name;
|
#define BlFunctionDefIntern(name) tsh_##name##FnT name;
|
||||||
|
|
||||||
// Scan for and assign the pattern to the variable, or err and return if not found
|
// Scan for and assign the pattern to the variable, or err and return if not
|
||||||
|
// found
|
||||||
#define BlScanFunctionCode(target, patt, mask) \
|
#define BlScanFunctionCode(target, patt, mask) \
|
||||||
target = (tsh_##target##FnT)tsh_ScanCode((char*)patt, (char*)mask); \
|
target = (tsh_##target##FnT)tsh_ScanCode((char*)patt, (char*)mask); \
|
||||||
if (!target) { \
|
if (!target) { \
|
||||||
BlPrintf("RedoBlHooks | Cannot find function " #target "!"); \
|
BlPrintf("RedoBlHooks | Cannot find function " #target "!"); \
|
||||||
return false; \
|
return false; \
|
||||||
} else { \
|
} else { \
|
||||||
if(tsh_DEBUGPRINT) BlPrintf("RedoBlHooks | Found function "#target" at %08x", (int)target); \
|
if (tsh_DEBUGPRINT) \
|
||||||
|
BlPrintf("RedoBlHooks | Found function " #target " at %08x", (int)target); \
|
||||||
}
|
}
|
||||||
#define BlScanFunctionText(target, text) \
|
#define BlScanFunctionText(target, text) \
|
||||||
target = (tsh_##target##FnT)tsh_ScanText((char*)text); \
|
target = (tsh_##target##FnT)tsh_ScanText((char*)text); \
|
||||||
@@ -64,7 +63,8 @@ void tsh_PatchInt(ADDR, int);
|
|||||||
BlPrintf("RedoBlHooks | Cannot find function " #target "!"); \
|
BlPrintf("RedoBlHooks | Cannot find function " #target "!"); \
|
||||||
return false; \
|
return false; \
|
||||||
} else { \
|
} else { \
|
||||||
if(tsh_DEBUGPRINT) BlPrintf("RedoBlHooks | Found function "#target" at %08x", (int)target); \
|
if (tsh_DEBUGPRINT) \
|
||||||
|
BlPrintf("RedoBlHooks | Found function " #target " at %08x", (int)target); \
|
||||||
}
|
}
|
||||||
#define BlScanCode(target, patt, mask) \
|
#define BlScanCode(target, patt, mask) \
|
||||||
target = tsh_ScanCode((char*)patt, (char*)mask); \
|
target = tsh_ScanCode((char*)patt, (char*)mask); \
|
||||||
@@ -72,7 +72,8 @@ void tsh_PatchInt(ADDR, int);
|
|||||||
BlPrintf("RedoBlHooks | Cannot find pattern " #target "!"); \
|
BlPrintf("RedoBlHooks | Cannot find pattern " #target "!"); \
|
||||||
return false; \
|
return false; \
|
||||||
} else { \
|
} else { \
|
||||||
if(tsh_DEBUGPRINT) BlPrintf("RedoBlHooks | Found "#target" at %08x", (int)target); \
|
if (tsh_DEBUGPRINT) \
|
||||||
|
BlPrintf("RedoBlHooks | Found " #target " at %08x", (int)target); \
|
||||||
}
|
}
|
||||||
#define BlScanText(target, text) \
|
#define BlScanText(target, text) \
|
||||||
target = tsh_ScanText((char*)text); \
|
target = tsh_ScanText((char*)text); \
|
||||||
@@ -80,7 +81,8 @@ void tsh_PatchInt(ADDR, int);
|
|||||||
BlPrintf("RedoBlHooks | Cannot find " #target "!"); \
|
BlPrintf("RedoBlHooks | Cannot find " #target "!"); \
|
||||||
return false; \
|
return false; \
|
||||||
} else { \
|
} else { \
|
||||||
if(tsh_DEBUGPRINT) BlPrintf("RedoBlHooks | Found "#target" at %08x", (int)target); \
|
if (tsh_DEBUGPRINT) \
|
||||||
|
BlPrintf("RedoBlHooks | Found " #target " at %08x", (int)target); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use in code to define the data and functions for hooking a function
|
// Use in code to define the data and functions for hooking a function
|
||||||
@@ -100,23 +102,30 @@ void tsh_PatchInt(ADDR, int);
|
|||||||
tsh_PatchAllMatchesCode((ADDR)len, (char*)text, (char*)repl, tsh_DEBUGPRINT);
|
tsh_PatchAllMatchesCode((ADDR)len, (char*)text, (char*)repl, tsh_DEBUGPRINT);
|
||||||
|
|
||||||
// Deprotect and replace one byte
|
// Deprotect and replace one byte
|
||||||
#define BlPatchByte(addr, byte) \
|
#define BlPatchByte(addr, byte) tsh_PatchByte((ADDR)addr, (BYTE)byte);
|
||||||
tsh_PatchByte((ADDR)addr, (BYTE)byte);
|
|
||||||
// Deprotect and replace a byte string
|
// Deprotect and replace a byte string
|
||||||
#define BlPatchBytes(len, addr, repl) \
|
#define BlPatchBytes(len, addr, repl) tsh_PatchBytes((ADDR)len, (ADDR)addr, (BYTE*)repl);
|
||||||
tsh_PatchBytes((ADDR)len, (ADDR)addr, (BYTE*)repl);
|
|
||||||
|
|
||||||
// BlPrintf(char* format, ...)
|
// BlPrintf(char* format, ...)
|
||||||
#define BlPrintf(...) if(tsh_BlPrintf) { tsh_BlPrintf(__VA_ARGS__); }
|
#define BlPrintf(...) \
|
||||||
|
if (tsh_BlPrintf) { \
|
||||||
|
tsh_BlPrintf(__VA_ARGS__); \
|
||||||
|
}
|
||||||
// BlHooksInit() -> bool: success
|
// BlHooksInit() -> bool: success
|
||||||
#define BlHooksInit() if(!tsh_InitInternal()) { BlPrintf("BlHooksInit failed"); return false; }
|
#define BlHooksInit() \
|
||||||
|
if (!tsh_InitInternal()) { \
|
||||||
|
BlPrintf("BlHooksInit failed"); \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
// BlHooksDeinit() -> bool: success
|
// BlHooksDeinit() -> bool: success
|
||||||
#define BlHooksDeinit() if(!tsh_DeinitInternal()) { BlPrintf("BlHooksDeinit failed"); return false; }
|
#define BlHooksDeinit() \
|
||||||
|
if (!tsh_DeinitInternal()) { \
|
||||||
|
BlPrintf("BlHooksDeinit failed"); \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
// Scanned structures
|
// Scanned structures
|
||||||
|
|
||||||
BlFunctionDefExtern(void, , tsh_BlPrintf, const char*, ...);
|
BlFunctionDefExtern(void, , tsh_BlPrintf, const char*, ...);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
27
readme.md
27
readme.md
@@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
# BlockLua
|
# BlockLua
|
||||||
|
|
||||||
Lua scripting for Blockland
|
Lua scripting for Blockland
|
||||||
|
|
||||||
## How to Install
|
## How to Install
|
||||||
|
|
||||||
- Install RedBlocklandLoader
|
- Install RedBlocklandLoader
|
||||||
- Copy `lua5.1.dll` into your Blockland install folder, next to `Blockland.exe`
|
- Copy `lua5.1.dll` into your Blockland install folder, next to `Blockland.exe`
|
||||||
- Copy `BlockLua.dll` into the `modules` folder within the Blockland folder
|
- Copy `BlockLua.dll` into the `modules` folder within the Blockland folder
|
||||||
|
|
||||||
|
|
||||||
## Quick Reference
|
## Quick Reference
|
||||||
|
|
||||||
### From TorqueScript
|
### From TorqueScript
|
||||||
|
|
||||||
`'print('hello world')` - Execute Lua in the console by prepending a `'` (single quote)
|
`'print('hello world')` - Execute Lua in the console by prepending a `'` (single quote)
|
||||||
`luaeval("code");` - Execute Lua code
|
`luaeval("code");` - Execute Lua code
|
||||||
`luacall("funcName", %args...);` - Call a Lua function (supports indexing tables and object methods)
|
`luacall("funcName", %args...);` - Call a Lua function (supports indexing tables and object methods)
|
||||||
@@ -20,6 +20,7 @@ Lua scripting for Blockland
|
|||||||
`luaset("varName", %value);` - Write a Lua global variable (supports indexing tables)
|
`luaset("varName", %value);` - Write a Lua global variable (supports indexing tables)
|
||||||
|
|
||||||
### From Lua
|
### From Lua
|
||||||
|
|
||||||
`bl.eval('code')` - Eval TorqueScript code
|
`bl.eval('code')` - Eval TorqueScript code
|
||||||
`bl.funcName(args)` - Call a TorqueScript function
|
`bl.funcName(args)` - Call a TorqueScript function
|
||||||
`bl.varName` - Read a TorqueScript global variable
|
`bl.varName` - Read a TorqueScript global variable
|
||||||
@@ -28,6 +29,7 @@ Lua scripting for Blockland
|
|||||||
`bl['namespaceName::funcName'](args)` - Call a namespaced TorqueScript function
|
`bl['namespaceName::funcName'](args)` - Call a namespaced TorqueScript function
|
||||||
|
|
||||||
### Accessing Torque Objects from Lua
|
### Accessing Torque Objects from Lua
|
||||||
|
|
||||||
`bl.objectName` - Access a Torque object by name
|
`bl.objectName` - Access a Torque object by name
|
||||||
`bl[objectID]` - Access a Torque object by ID (or name)
|
`bl[objectID]` - Access a Torque object by ID (or name)
|
||||||
`object.fieldOrKey` - Read a field or Lua key from a Torque object
|
`object.fieldOrKey` - Read a field or Lua key from a Torque object
|
||||||
@@ -40,15 +42,18 @@ Lua scripting for Blockland
|
|||||||
`object:exists()` - 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
|
||||||
`sched:cancel()` - Cancel a previously scheduled timer
|
`sched:cancel()` - Cancel a previously scheduled timer
|
||||||
|
|
||||||
### Raycasts and Searches
|
### Raycasts and Searches
|
||||||
|
|
||||||
`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.
|
`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.
|
||||||
|
|
||||||
### List of Object Classes (for raycasts and searches)
|
### List of Object Classes (for raycasts and searches)
|
||||||
|
|
||||||
`'all'` - Any object
|
`'all'` - Any object
|
||||||
`'player'` - Players or bots
|
`'player'` - Players or bots
|
||||||
`'item'` - Items
|
`'item'` - Items
|
||||||
@@ -59,6 +64,7 @@ Lua scripting for Blockland
|
|||||||
Other types: `'static'`, `'environment'`, `'terrain'`, `'water'`, `'trigger'`, `'marker'`, `'gamebase'`, `'shapebase'`, `'camera'`, `'staticshape'`, `'vehicleblocker'`, `'explosion'`, `'corpse'`, `'debris'`, `'physicalzone'`, `'staticts'`, `'staticrendered'`, `'damagableitem'`
|
Other types: `'static'`, `'environment'`, `'terrain'`, `'water'`, `'trigger'`, `'marker'`, `'gamebase'`, `'shapebase'`, `'camera'`, `'staticshape'`, `'vehicleblocker'`, `'explosion'`, `'corpse'`, `'debris'`, `'physicalzone'`, `'staticts'`, `'staticrendered'`, `'damagableitem'`
|
||||||
|
|
||||||
### Server-Client Communication
|
### Server-Client Communication
|
||||||
|
|
||||||
`bl.addServerCmd('commandName', function(client, args...) ... end)` - Register a /command on the server
|
`bl.addServerCmd('commandName', function(client, args...) ... end)` - Register a /command on the server
|
||||||
`bl.addClientCmd('commandName', function(args...) ... end)` - Register a client command on the client
|
`bl.addClientCmd('commandName', function(args...) ... end)` - Register a client command on the client
|
||||||
`bl.commandToServer('commandName', args...)` - As a client, execute a server command
|
`bl.commandToServer('commandName', args...)` - As a client, execute a server command
|
||||||
@@ -66,6 +72,7 @@ Other types: `'static'`, `'environment'`, `'terrain'`, `'water'`, `'trigger'`, `
|
|||||||
`bl.commandToAll('commandName', args...)` - As the server, execute a client command on all clients
|
`bl.commandToAll('commandName', args...)` - As the server, execute a client command on all clients
|
||||||
|
|
||||||
### Packages/Hooks
|
### Packages/Hooks
|
||||||
|
|
||||||
`bl.hook('packageName', 'functionName', 'before'/'after', function(args) ... end)` - Hook a Torque function with a Lua function.
|
`bl.hook('packageName', 'functionName', 'before'/'after', function(args) ... end)` - Hook a Torque function with a Lua function.
|
||||||
`args` is an array containing the arguments provided to the function. If the hook is `before`, these can be modified before being passed to the parent function.
|
`args` is an array containing the arguments provided to the function. If the hook is `before`, these can be modified before being passed to the parent function.
|
||||||
If `args._return` is set to anything other than nil by a `before` hook, the parent function will not be called, and the function will simply return that value. Also in this case, any `after` hook will not be executed.
|
If `args._return` is set to anything other than nil by a `before` hook, the parent function will not be called, and the function will simply return that value. Also in this case, any `after` hook will not be executed.
|
||||||
@@ -75,10 +82,12 @@ In an `after` hook, `args._return` is set to the value returned by the parent fu
|
|||||||
`bl.unhook('packageName')` - Remove any previously defined hooks within the package
|
`bl.unhook('packageName')` - Remove any previously defined hooks within the package
|
||||||
|
|
||||||
### Modules and Dependencies
|
### Modules and Dependencies
|
||||||
|
|
||||||
`dofile('Add-Ons/Path/file.lua')` - Execute a Lua file. Relative paths (`./file.lua`) are allowed. `..` is not allowed.
|
`dofile('Add-Ons/Path/file.lua')` - Execute a Lua file. Relative paths (`./file.lua`) are allowed. `..` is not allowed.
|
||||||
|
|
||||||
`require('modulePath.moduleName')` - Load a Lua file or external library.
|
`require('modulePath.moduleName')` - Load a Lua file or external library.
|
||||||
`require` replaces `.` with `/` in the path, and then searches for files in the following order:
|
`require` replaces `.` with `/` in the path, and then searches for files in the following order:
|
||||||
|
|
||||||
- `./modulePath/moduleName.lua`
|
- `./modulePath/moduleName.lua`
|
||||||
- `./modulePath/moduleName/init.lua`
|
- `./modulePath/moduleName/init.lua`
|
||||||
- `modulePath/moduleName.lua` (Relative to game directory)
|
- `modulePath/moduleName.lua` (Relative to game directory)
|
||||||
@@ -90,6 +99,7 @@ In an `after` hook, `args._return` is set to the value returned by the parent fu
|
|||||||
Like in standard Lua, modules loaded using `require` are only executed the first time `require` is called with that path (from anywhere). 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 (from anywhere). Subsequent calls simply return the result from the initial execution. To allow hot reloading, use `dofile`.
|
||||||
|
|
||||||
### File I/O
|
### File I/O
|
||||||
|
|
||||||
Lua's builtin file I/O is emulated, and is confined to the same directories as TorqueScript file I/O.
|
Lua's builtin file I/O is emulated, and is confined to the same directories as TorqueScript file I/O.
|
||||||
Relative paths (`./`) are allowed. `..` is not allowed.
|
Relative paths (`./`) are allowed. `..` is not allowed.
|
||||||
`file = io.open('./file.txt', 'r'/'w'/'a'/'rb'/'wb'/'ab')` - Open a file
|
`file = io.open('./file.txt', 'r'/'w'/'a'/'rb'/'wb'/'ab')` - Open a file
|
||||||
@@ -100,6 +110,7 @@ Reading files from ZIPs is supported, with caveats. Null characters are not allo
|
|||||||
When reading from outside ZIPs, binary files are fully supported.
|
When reading from outside ZIPs, binary files are fully supported.
|
||||||
|
|
||||||
### Object Creation
|
### Object Creation
|
||||||
|
|
||||||
`bl.new('className')` - Create a new Torque object
|
`bl.new('className')` - Create a new Torque object
|
||||||
`bl.new('className', {fieldName = value, ...})` - Create a new Torque object with the given fields
|
`bl.new('className', {fieldName = value, ...})` - Create a new Torque object with the given fields
|
||||||
`bl.new('className objectName', fields?)` - Create a new named Torque object
|
`bl.new('className objectName', fields?)` - Create a new named Torque object
|
||||||
@@ -108,6 +119,7 @@ When reading from outside ZIPs, binary files are fully supported.
|
|||||||
`bl.datablock('datablockClassName datablockName:parentDatablockName', fields?)` - Create a new datablock with inheritance
|
`bl.datablock('datablockClassName datablockName:parentDatablockName', fields?)` - Create a new datablock with inheritance
|
||||||
|
|
||||||
### Classes and Types
|
### Classes and Types
|
||||||
|
|
||||||
`bl.type('varName', 'type')` - Register the type of a Torque global variable, for conversion when accessing from Lua. Valid types are 'boolean', 'object', 'string' (prevents automatic conversion), and nil (default, applies automatic conversion).
|
`bl.type('varName', 'type')` - Register the type of a Torque global variable, for conversion when accessing from Lua. Valid types are 'boolean', 'object', 'string' (prevents automatic conversion), and nil (default, applies automatic conversion).
|
||||||
`bl.type('funcName', 'type')` - Register the return type of a Torque function, for conversion when calling from Lua. Valid types are 'bool', 'object', and nil - all other conversion is automatic. Already done for all default functions.
|
`bl.type('funcName', 'type')` - Register the return type of a Torque function, for conversion when calling from Lua. Valid types are 'bool', 'object', and nil - all other conversion is automatic. Already done for all default functions.
|
||||||
`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.
|
||||||
@@ -118,6 +130,7 @@ When reading from outside ZIPs, binary files are fully supported.
|
|||||||
`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.
|
`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.
|
||||||
|
|
||||||
### Vector
|
### 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
|
||||||
@@ -143,9 +156,11 @@ When reading from outside ZIPs, binary files are fully supported.
|
|||||||
`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
|
### Matrix
|
||||||
|
|
||||||
WIP
|
WIP
|
||||||
|
|
||||||
### Extended Standard Lua Library
|
### Extended Standard Lua Library
|
||||||
|
|
||||||
`str[index]`
|
`str[index]`
|
||||||
`str[{start,stop}]`
|
`str[{start,stop}]`
|
||||||
`string.split(str, separator='' (splits into chars), noregex=false)`
|
`string.split(str, separator='' (splits into chars), noregex=false)`
|
||||||
@@ -179,10 +194,12 @@ WIP
|
|||||||
`math.clamp(num, min, max)`
|
`math.clamp(num, min, max)`
|
||||||
|
|
||||||
## 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 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
|
||||||
- A Torque object container becomes its object ID
|
- A Torque object container becomes its object ID
|
||||||
@@ -193,6 +210,7 @@ TorqueScript stores no type information; all values in TorqueScript are strings.
|
|||||||
- Tables cannot be passed and will throw an error
|
- Tables cannot be passed and will throw an error
|
||||||
|
|
||||||
### From TorqueScript to Lua
|
### From TorqueScript to Lua
|
||||||
|
|
||||||
- The empty string "" becomes `nil`
|
- 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.
|
- 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 two or three numbers separated by single spaces becomes a `vector`
|
||||||
@@ -204,16 +222,19 @@ For scenarios where the automatic TorqueScript->Lua conversion rules are insuffi
|
|||||||
To convert things 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
|
## 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.
|
||||||
|
|
||||||
### Unsafe Mode
|
### Unsafe Mode
|
||||||
|
|
||||||
BlockLua can be built in Unsafe Mode by specifying the `-DBLLUA_UNSAFE` compiler flag. This removes the sandboxing of Lua code, allowing it to access any file and use any library, including ffi.
|
BlockLua can be built in Unsafe Mode by specifying the `-DBLLUA_UNSAFE` compiler flag. This removes the sandboxing of Lua code, allowing it to access any file and use any library, including ffi.
|
||||||
A more limited option is `-DBLLUA_ALLOWFFI`, which allows the use of the `ffi` library. This can still be exploited to grant all the same access as full unsafe mode.
|
A more limited option is `-DBLLUA_ALLOWFFI`, which allows the use of the `ffi` library. This can still be exploited to grant all the same access as full unsafe mode.
|
||||||
Please do not publish add-ons that require either of these.
|
Please do not publish add-ons that require either of these.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
|
|
||||||
With any *32-bit* variant of GCC installed (such as MinGW or MSYS2), run the following command in the repo directory:
|
With any _32-bit_ variant of GCC installed (such as MinGW or MSYS2), run the following command in the repo directory:
|
||||||
`g++ src/bllua4.cpp -o BlockLua.dll -m32 -shared -static-libgcc -Isrc -Iinc/tsfuncs -Iinc/lua -lpsapi -L. -llua5.1`
|
`g++ src/bllua4.cpp -o BlockLua.dll -m32 -shared -static-libgcc -Isrc -Iinc/tsfuncs -Iinc/lua -lpsapi -L. -llua5.1`
|
||||||
|
|
||||||
LuaJIT (lua5.1.dll) can be obtained from https://luajit.org/
|
LuaJIT (lua5.1.dll) can be obtained from https://luajit.org/
|
||||||
|
|||||||
@@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
|
||||||
#include "lua.hpp"
|
|
||||||
#include "BlHooks.cpp"
|
|
||||||
#include "BlFuncs.cpp"
|
#include "BlFuncs.cpp"
|
||||||
|
#include "BlHooks.cpp"
|
||||||
|
#include "lua.hpp"
|
||||||
|
|
||||||
#include "luainterp.cpp"
|
#include "luainterp.cpp"
|
||||||
#include "lualibts.cpp"
|
#include "lualibts.cpp"
|
||||||
@@ -74,7 +77,8 @@ bool init() {
|
|||||||
BLL_LOAD_LUA(gL, bll_fileLuaLibblTypes);
|
BLL_LOAD_LUA(gL, bll_fileLuaLibblTypes);
|
||||||
|
|
||||||
// Expose Lua API to TS
|
// Expose Lua API to TS
|
||||||
BlAddFunction(NULL, NULL, "_bllua_luacall", bll_ts_luacall, "LuaCall(name, ...) - Call Lua function and return result", 2, 20);
|
BlAddFunction(
|
||||||
|
NULL, NULL, "_bllua_luacall", bll_ts_luacall, "LuaCall(name, ...) - Call Lua function and return result", 2, 20);
|
||||||
BlEval(bll_fileTsEnv);
|
BlEval(bll_fileTsEnv);
|
||||||
BlEval(bll_fileTsLibts);
|
BlEval(bll_fileTsLibts);
|
||||||
BlEval(bll_fileTsLibblSupport);
|
BlEval(bll_fileTsLibblSupport);
|
||||||
@@ -103,8 +107,11 @@ bool deinit() {
|
|||||||
|
|
||||||
bool __stdcall DllMain(HINSTANCE hinstance, DWORD reason, void* reserved) {
|
bool __stdcall DllMain(HINSTANCE hinstance, DWORD reason, void* reserved) {
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case DLL_PROCESS_ATTACH: return init();
|
case DLL_PROCESS_ATTACH:
|
||||||
case DLL_PROCESS_DETACH: return deinit();
|
return init();
|
||||||
default : return true;
|
case DLL_PROCESS_DETACH:
|
||||||
|
return deinit();
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
|
|
||||||
-- Utility: Convert a list of strings into a map of string->true
|
-- Utility: Convert a list of strings into a map of string->true
|
||||||
local function tmap(t) local u = {}; for _, n in ipairs(t) do u[n] = true end; return u; end
|
local function tmap(t)
|
||||||
|
local u = {}; for _, n in ipairs(t) do u[n] = true end; return u;
|
||||||
|
end
|
||||||
|
|
||||||
-- Save banned global variables for wrapping with safe functions
|
-- Save banned global variables for wrapping with safe functions
|
||||||
local old_io = io
|
local old_io = io
|
||||||
@@ -60,6 +62,9 @@ local disallowed_exts = tmap {
|
|||||||
-- Return: clean file path if allowed (or nil if disallowed),
|
-- Return: clean file path if allowed (or nil if disallowed),
|
||||||
-- error string (or nil if allowed)
|
-- error string (or nil if allowed)
|
||||||
local function safe_path(fn, readonly)
|
local function safe_path(fn, readonly)
|
||||||
|
if type(fn) ~= 'string' then
|
||||||
|
return nil, 'Filename must be a string'
|
||||||
|
end
|
||||||
fn = fn:gsub('\\', '/')
|
fn = fn:gsub('\\', '/')
|
||||||
fn = fn:gsub('^ +', '')
|
fn = fn:gsub('^ +', '')
|
||||||
fn = fn:gsub(' +$', '')
|
fn = fn:gsub(' +$', '')
|
||||||
@@ -103,6 +108,7 @@ function _bllua_io_open(fn, md)
|
|||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Allow io.type (works on file handles returned by io.open)
|
-- Allow io.type (works on file handles returned by io.open)
|
||||||
function _bllua_io_type(f)
|
function _bllua_io_type(f)
|
||||||
return old_io.type(f)
|
return old_io.type(f)
|
||||||
@@ -128,6 +134,7 @@ function _bllua_requiresecure(name)
|
|||||||
return old_require(name)
|
return old_require(name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
package = {
|
package = {
|
||||||
seeall = old_package.seeall,
|
seeall = old_package.seeall,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ end
|
|||||||
|
|
||||||
-- Called when pcall fails on a ts->lua call, used to print detailed error info
|
-- Called when pcall fails on a ts->lua call, used to print detailed error info
|
||||||
function _bllua_on_error(err)
|
function _bllua_on_error(err)
|
||||||
|
-- Convert error to string if it's not already
|
||||||
|
err = tostring(err)
|
||||||
err = err:match(': (.+)$') or err
|
err = err:match(': (.+)$') or err
|
||||||
local tracelines = { err }
|
local tracelines = { err }
|
||||||
local level = 2
|
local level = 2
|
||||||
@@ -25,7 +27,7 @@ function _bllua_on_error(err)
|
|||||||
local info = debug.getinfo(level)
|
local info = debug.getinfo(level)
|
||||||
if not info then break end
|
if not info then break end
|
||||||
local filename = debug.getfilename(level) or info.short_src
|
local filename = debug.getfilename(level) or info.short_src
|
||||||
local funcname = info.name
|
local funcname = info.name or '<unknown>'
|
||||||
if funcname == 'dofile' then break end
|
if funcname == 'dofile' then break end
|
||||||
table.insert(tracelines, string.format('%s:%s in function \'%s\'',
|
table.insert(tracelines, string.format('%s:%s in function \'%s\'',
|
||||||
filename,
|
filename,
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
|
|
||||||
// Handle errors with a Lua function, defined in lua-env.lua
|
// Handle errors with a Lua function, defined in lua-env.lua
|
||||||
|
#include "luainterp.hpp"
|
||||||
|
#include "BlHooks.hpp"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "lua.h"
|
||||||
|
#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)) {
|
||||||
@@ -15,6 +21,7 @@ int bll_error_handler(lua_State *L) {
|
|||||||
lua_pcall(L, 1, 1, 0);
|
lua_pcall(L, 1, 1, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bll_pcall(lua_State* L, int nargs, int nret) {
|
int bll_pcall(lua_State* L, int nargs, int nret) {
|
||||||
// calculate stack position for message handler
|
// calculate stack position for message handler
|
||||||
int hpos = lua_gettop(L) - nargs;
|
int hpos = lua_gettop(L) - nargs;
|
||||||
@@ -48,21 +55,27 @@ bool bll_LuaEval(lua_State* L, const char* str) {
|
|||||||
|
|
||||||
// Convert a Lua stack entry into a string for providing to TS
|
// Convert a Lua stack entry into a string for providing to TS
|
||||||
// Use static buffer to avoid excessive malloc
|
// Use static buffer to avoid excessive malloc
|
||||||
#define BLL_ARG_COUNT 20
|
|
||||||
#define BLL_ARG_MAX 8192
|
|
||||||
char bll_arg_buffer[BLL_ARG_COUNT][BLL_ARG_MAX];
|
char bll_arg_buffer[BLL_ARG_COUNT][BLL_ARG_MAX];
|
||||||
|
|
||||||
bool bll_toarg(lua_State* L, char* buf, int i, bool err) {
|
bool bll_toarg(lua_State* L, char* buf, int i, bool err) {
|
||||||
if (lua_isstring(L, i)) {
|
if (lua_isstring(L, i)) {
|
||||||
const char* str = lua_tostring(L, i);
|
const char* str = lua_tostring(L, i);
|
||||||
if (strlen(str) >= BLL_ARG_MAX) {
|
if (strlen(str) >= BLL_ARG_MAX) {
|
||||||
if(err) luaL_error(L, "argument to TS is too long - max length is 8192");
|
if (err)
|
||||||
|
luaL_error(L, "argument to TS is too long - max length is 8192");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
strcpy(buf, str);
|
#ifdef _MSC_VER
|
||||||
|
strncpy_s(buf, BLL_ARG_MAX, str, _TRUNCATE);
|
||||||
|
#else
|
||||||
|
strncpy(buf, str, BLL_ARG_MAX - 1);
|
||||||
|
buf[BLL_ARG_MAX - 1] = '\0';
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(err) luaL_error(L, "argument to TS must be a string");
|
if (err)
|
||||||
|
luaL_error(L, "argument to TS must be a string");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/luainterp.hpp
Normal file
17
src/luainterp.hpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// Shared declarations for Lua <-> TS argument handling
|
||||||
|
#ifndef _H_LUAINTERP_SHARED
|
||||||
|
#define _H_LUAINTERP_SHARED
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
|
#define BLL_ARG_COUNT 20
|
||||||
|
#define BLL_ARG_MAX 8192
|
||||||
|
|
||||||
|
extern char bll_arg_buffer[BLL_ARG_COUNT][BLL_ARG_MAX];
|
||||||
|
bool bll_toarg(lua_State* L, char* buf, int i, bool err);
|
||||||
|
int bll_pcall(lua_State* L, int nargs, int nret);
|
||||||
|
void bll_printError(lua_State* L, const char* operation, const char* item);
|
||||||
|
|
||||||
|
extern lua_State* gL;
|
||||||
|
|
||||||
|
#endif
|
||||||
256
src/lualibts.cpp
256
src/lualibts.cpp
@@ -3,14 +3,24 @@
|
|||||||
// TS -> Lua API
|
// TS -> Lua API
|
||||||
|
|
||||||
// Call a TS function from Lua, push the result to Lua stack
|
// Call a TS function from Lua, push the result to Lua stack
|
||||||
|
#include "BlFuncs.hpp"
|
||||||
|
#include "BlHooks.hpp"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "lua.h"
|
||||||
|
#include "luainterp.hpp"
|
||||||
|
|
||||||
int bll_TsCall(lua_State* L, const char* oname, const char* fname, int argc, int ofs) {
|
int bll_TsCall(lua_State* L, const char* oname, const char* fname, int argc, int ofs) {
|
||||||
ADDR obj = (ADDR)NULL;
|
ADDR obj = (ADDR)NULL;
|
||||||
if (oname) {
|
if (oname) {
|
||||||
obj = BlObject(oname);
|
obj = BlObject(oname);
|
||||||
if(!obj) { return luaL_error(L, "Lua->TS call: Object not found"); }
|
if (!obj) {
|
||||||
|
return luaL_error(L, "Lua->TS call: Object not found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(argc > BLL_ARG_COUNT) { return luaL_error(L, "Lua->TS call: Too many arguments (Max is 19)"); }
|
if (argc > BLL_ARG_COUNT) {
|
||||||
|
return luaL_error(L, "Lua->TS call: Too many arguments (Max is 19)");
|
||||||
|
}
|
||||||
|
|
||||||
char* argv[BLL_ARG_COUNT];
|
char* argv[BLL_ARG_COUNT];
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
@@ -23,52 +33,174 @@ int bll_TsCall(lua_State* L, const char* oname, const char* fname, int argc, int
|
|||||||
const char* res;
|
const char* res;
|
||||||
if (obj) {
|
if (obj) {
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 0: res = BlCallObj(obj, fname); break; // no idea why this happens sometimes, it shouldnt be possible
|
case 0:
|
||||||
case 1: res = BlCallObj(obj, fname); break;
|
res = BlCallObj(obj, fname);
|
||||||
case 2: res = BlCallObj(obj, fname, argv[0]); break;
|
break; // no idea why this happens sometimes, it shouldnt be possible
|
||||||
case 3: res = BlCallObj(obj, fname, argv[0], argv[1]); break;
|
case 1:
|
||||||
case 4: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2]); break;
|
res = BlCallObj(obj, fname);
|
||||||
case 5: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3]); break;
|
break;
|
||||||
case 6: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4]); break;
|
case 2:
|
||||||
case 7: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); break;
|
res = BlCallObj(obj, fname, argv[0]);
|
||||||
case 8: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); break;
|
break;
|
||||||
case 9: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); break;
|
case 3:
|
||||||
case 10: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); break;
|
res = BlCallObj(obj, fname, argv[0], argv[1]);
|
||||||
case 11: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); break;
|
break;
|
||||||
case 12: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]); break;
|
case 4:
|
||||||
case 13: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]); break;
|
res = BlCallObj(obj, fname, argv[0], argv[1], argv[2]);
|
||||||
case 14: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]); break;
|
break;
|
||||||
case 15: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]); break;
|
case 5:
|
||||||
case 16: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]); break;
|
res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3]);
|
||||||
case 17: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15]); break;
|
break;
|
||||||
case 18: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16]); break;
|
case 6:
|
||||||
case 19: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17]); break;
|
res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||||
case 20: res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18]); break;
|
break;
|
||||||
default: res = ""; luaL_error(L, "Lua->TS object call: Too many arguments (Max is 19)");
|
case 7:
|
||||||
|
res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
res = BlCallObj(obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10]);
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11]);
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11], argv[12]);
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11], argv[12], argv[13]);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11], argv[12], argv[13], argv[14]);
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11], argv[12], argv[13], argv[14], argv[15]);
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16]);
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17]);
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
res = BlCallObj(
|
||||||
|
obj, fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
|
||||||
|
argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res = "";
|
||||||
|
luaL_error(L, "Lua->TS object call: Too many arguments (Max is 19)");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 0: res = BlCall(fname); break;
|
case 0:
|
||||||
case 1: res = BlCall(fname, argv[0]); break;
|
res = BlCall(fname);
|
||||||
case 2: res = BlCall(fname, argv[0], argv[1]); break;
|
break;
|
||||||
case 3: res = BlCall(fname, argv[0], argv[1], argv[2]); break;
|
case 1:
|
||||||
case 4: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3]); break;
|
res = BlCall(fname, argv[0]);
|
||||||
case 5: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4]); break;
|
break;
|
||||||
case 6: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); break;
|
case 2:
|
||||||
case 7: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); break;
|
res = BlCall(fname, argv[0], argv[1]);
|
||||||
case 8: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); break;
|
break;
|
||||||
case 9: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); break;
|
case 3:
|
||||||
case 10: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); break;
|
res = BlCall(fname, argv[0], argv[1], argv[2]);
|
||||||
case 11: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]); break;
|
break;
|
||||||
case 12: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]); break;
|
case 4:
|
||||||
case 13: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]); break;
|
res = BlCall(fname, argv[0], argv[1], argv[2], argv[3]);
|
||||||
case 14: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]); break;
|
break;
|
||||||
case 15: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]); break;
|
case 5:
|
||||||
case 16: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15]); break;
|
res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||||
case 17: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16]); break;
|
break;
|
||||||
case 18: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17]); break;
|
case 6:
|
||||||
case 19: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18]); break;
|
res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
|
||||||
default: res = ""; luaL_error(L, "Lua->TS call: Too many arguments (Max is 19)");
|
break;
|
||||||
|
case 7:
|
||||||
|
res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11]);
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11], argv[12]);
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11], argv[12], argv[13]);
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11], argv[12], argv[13], argv[14]);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11], argv[12], argv[13], argv[14], argv[15]);
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11], argv[12], argv[13], argv[14], argv[15], argv[16]);
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17]);
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
res = BlCall(
|
||||||
|
fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
|
||||||
|
argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res = "";
|
||||||
|
luaL_error(L, "Lua->TS call: Too many arguments (Max is 19)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,19 +208,23 @@ int bll_TsCall(lua_State* L, const char* oname, const char* fname, int argc, int
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua lib function: ts.call
|
// Lua lib function: ts.call
|
||||||
int bll_lua_tscall(lua_State* L) {
|
int bll_lua_tscall(lua_State* L) {
|
||||||
int argc = lua_gettop(L) - 1; // number of arguments after function name
|
int argc = lua_gettop(L) - 1; // number of arguments after function name
|
||||||
if(argc < 0) return luaL_error(L, "_bllua_ts.call: Must provide a function name");
|
if (argc < 0)
|
||||||
|
return luaL_error(L, "_bllua_ts.call: Must provide a function name");
|
||||||
|
|
||||||
const char* fname = luaL_checkstring(L, 1);
|
const char* fname = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
return bll_TsCall(L, NULL, fname, argc, 1);
|
return bll_TsCall(L, NULL, fname, argc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua lib function: ts.callobj
|
// Lua lib function: ts.callobj
|
||||||
int bll_lua_tscallobj(lua_State* L) {
|
int bll_lua_tscallobj(lua_State* L) {
|
||||||
int argc = lua_gettop(L) - 2; // number of arguments after function name and object?
|
int argc = lua_gettop(L) - 2; // number of arguments after function name and object?
|
||||||
if(argc < 0) return luaL_error(L, "_bllua_ts.callobj: Must provide an object and function name");
|
if (argc < 0)
|
||||||
|
return luaL_error(L, "_bllua_ts.callobj: Must provide an object and function name");
|
||||||
|
|
||||||
const char* oname = luaL_checkstring(L, 1);
|
const char* oname = luaL_checkstring(L, 1);
|
||||||
const char* fname = luaL_checkstring(L, 2);
|
const char* fname = luaL_checkstring(L, 2);
|
||||||
@@ -110,19 +246,24 @@ int bll_lua_tsgetfield(lua_State* L) {
|
|||||||
const char* oname = luaL_checkstring(L, 1);
|
const char* oname = luaL_checkstring(L, 1);
|
||||||
const char* vname = luaL_checkstring(L, 2);
|
const char* vname = luaL_checkstring(L, 2);
|
||||||
ADDR obj = BlObject(oname);
|
ADDR obj = BlObject(oname);
|
||||||
if(!obj) { return luaL_error(L, "_bllua_ts.getfield: Object not found"); }
|
if (!obj) {
|
||||||
|
return luaL_error(L, "_bllua_ts.getfield: Object not found");
|
||||||
|
}
|
||||||
|
|
||||||
const char* val = BlGetField(obj, vname, NULL);
|
const char* val = BlGetField(obj, vname, NULL);
|
||||||
lua_pushstring(L, val);
|
lua_pushstring(L, val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua lib function: ts.setfield
|
// Lua lib function: ts.setfield
|
||||||
int bll_lua_tssetfield(lua_State* L) {
|
int bll_lua_tssetfield(lua_State* L) {
|
||||||
const char* oname = luaL_checkstring(L, 1);
|
const char* oname = luaL_checkstring(L, 1);
|
||||||
const char* vname = luaL_checkstring(L, 2);
|
const char* vname = luaL_checkstring(L, 2);
|
||||||
const char* val = luaL_checkstring(L, 3);
|
const char* val = luaL_checkstring(L, 3);
|
||||||
ADDR obj = BlObject(oname);
|
ADDR obj = BlObject(oname);
|
||||||
if(!obj) { return luaL_error(L, "_bllua_ts.setfield: Object not found"); }
|
if (!obj) {
|
||||||
|
return luaL_error(L, "_bllua_ts.setfield: Object not found");
|
||||||
|
}
|
||||||
|
|
||||||
BlSetField(obj, vname, NULL, val);
|
BlSetField(obj, vname, NULL, val);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -145,15 +286,10 @@ int bll_lua_tsecho(lua_State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const luaL_Reg bll_lua_reg[] = {
|
const luaL_Reg bll_lua_reg[] = {
|
||||||
{"call" , bll_lua_tscall },
|
{"call", bll_lua_tscall}, {"callobj", bll_lua_tscallobj},
|
||||||
{"callobj" , bll_lua_tscallobj },
|
{"getvar", bll_lua_tsgetvar}, {"getfield", bll_lua_tsgetfield},
|
||||||
{"getvar" , bll_lua_tsgetvar },
|
{"setfield", bll_lua_tssetfield}, {"eval", bll_lua_tseval},
|
||||||
{"getfield", bll_lua_tsgetfield},
|
{"echo", bll_lua_tsecho}, {NULL, NULL},
|
||||||
{"setfield", bll_lua_tssetfield},
|
|
||||||
{"eval" , bll_lua_tseval },
|
|
||||||
{"echo" , bll_lua_tsecho },
|
|
||||||
{NULL, NULL},
|
|
||||||
};
|
};
|
||||||
void llibbl_init(lua_State* L) {
|
|
||||||
luaL_register(L, "_bllua_ts", bll_lua_reg);
|
void llibbl_init(lua_State* L) { luaL_register(L, "_bllua_ts", bll_lua_reg); }
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
|
|
||||||
// Call a Lua function from TS, return true if success - result will be on Lua stack
|
// Call a Lua function from TS, return true if success - result will be on Lua
|
||||||
|
// stack
|
||||||
|
#include "BlFuncs.hpp"
|
||||||
|
#include "BlHooks.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++) {
|
||||||
@@ -14,9 +19,12 @@ bool bll_LuaCall(const char* fname, int argc, const char* argv[]) {
|
|||||||
|
|
||||||
// TS lib function: luacall
|
// TS lib function: luacall
|
||||||
const char* bll_ts_luacall(ADDR obj, int argc, const char* argv[]) {
|
const char* bll_ts_luacall(ADDR obj, int argc, const char* argv[]) {
|
||||||
if(argc<2) return "";
|
if (argc < 2)
|
||||||
|
return "";
|
||||||
|
|
||||||
if(!bll_LuaCall(argv[1], argc-2, &argv[2])) { return ""; }
|
if (!bll_LuaCall(argv[1], argc - 2, &argv[2])) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
char* retbuf = BlReturnBuffer(BLL_ARG_MAX);
|
char* retbuf = BlReturnBuffer(BLL_ARG_MAX);
|
||||||
bll_toarg(gL, retbuf, -1, false); // provide returned value to ts
|
bll_toarg(gL, retbuf, -1, false); // provide returned value to ts
|
||||||
|
|||||||
@@ -24,8 +24,11 @@ local function ipairsNilable(t)
|
|||||||
local i = 0
|
local i = 0
|
||||||
return function()
|
return function()
|
||||||
i = i + 1
|
i = i + 1
|
||||||
if i>maxk then return nil
|
if i > maxk then
|
||||||
else return i, t[i] end
|
return nil
|
||||||
|
else
|
||||||
|
return i, t[i]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -133,17 +136,23 @@ local function forceValFromTs(val, typ)
|
|||||||
end
|
end
|
||||||
local function vectorFromTs(val)
|
local function vectorFromTs(val)
|
||||||
local xS, yS, zS = val:match('^(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+)$')
|
local xS, yS, zS = val:match('^(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+)$')
|
||||||
if xS then return vector{tonumber(xS),tonumber(yS),tonumber(zS)}
|
if xS then
|
||||||
else return nil end
|
return vector { tonumber(xS), tonumber(yS), tonumber(zS) }
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local function boxFromTs(val)
|
local function boxFromTs(val)
|
||||||
local x1S, y1S, z1S, x2S, y2S, z2S = val:match(
|
local x1S, y1S, z1S, x2S, y2S, z2S = val:match(
|
||||||
'^(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+) ' ..
|
'^(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+) ' ..
|
||||||
'(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+)$')
|
'(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+)$')
|
||||||
if x1S then return {
|
if x1S then
|
||||||
|
return {
|
||||||
vector { tonumber(x1S), tonumber(y1S), tonumber(z1S) },
|
vector { tonumber(x1S), tonumber(y1S), tonumber(z1S) },
|
||||||
vector { tonumber(x2S), tonumber(y2S), tonumber(z2S) } }
|
vector { tonumber(x2S), tonumber(y2S), tonumber(z2S) } }
|
||||||
else return nil end
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local function multinumericFromTs(val)
|
local function multinumericFromTs(val)
|
||||||
local tsNumPat = '%-?[0-9]+%.?[0-9]*e?[0-9]*'
|
local tsNumPat = '%-?[0-9]+%.?[0-9]*e?[0-9]*'
|
||||||
@@ -173,7 +182,8 @@ bl._forceType = bl._forceType or {}
|
|||||||
-- todo: ensure name and name2 are already lowercase
|
-- todo: ensure name and name2 are already lowercase
|
||||||
local function valFromTs(val, name, name2)
|
local function valFromTs(val, name, name2)
|
||||||
if type(val) ~= 'string' then
|
if type(val) ~= 'string' then
|
||||||
error('valFromTs: expected string, got '..type(val), 3) end
|
error('valFromTs: expected string, got ' .. type(val), 3)
|
||||||
|
end
|
||||||
if name then
|
if name then
|
||||||
name = name:lower()
|
name = name:lower()
|
||||||
if bl._forceType[name] then
|
if bl._forceType[name] then
|
||||||
@@ -195,7 +205,7 @@ local function valFromTs(val, name, name2)
|
|||||||
local vec = multinumericFromTs(val)
|
local vec = multinumericFromTs(val)
|
||||||
if vec then return vec end
|
if vec then return vec end
|
||||||
-- net string
|
-- net string
|
||||||
if val:sub(1,1)=='\x01' then
|
if val:sub(1, 1) == '\001' then
|
||||||
return _bllua_ts.call('getTaggedString', val)
|
return _bllua_ts.call('getTaggedString', val)
|
||||||
end
|
end
|
||||||
-- string
|
-- string
|
||||||
@@ -218,15 +228,18 @@ end
|
|||||||
local function classFromForceTypeStr(name)
|
local function classFromForceTypeStr(name)
|
||||||
local class, rest = name:match('^([a-zA-Z0-9_]+)(::.+)$')
|
local class, rest = name:match('^([a-zA-Z0-9_]+)(::.+)$')
|
||||||
if not class then
|
if not class then
|
||||||
class, rest = name:match('^([a-zA-Z0-9_]+)(%..+)$') end
|
class, rest = name:match('^([a-zA-Z0-9_]+)(%..+)$')
|
||||||
|
end
|
||||||
return class, rest
|
return class, rest
|
||||||
end
|
end
|
||||||
local setForceType
|
local setForceType
|
||||||
setForceType = function(ftname, typ)
|
setForceType = function(ftname, typ)
|
||||||
if typ ~= nil and not fromTsForceTypes[typ] then
|
if typ ~= nil and not fromTsForceTypes[typ] then
|
||||||
error('bl.type: invalid type \''..typ..'\'', 2) end
|
error('bl.type: invalid type \'' .. typ .. '\'', 2)
|
||||||
|
end
|
||||||
if not isValidFuncNameNsArgn(ftname) then
|
if not isValidFuncNameNsArgn(ftname) then
|
||||||
error('bl.type: invalid function or variable name \''..ftname..'\'', 2) end
|
error('bl.type: invalid function or variable name \'' .. ftname .. '\'', 2)
|
||||||
|
end
|
||||||
|
|
||||||
ftname = ftname:lower()
|
ftname = ftname:lower()
|
||||||
|
|
||||||
@@ -277,15 +290,19 @@ local function tsIsFunction(name) return tsBool(_bllua_ts.call('isFunction', nam
|
|||||||
local function tsIsFunctionNs(ns, name) return tsBool(_bllua_ts.call('isFunction', ns, name)) end
|
local function tsIsFunctionNs(ns, name) return tsBool(_bllua_ts.call('isFunction', ns, name)) end
|
||||||
local function tsIsFunctionNsname(nsname)
|
local function tsIsFunctionNsname(nsname)
|
||||||
local ns, name = nsname:match('^([^:]+)::([^:]+)$')
|
local ns, name = nsname:match('^([^:]+)::([^:]+)$')
|
||||||
if ns then return tsIsFunctionNs(ns, name)
|
if ns then
|
||||||
else return tsIsFunction(nsname) end
|
return tsIsFunctionNs(ns, name)
|
||||||
|
else
|
||||||
|
return tsIsFunction(nsname)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
-- sanity check to make sure objects that don't isObject are always marked as ._deleted
|
-- sanity check to make sure objects that don't isObject are always marked as ._deleted
|
||||||
-- can be removed later
|
-- can be removed later
|
||||||
local function assertTsObjectExists(obj)
|
local function assertTsObjectExists(obj)
|
||||||
local is = tsIsObject(obj._tsObjectId)
|
local is = tsIsObject(obj._tsObjectId)
|
||||||
if not is then
|
if not is then
|
||||||
print('Warning: TS object :exists or isobject from lua but no longer exists') end
|
print('Warning: TS object :exists or isobject from lua but no longer exists')
|
||||||
|
end
|
||||||
return is
|
return is
|
||||||
end
|
end
|
||||||
function bl.isObject(obj)
|
function bl.isObject(obj)
|
||||||
@@ -303,6 +320,7 @@ function bl.isObject(obj)
|
|||||||
error('bl.isObject: argument #1: expected torque object, number, or string', 2)
|
error('bl.isObject: argument #1: expected torque object, number, or string', 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.isFunction(name)
|
function bl.isFunction(name)
|
||||||
return tsIsFunctionNsname(name)
|
return tsIsFunctionNsname(name)
|
||||||
end
|
end
|
||||||
@@ -317,9 +335,11 @@ local tsClassMeta = {
|
|||||||
bl._objectUserMetas = bl._objectUserMetas or {}
|
bl._objectUserMetas = bl._objectUserMetas or {}
|
||||||
function bl.class(cname, inhname)
|
function bl.class(cname, inhname)
|
||||||
if not (type(cname) == 'string' and isValidFuncName(cname)) then
|
if not (type(cname) == 'string' and isValidFuncName(cname)) then
|
||||||
error('bl.class: argument #1: invalid class name', 2) end
|
error('bl.class: argument #1: invalid class name', 2)
|
||||||
|
end
|
||||||
if not (inhname == nil or (type(inhname) == 'string' and isValidFuncName(inhname))) then
|
if not (inhname == nil or (type(inhname) == 'string' and isValidFuncName(inhname))) then
|
||||||
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
|
||||||
cname = cname:lower()
|
cname = cname:lower()
|
||||||
|
|
||||||
local met = bl._objectUserMetas[cname] or {
|
local met = bl._objectUserMetas[cname] or {
|
||||||
@@ -334,15 +354,18 @@ function bl.class(cname, inhname)
|
|||||||
inhname = inhname:lower()
|
inhname = inhname:lower()
|
||||||
|
|
||||||
local inh = bl._objectUserMetas[inhname]
|
local inh = bl._objectUserMetas[inhname]
|
||||||
if not inh then error('bl.class: argument #2: \''..inhname..'\' is not the '..
|
if not inh then
|
||||||
'name of an existing class', 2) end
|
error('bl.class: argument #2: \'' .. inhname .. '\' is not the ' ..
|
||||||
|
'name of an existing class', 2)
|
||||||
|
end
|
||||||
|
|
||||||
inh._children[cname] = true
|
inh._children[cname] = true
|
||||||
|
|
||||||
local inhI = met._inherit
|
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
|
||||||
met._inherit = inh
|
met._inherit = inh
|
||||||
|
|
||||||
-- apply inherited method and field types
|
-- apply inherited method and field types
|
||||||
@@ -354,6 +377,7 @@ function bl.class(cname, inhname)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function objectInheritedMetas(name)
|
local function objectInheritedMetas(name)
|
||||||
local inh = bl._objectUserMetas[name:lower()]
|
local inh = bl._objectUserMetas[name:lower()]
|
||||||
return function()
|
return function()
|
||||||
@@ -368,15 +392,18 @@ local tsObjectMeta = {
|
|||||||
-- Return torque member function or value
|
-- Return torque member function or value
|
||||||
__index = function(t, name)
|
__index = function(t, name)
|
||||||
if rawget(t, '_deleted') then
|
if rawget(t, '_deleted') then
|
||||||
error('ts object index: object no longer exists', 2) end
|
error('ts object index: object no longer exists', 2)
|
||||||
|
end
|
||||||
if type(name) ~= 'string' and type(name) ~= 'number' then
|
if type(name) ~= 'string' and type(name) ~= 'number' then
|
||||||
error('ts object index: index must be a string or number', 2) end
|
error('ts object index: index must be a string or number', 2)
|
||||||
|
end
|
||||||
if getmetatable(t)[name] then
|
if getmetatable(t)[name] then
|
||||||
return getmetatable(t)[name]
|
return getmetatable(t)[name]
|
||||||
elseif type(name) == 'number' then
|
elseif type(name) == 'number' then
|
||||||
if not tsIsFunctionNs(rawget(t, '_tsNamespace'), 'getObject') then
|
if not tsIsFunctionNs(rawget(t, '_tsNamespace'), 'getObject') then
|
||||||
error('ts object __index: index is number, but object does not have ' ..
|
error('ts object __index: index is number, but object does not have ' ..
|
||||||
'getObject method', 2) end
|
'getObject method', 2)
|
||||||
|
end
|
||||||
return toTsObject(_bllua_ts.callobj(t._tsObjectId, 'getObject',
|
return toTsObject(_bllua_ts.callobj(t._tsObjectId, 'getObject',
|
||||||
tostring(name)))
|
tostring(name)))
|
||||||
else
|
else
|
||||||
@@ -389,7 +416,8 @@ local tsObjectMeta = {
|
|||||||
then
|
then
|
||||||
return function(t2, ...)
|
return function(t2, ...)
|
||||||
if t2 == nil or type(t2) ~= 'table' or not t2._tsObjectId then
|
if t2 == nil or type(t2) ~= 'table' or not t2._tsObjectId then
|
||||||
error('ts object method: be sure to use :func() not .func()', 2) end
|
error('ts object method: be sure to use :func() not .func()', 2)
|
||||||
|
end
|
||||||
local argsS = arglistToTs({ ... })
|
local argsS = arglistToTs({ ... })
|
||||||
local res =
|
local res =
|
||||||
_bllua_ts.callobj(t2._tsObjectId, name, unpack(argsS))
|
_bllua_ts.callobj(t2._tsObjectId, name, unpack(argsS))
|
||||||
@@ -410,9 +438,11 @@ local tsObjectMeta = {
|
|||||||
-- Use :set() to set Torque data
|
-- Use :set() to set Torque data
|
||||||
__newindex = function(t, name, val)
|
__newindex = function(t, name, val)
|
||||||
if rawget(t, '_deleted') then
|
if rawget(t, '_deleted') then
|
||||||
error('ts object newindex: object no longer exists', 2) end
|
error('ts object newindex: object no longer exists', 2)
|
||||||
|
end
|
||||||
if type(name) ~= 'string' then
|
if type(name) ~= 'string' then
|
||||||
error('ts object newindex: index must be a string', 2) end
|
error('ts object newindex: index must be a string', 2)
|
||||||
|
end
|
||||||
rawset(t, name, val)
|
rawset(t, name, val)
|
||||||
-- create strong reference since it's now storing lua data
|
-- create strong reference since it's now storing lua data
|
||||||
bl._objectsStrong[rawget(t, '_tsObjectId')] = t
|
bl._objectsStrong[rawget(t, '_tsObjectId')] = t
|
||||||
@@ -421,11 +451,14 @@ local tsObjectMeta = {
|
|||||||
-- Use to set torque data
|
-- Use to set torque data
|
||||||
set = function(t, name, val)
|
set = function(t, name, val)
|
||||||
if t == nil or type(t) ~= 'table' or not t._tsObjectId then
|
if t == nil or type(t) ~= 'table' or not t._tsObjectId then
|
||||||
error('ts object method: be sure to use :func() not .func()', 2) end
|
error('ts object method: be sure to use :func() not .func()', 2)
|
||||||
|
end
|
||||||
if t._deleted then
|
if t._deleted then
|
||||||
error('ts object method: object no longer exists', 2) end
|
error('ts object method: object no longer exists', 2)
|
||||||
|
end
|
||||||
if type(name) ~= 'string' then
|
if type(name) ~= 'string' then
|
||||||
error('ts object :set(): index must be a string', 2) end
|
error('ts object :set(): index must be a string', 2)
|
||||||
|
end
|
||||||
_bllua_ts.setfield(t._tsObjectId, name, valToTs(val))
|
_bllua_ts.setfield(t._tsObjectId, name, valToTs(val))
|
||||||
end,
|
end,
|
||||||
-- __tostring: Called when printing
|
-- __tostring: Called when printing
|
||||||
@@ -439,9 +472,11 @@ local tsObjectMeta = {
|
|||||||
-- If the object has a getCount method, return its count
|
-- If the object has a getCount method, return its count
|
||||||
__len = function(t)
|
__len = function(t)
|
||||||
if t._deleted then
|
if t._deleted then
|
||||||
error('ts object __len: object no longer exists', 2) end
|
error('ts object __len: object no longer exists', 2)
|
||||||
|
end
|
||||||
if not tsIsFunctionNs(t._tsNamespace, 'getCount') then
|
if not tsIsFunctionNs(t._tsNamespace, 'getCount') then
|
||||||
error('ts object __len: object has no getCount method', 2) end
|
error('ts object __len: object has no getCount method', 2)
|
||||||
|
end
|
||||||
return tonumber(_bllua_ts.callobj(t._tsObjectId, 'getCount'))
|
return tonumber(_bllua_ts.callobj(t._tsObjectId, 'getCount'))
|
||||||
end,
|
end,
|
||||||
-- object:members()
|
-- object:members()
|
||||||
@@ -449,14 +484,17 @@ local tsObjectMeta = {
|
|||||||
-- for index, object in group:members() do ... end
|
-- for index, object in group:members() do ... end
|
||||||
members = function(t)
|
members = function(t)
|
||||||
if t == nil then
|
if t == nil then
|
||||||
error('ts object method: be sure to use :func() not .func()', 2) end
|
error('ts object method: be sure to use :func() not .func()', 2)
|
||||||
|
end
|
||||||
if t._deleted then
|
if t._deleted then
|
||||||
error('ts object method: object no longer exists', 2) end
|
error('ts object method: object no longer exists', 2)
|
||||||
|
end
|
||||||
if not (
|
if not (
|
||||||
tsIsFunctionNs(t._tsNamespace, 'getCount') and
|
tsIsFunctionNs(t._tsNamespace, 'getCount') and
|
||||||
tsIsFunctionNs(t._tsNamespace, 'getObject')) then
|
tsIsFunctionNs(t._tsNamespace, 'getObject')) then
|
||||||
error('ts object :members() - ' ..
|
error('ts object :members() - ' ..
|
||||||
'Object does not have getCount and getObject methods', 2) end
|
'Object does not have getCount and getObject methods', 2)
|
||||||
|
end
|
||||||
local count = tonumber(_bllua_ts.callobj(t._tsObjectId, 'getCount'))
|
local count = tonumber(_bllua_ts.callobj(t._tsObjectId, 'getCount'))
|
||||||
local idx = 0
|
local idx = 0
|
||||||
return function()
|
return function()
|
||||||
@@ -474,23 +512,29 @@ local tsObjectMeta = {
|
|||||||
-- Wrap some Torque functions for performance and error checking
|
-- Wrap some Torque functions for performance and error checking
|
||||||
getName = function(t)
|
getName = function(t)
|
||||||
if t == nil then
|
if t == nil then
|
||||||
error('ts object method: be sure to use :func() not .func()', 2) end
|
error('ts object method: be sure to use :func() not .func()', 2)
|
||||||
|
end
|
||||||
if t._deleted then
|
if t._deleted then
|
||||||
error('ts object method: object no longer exists', 2) end
|
error('ts object method: object no longer exists', 2)
|
||||||
|
end
|
||||||
return t._tsName
|
return t._tsName
|
||||||
end,
|
end,
|
||||||
getId = function(t)
|
getId = function(t)
|
||||||
if t == nil then
|
if t == nil then
|
||||||
error('ts object method: be sure to use :func() not .func()', 2) end
|
error('ts object method: be sure to use :func() not .func()', 2)
|
||||||
|
end
|
||||||
if t._deleted then
|
if t._deleted then
|
||||||
error('ts object method: object no longer exists', 2) end
|
error('ts object method: object no longer exists', 2)
|
||||||
|
end
|
||||||
return tonumber(t._tsObjectId)
|
return tonumber(t._tsObjectId)
|
||||||
end,
|
end,
|
||||||
getType = function(t)
|
getType = function(t)
|
||||||
if t == nil then
|
if t == nil then
|
||||||
error('ts object method: be sure to use :func() not .func()', 2) end
|
error('ts object method: be sure to use :func() not .func()', 2)
|
||||||
|
end
|
||||||
if t._deleted then
|
if t._deleted then
|
||||||
error('ts object method: object no longer exists', 2) end
|
error('ts object method: object no longer exists', 2)
|
||||||
|
end
|
||||||
return tsTypesByNum[_bllua_ts.callobj(t._tsObjectId, 'getType')]
|
return tsTypesByNum[_bllua_ts.callobj(t._tsObjectId, 'getType')]
|
||||||
end,
|
end,
|
||||||
---- Schedule method for objects
|
---- Schedule method for objects
|
||||||
@@ -512,7 +556,8 @@ local tsObjectMeta = {
|
|||||||
--end,
|
--end,
|
||||||
exists = function(t)
|
exists = function(t)
|
||||||
if t == nil then
|
if t == nil then
|
||||||
error('ts object method: be sure to use :func() not .func()', 2) end
|
error('ts object method: be sure to use :func() not .func()', 2)
|
||||||
|
end
|
||||||
if t._deleted then
|
if t._deleted then
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
@@ -546,13 +591,15 @@ end
|
|||||||
-- Return a Torque object for the object ID string, or create one if none exists
|
-- Return a Torque object for the object ID string, or create one if none exists
|
||||||
toTsObject = function(idiS)
|
toTsObject = function(idiS)
|
||||||
if type(idiS) ~= 'string' then
|
if type(idiS) ~= 'string' then
|
||||||
error('toTsObject: input must be a string', 2) end
|
error('toTsObject: input must be a string', 2)
|
||||||
|
end
|
||||||
idiS = idiS:lower()
|
idiS = idiS:lower()
|
||||||
if bl._objectsWeak[idiS] then return bl._objectsWeak[idiS] end
|
if bl._objectsWeak[idiS] then return bl._objectsWeak[idiS] end
|
||||||
|
|
||||||
if not tsIsObject(idiS) then
|
if not tsIsObject(idiS) then
|
||||||
--error('toTsObject: object \''..idiS..'\' does not exist', 2) end
|
--error('toTsObject: object \''..idiS..'\' does not exist', 2) end
|
||||||
return nil end
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local className = _bllua_ts.callobj(idiS, 'getClassName')
|
local className = _bllua_ts.callobj(idiS, 'getClassName')
|
||||||
local obj = {
|
local obj = {
|
||||||
@@ -641,18 +688,22 @@ function bl.call(func, ...)
|
|||||||
local argsS = arglistToTs(args)
|
local argsS = arglistToTs(args)
|
||||||
return _bllua_ts.call(func, unpack(argsS))
|
return _bllua_ts.call(func, unpack(argsS))
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.eval(code)
|
function bl.eval(code)
|
||||||
local res = _bllua_ts.eval(code)
|
local res = _bllua_ts.eval(code)
|
||||||
return valFromTs(res)
|
return valFromTs(res)
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.exec(file)
|
function bl.exec(file)
|
||||||
local res = _bllua_ts.call('exec', file)
|
local res = _bllua_ts.call('exec', file)
|
||||||
return valFromTs(res)
|
return valFromTs(res)
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.array(name, ...)
|
function bl.array(name, ...)
|
||||||
local rest = { ... }
|
local rest = { ... }
|
||||||
return name .. table.concat(rest, '_')
|
return name .. table.concat(rest, '_')
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.boolean(val)
|
function bl.boolean(val)
|
||||||
return val ~= nil and
|
return val ~= nil and
|
||||||
val ~= false and
|
val ~= false and
|
||||||
@@ -660,6 +711,7 @@ function bl.boolean(val)
|
|||||||
--val~='0' and
|
--val~='0' and
|
||||||
val ~= 0
|
val ~= 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.object(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
|
||||||
@@ -669,6 +721,7 @@ function bl.object(id)
|
|||||||
error('bl.object: id must be a ts object, number, or string', 2)
|
error('bl.object: id must be a ts object, number, or string', 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.string(val)
|
function bl.string(val)
|
||||||
return valFromTsTostring(val)
|
return valFromTsTostring(val)
|
||||||
end
|
end
|
||||||
@@ -679,24 +732,33 @@ luaLookup = function(tbl, name, set, val)
|
|||||||
if name:find('%.') then
|
if name:find('%.') then
|
||||||
local first, rest = name:match('^([^%.:]+)%.(.+)$')
|
local first, rest = name:match('^([^%.:]+)%.(.+)$')
|
||||||
if not isValidFuncName(first) then
|
if not isValidFuncName(first) then
|
||||||
error('luaLookup: invalid name \''..tostring(first)..'\'', 3) end
|
error('luaLookup: invalid name \'' .. tostring(first) .. '\'', 3)
|
||||||
|
end
|
||||||
if tbl[first] == nil then
|
if tbl[first] == nil then
|
||||||
if set then tbl[first] = {}
|
if set then
|
||||||
else return nil end
|
tbl[first] = {}
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return luaLookup(tbl[first], rest, set, val)
|
return luaLookup(tbl[first], rest, set, val)
|
||||||
elseif name:find(':') then
|
elseif name:find(':') then
|
||||||
local first, rest = name:match('^([^%.:]+):(.*)$')
|
local first, rest = name:match('^([^%.:]+):(.*)$')
|
||||||
if rest:find('[%.:]') then
|
if rest:find('[%.:]') then
|
||||||
error('luacall: cannot have : or . after :', 3) end
|
error('luacall: cannot have : or . after :', 3)
|
||||||
|
end
|
||||||
if not isValidFuncName(first) then
|
if not isValidFuncName(first) then
|
||||||
error('luacall: invalid name \''..tostring(first)..'\'', 3) end
|
error('luacall: invalid name \'' .. tostring(first) .. '\'', 3)
|
||||||
|
end
|
||||||
if not isValidFuncName(rest) then
|
if not isValidFuncName(rest) then
|
||||||
error('luacall: invalid method name \''..tostring(first)..'\'', 3) end
|
error('luacall: invalid method name \'' .. tostring(first) .. '\'', 3)
|
||||||
|
end
|
||||||
if not tbl[first] then
|
if not tbl[first] then
|
||||||
error('luacall: no object named \''..rest..'\'', 3) end
|
error('luacall: no object named \'' .. rest .. '\'', 3)
|
||||||
|
end
|
||||||
if tbl[first][rest] == nil then
|
if tbl[first][rest] == nil then
|
||||||
error('luacall: no method named \''..rest..'\'', 3) end
|
error('luacall: no method named \'' .. rest .. '\'', 3)
|
||||||
|
end
|
||||||
return function(...)
|
return function(...)
|
||||||
tbl[first][rest](tbl[first], ...)
|
tbl[first][rest](tbl[first], ...)
|
||||||
end
|
end
|
||||||
@@ -713,19 +775,23 @@ function _bllua_call(fname, ...)
|
|||||||
local args = arglistFromTs(fname:lower(), { ... }) -- todo: separate lua from ts func names?
|
local args = arglistFromTs(fname:lower(), { ... }) -- todo: separate lua from ts func names?
|
||||||
local func = luaLookup(_G, fname)
|
local func = luaLookup(_G, fname)
|
||||||
if not func then
|
if not func then
|
||||||
error('luacall: no global in lua named \''..fname..'\'', 2) end
|
error('luacall: no global in lua named \'' .. fname .. '\'', 2)
|
||||||
|
end
|
||||||
local res = func(unpack(args))
|
local res = func(unpack(args))
|
||||||
return valToTs(res)
|
return valToTs(res)
|
||||||
end
|
end
|
||||||
|
|
||||||
function _bllua_getvar(vname)
|
function _bllua_getvar(vname)
|
||||||
return valToTs(luaLookup(_G, vname))
|
return valToTs(luaLookup(_G, vname))
|
||||||
end
|
end
|
||||||
|
|
||||||
function _bllua_setvar(vname, valS)
|
function _bllua_setvar(vname, valS)
|
||||||
return valToTs(luaLookup(_G, vname, true, valFromTs(valS, vname))) -- todo: separate lua from ts var names?
|
return valToTs(luaLookup(_G, vname, true, valFromTs(valS, vname))) -- todo: separate lua from ts var names?
|
||||||
end
|
end
|
||||||
function _bllua_eval(code) return loadstring(code)() end
|
|
||||||
function _bllua_exec(fn) return dofile(fn, 2) end
|
|
||||||
|
|
||||||
|
function _bllua_eval(code) return loadstring(code)() end
|
||||||
|
|
||||||
|
function _bllua_exec(fn) return dofile(fn, 2) end
|
||||||
|
|
||||||
-- bl.schedule: Use TS's schedule function to schedule lua calls
|
-- bl.schedule: Use TS's schedule function to schedule lua calls
|
||||||
-- bl.schedule(time, function, args...)
|
-- bl.schedule(time, function, args...)
|
||||||
@@ -753,6 +819,7 @@ function bl.schedule(time, cb, ...)
|
|||||||
bl._scheduleTable[id] = sch
|
bl._scheduleTable[id] = sch
|
||||||
return sch
|
return sch
|
||||||
end
|
end
|
||||||
|
|
||||||
function _bllua_schedule_callback(idS)
|
function _bllua_schedule_callback(idS)
|
||||||
local id = tonumber(idS) or
|
local id = tonumber(idS) or
|
||||||
error('_bllua_schedule_callback: invalid id: ' .. tostring(idS))
|
error('_bllua_schedule_callback: invalid id: ' .. tostring(idS))
|
||||||
@@ -771,9 +838,11 @@ function _bllua_process_cmd(cmdS, ...)
|
|||||||
if not func then error('_bllua_process_cmd: no cmd named \'' .. cmd .. '\'') end
|
if not func then error('_bllua_process_cmd: no cmd named \'' .. cmd .. '\'') end
|
||||||
func(unpack(args)) --pcall(func, unpack(args))
|
func(unpack(args)) --pcall(func, unpack(args))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function addCmd(cmd, func)
|
local function addCmd(cmd, func)
|
||||||
if not isValidFuncName(cmd) then
|
if not isValidFuncName(cmd) then
|
||||||
error('addCmd: invalid function name \''..tostring(cmd)..'\'') end
|
error('addCmd: invalid function name \'' .. tostring(cmd) .. '\'')
|
||||||
|
end
|
||||||
bl._cmds[cmd] = func
|
bl._cmds[cmd] = func
|
||||||
_bllua_ts.eval('function ' .. cmd .. '(' .. tsArgsLocal .. '){' ..
|
_bllua_ts.eval('function ' .. cmd .. '(' .. tsArgsLocal .. '){' ..
|
||||||
'_bllua_luacall(_bllua_process_cmd,"' .. cmd .. '",' .. tsArgsLocal .. ');}')
|
'_bllua_luacall(_bllua_process_cmd,"' .. cmd .. '",' .. tsArgsLocal .. ');}')
|
||||||
@@ -783,6 +852,7 @@ function bl.addServerCmd(name, func)
|
|||||||
addCmd('servercmd' .. name, func)
|
addCmd('servercmd' .. name, func)
|
||||||
bl._forceType['servercmd' .. name .. ':1'] = 'object'
|
bl._forceType['servercmd' .. name .. ':1'] = 'object'
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.addClientCmd(name, func)
|
function bl.addClientCmd(name, func)
|
||||||
name = name:lower()
|
name = name:lower()
|
||||||
addCmd('clientcmd' .. name, func)
|
addCmd('clientcmd' .. name, func)
|
||||||
@@ -794,12 +864,14 @@ function bl.commandToServer(cmd, ...)
|
|||||||
_bllua_ts.call('addTaggedString', cmd),
|
_bllua_ts.call('addTaggedString', cmd),
|
||||||
unpack(arglistToTs({ ... })))
|
unpack(arglistToTs({ ... })))
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.commandToClient(client, cmd, ...)
|
function bl.commandToClient(client, cmd, ...)
|
||||||
_bllua_ts.call('commandToClient',
|
_bllua_ts.call('commandToClient',
|
||||||
valToTs(client),
|
valToTs(client),
|
||||||
_bllua_ts.call('addTaggedString', cmd),
|
_bllua_ts.call('addTaggedString', cmd),
|
||||||
unpack(arglistToTs({ ... })))
|
unpack(arglistToTs({ ... })))
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.commandToAll(cmd, ...)
|
function bl.commandToAll(cmd, ...)
|
||||||
_bllua_ts.call('commandToAll',
|
_bllua_ts.call('commandToAll',
|
||||||
_bllua_ts.call('addTaggedString', cmd),
|
_bllua_ts.call('addTaggedString', cmd),
|
||||||
@@ -831,7 +903,8 @@ function _bllua_process_hook_before(pkgS, nameS, ...)
|
|||||||
local func = bl._hooks[pkgS] and bl._hooks[pkgS][nameS] and
|
local func = bl._hooks[pkgS] and bl._hooks[pkgS][nameS] and
|
||||||
bl._hooks[pkgS][nameS].before
|
bl._hooks[pkgS][nameS].before
|
||||||
if not func then
|
if not func then
|
||||||
error('_bllua_process_hook_before: no hook for '..pkgs..':'..nameS) end
|
error('_bllua_process_hook_before: no hook for ' .. pkgs .. ':' .. nameS)
|
||||||
|
end
|
||||||
_bllua_ts.setvar('_bllua_hook_abort', '0')
|
_bllua_ts.setvar('_bllua_hook_abort', '0')
|
||||||
func(args) --pcall(func, args)
|
func(args) --pcall(func, args)
|
||||||
if args._return then
|
if args._return then
|
||||||
@@ -842,6 +915,7 @@ function _bllua_process_hook_before(pkgS, nameS, ...)
|
|||||||
_bllua_ts.setvar('_bllua_hook_arg' .. i, valToTs(args[i]))
|
_bllua_ts.setvar('_bllua_hook_arg' .. i, valToTs(args[i]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function _bllua_process_hook_after(pkgS, nameS, resultS, ...)
|
function _bllua_process_hook_after(pkgS, nameS, resultS, ...)
|
||||||
nameS = nameS:lower()
|
nameS = nameS:lower()
|
||||||
local args = arglistFromTs(nameS, { ... })
|
local args = arglistFromTs(nameS, { ... })
|
||||||
@@ -849,10 +923,12 @@ function _bllua_process_hook_after(pkgS, nameS, resultS, ...)
|
|||||||
local func = bl._hooks[pkgS] and bl._hooks[pkgS][nameS] and
|
local func = bl._hooks[pkgS] and bl._hooks[pkgS][nameS] and
|
||||||
bl._hooks[pkgS][nameS].after
|
bl._hooks[pkgS][nameS].after
|
||||||
if not func then
|
if not func then
|
||||||
error('_bllua_process_hook_after: no hook for '..pkgs..':'..nameS) end
|
error('_bllua_process_hook_after: no hook for ' .. pkgs .. ':' .. nameS)
|
||||||
|
end
|
||||||
func(args) --pcall(func, args)
|
func(args) --pcall(func, args)
|
||||||
return valToTs(args._return)
|
return valToTs(args._return)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function updateHook(pkg, name, hk)
|
local function updateHook(pkg, name, hk)
|
||||||
local beforeCode = hk.before and
|
local beforeCode = hk.before and
|
||||||
('_bllua_luacall("_bllua_process_hook_before","' .. pkg .. '","' .. name ..
|
('_bllua_luacall("_bllua_process_hook_before","' .. pkg .. '","' .. name ..
|
||||||
@@ -879,13 +955,17 @@ local function updateHook(pkg, name, hk)
|
|||||||
end
|
end
|
||||||
function bl.hook(pkg, name, time, func)
|
function bl.hook(pkg, name, time, func)
|
||||||
if not isValidFuncName(pkg) then
|
if not isValidFuncName(pkg) then
|
||||||
error('bl.hook: argument #1: invalid package name \''..tostring(pkg)..'\'', 2) end
|
error('bl.hook: argument #1: invalid package name \'' .. tostring(pkg) .. '\'', 2)
|
||||||
|
end
|
||||||
if not isValidFuncNameNs(name) then
|
if not isValidFuncNameNs(name) then
|
||||||
error('bl.hook: argument #2: invalid function name \''..tostring(name)..'\'', 2) end
|
error('bl.hook: argument #2: invalid function name \'' .. tostring(name) .. '\'', 2)
|
||||||
|
end
|
||||||
if time ~= 'before' and time ~= 'after' then
|
if time ~= 'before' and time ~= 'after' then
|
||||||
error('bl.hook: argument #3: time must be \'before\' or \'after\'', 2) end
|
error('bl.hook: argument #3: time must be \'before\' or \'after\'', 2)
|
||||||
|
end
|
||||||
if type(func) ~= 'function' then
|
if type(func) ~= 'function' then
|
||||||
error('bl.hook: argument #4: expected a function', 2) end
|
error('bl.hook: argument #4: expected a function', 2)
|
||||||
|
end
|
||||||
|
|
||||||
bl._hooks[pkg] = bl._hooks[pkg] or {}
|
bl._hooks[pkg] = bl._hooks[pkg] or {}
|
||||||
bl._hooks[pkg][name] = bl._hooks[pkg][name] or {}
|
bl._hooks[pkg][name] = bl._hooks[pkg][name] or {}
|
||||||
@@ -894,16 +974,20 @@ function bl.hook(pkg, name, time, func)
|
|||||||
updateHook(pkg, name, bl._hooks[pkg][name])
|
updateHook(pkg, name, bl._hooks[pkg][name])
|
||||||
activatePackage(pkg)
|
activatePackage(pkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tableEmpty(t)
|
local function tableEmpty(t)
|
||||||
return next(t) ~= nil
|
return next(t) ~= nil
|
||||||
end
|
end
|
||||||
function bl.unhook(pkg, name, time)
|
function bl.unhook(pkg, name, time)
|
||||||
if not isValidFuncName(pkg) then
|
if not isValidFuncName(pkg) then
|
||||||
error('bl.unhook: argument #1: invalid package name \''..tostring(pkg)..'\'', 2) end
|
error('bl.unhook: argument #1: invalid package name \'' .. tostring(pkg) .. '\'', 2)
|
||||||
|
end
|
||||||
if name and not isValidFuncNameNs(name) then
|
if name and not isValidFuncNameNs(name) then
|
||||||
error('bl.unhook: argument #2: invalid function name \''..tostring(name)..'\'', 2) end
|
error('bl.unhook: argument #2: invalid function name \'' .. tostring(name) .. '\'', 2)
|
||||||
|
end
|
||||||
if time and 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
|
error('bl.unhook: argument #3: time must be \'before\' or \'after\'', 2)
|
||||||
|
end
|
||||||
|
|
||||||
if not name then
|
if not name then
|
||||||
if bl._hooks[pkg] then
|
if bl._hooks[pkg] then
|
||||||
@@ -927,7 +1011,8 @@ function bl.unhook(pkg, name, time)
|
|||||||
updateHook(pkg, name, {})
|
updateHook(pkg, name, {})
|
||||||
else
|
else
|
||||||
if time ~= 'before' and time ~= 'after' then
|
if time ~= 'before' and time ~= 'after' then
|
||||||
error('bl.unhook: argument #3: time must be nil, \'before\', or \'after\'', 2) end
|
error('bl.unhook: argument #3: time must be nil, \'before\', or \'after\'', 2)
|
||||||
|
end
|
||||||
bl._hooks[pkg][name][time] = nil
|
bl._hooks[pkg][name][time] = nil
|
||||||
if tableEmpty(bl._hooks[pkg][name]) then
|
if tableEmpty(bl._hooks[pkg][name]) then
|
||||||
bl._hooks[pkg][name] = nil
|
bl._hooks[pkg][name] = nil
|
||||||
@@ -950,14 +1035,16 @@ end
|
|||||||
-- Container search/raycast
|
-- Container search/raycast
|
||||||
local function vecToTs(v)
|
local function vecToTs(v)
|
||||||
if not isTsVector(v) then
|
if not isTsVector(v) then
|
||||||
error('vecToTs: argument is not a vector', 3) end
|
error('vecToTs: argument is not a vector', 3)
|
||||||
|
end
|
||||||
return table.concat(v, ' ')
|
return table.concat(v, ' ')
|
||||||
end
|
end
|
||||||
local function maskToTs(mask)
|
local function maskToTs(mask)
|
||||||
if type(mask) == 'string' then
|
if type(mask) == 'string' then
|
||||||
local val = tsTypesByName[mask:lower()]
|
local val = tsTypesByName[mask:lower()]
|
||||||
if not val then
|
if not val then
|
||||||
error('maskToTs: invalid mask \''..mask..'\'', 3) end
|
error('maskToTs: invalid mask \'' .. mask .. '\'', 3)
|
||||||
|
end
|
||||||
return tostring(val)
|
return tostring(val)
|
||||||
elseif type(mask) == 'table' then
|
elseif type(mask) == 'table' then
|
||||||
local tval = 0
|
local tval = 0
|
||||||
@@ -967,7 +1054,8 @@ local function maskToTs(mask)
|
|||||||
local val = tsTypesByName[v:lower()]
|
local val = tsTypesByName[v:lower()]
|
||||||
if not val then
|
if not val then
|
||||||
error('maskToTs: invalid mask \'' .. v ..
|
error('maskToTs: invalid mask \'' .. v ..
|
||||||
'\' at index '..i..' in mask list', 3) end
|
'\' at index ' .. i .. ' in mask list', 3)
|
||||||
|
end
|
||||||
tval = tval + val
|
tval = tval + val
|
||||||
seen[v] = true
|
seen[v] = true
|
||||||
end
|
end
|
||||||
@@ -1009,6 +1097,7 @@ function bl.raycast(start, stop, mask, ignores)
|
|||||||
return hit, pos, norm
|
return hit, pos, norm
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tsContainerSearchIterator()
|
local function tsContainerSearchIterator()
|
||||||
local retS = _bllua_ts.call('containerSearchNext')
|
local retS = _bllua_ts.call('containerSearchNext')
|
||||||
if retS == '0' then
|
if retS == '0' then
|
||||||
@@ -1025,10 +1114,12 @@ function bl.boxSearch(pos, size, mask)
|
|||||||
_bllua_ts.call('initContainerBoxSearch', posS, sizeS, maskS)
|
_bllua_ts.call('initContainerBoxSearch', posS, sizeS, maskS)
|
||||||
return tsContainerSearchIterator
|
return tsContainerSearchIterator
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.radiusSearch(pos, radius, mask)
|
function bl.radiusSearch(pos, radius, mask)
|
||||||
local posS = vecToTs(pos)
|
local posS = vecToTs(pos)
|
||||||
if type(radius) ~= 'number' then
|
if type(radius) ~= 'number' then
|
||||||
error('bl.radiusSearch: argument #2: radius must be a number', 2) end
|
error('bl.radiusSearch: argument #2: radius must be a number', 2)
|
||||||
|
end
|
||||||
local radiusS = tostring(radius)
|
local radiusS = tostring(radius)
|
||||||
local maskS = maskToTs(mask)
|
local maskS = maskToTs(mask)
|
||||||
|
|
||||||
@@ -1066,7 +1157,8 @@ local function createTsObj(keyword, class, name, inherit, props)
|
|||||||
if props then
|
if props then
|
||||||
for k, v in pairs(props) do
|
for k, v in pairs(props) do
|
||||||
if not isValidFuncName(k) then
|
if not isValidFuncName(k) then
|
||||||
error('bl.new/bl.datablock: invalid property name \''..k..'\'') end
|
error('bl.new/bl.datablock: invalid property name \'' .. k .. '\'')
|
||||||
|
end
|
||||||
table.insert(propsT, k .. '="' .. valToTs(v) .. '";')
|
table.insert(propsT, k .. '="' .. valToTs(v) .. '";')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1077,7 +1169,8 @@ local function createTsObj(keyword, class, name, inherit, props)
|
|||||||
table.concat(propsT) .. '};')
|
table.concat(propsT) .. '};')
|
||||||
local obj = toTsObject(objS)
|
local obj = toTsObject(objS)
|
||||||
if not obj then
|
if not obj then
|
||||||
error('bl.new/bl.datablock: failed to create object', 3) end
|
error('bl.new/bl.datablock: failed to create object', 3)
|
||||||
|
end
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
end
|
end
|
||||||
@@ -1102,13 +1195,15 @@ local function parseTsDecl(decl)
|
|||||||
(inherit == nil or isValidFuncName(inherit))) then
|
(inherit == nil or isValidFuncName(inherit))) then
|
||||||
error('bl.new/bl.datablock: invalid decl \'' .. decl .. '\'\n' ..
|
error('bl.new/bl.datablock: invalid decl \'' .. decl .. '\'\n' ..
|
||||||
'must be of the format: \'className\', \'className name\', ' ..
|
'must be of the format: \'className\', \'className name\', ' ..
|
||||||
'\'className :inherit\', or \'className name:inherit\'', 3) end
|
'\'className :inherit\', or \'className name:inherit\'', 3)
|
||||||
|
end
|
||||||
return class, name, inherit
|
return class, name, inherit
|
||||||
end
|
end
|
||||||
function bl.new(decl, props)
|
function bl.new(decl, props)
|
||||||
local class, name, inherit = parseTsDecl(decl)
|
local class, name, inherit = parseTsDecl(decl)
|
||||||
return createTsObj('new', class, name, inherit, props)
|
return createTsObj('new', class, name, inherit, props)
|
||||||
end
|
end
|
||||||
|
|
||||||
function bl.datablock(decl, props)
|
function bl.datablock(decl, props)
|
||||||
local class, name, inherit = parseTsDecl(decl)
|
local class, name, inherit = parseTsDecl(decl)
|
||||||
if not name then error('bl.datablock: must specify a name', 2) end
|
if not name then error('bl.datablock: must specify a name', 2) end
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
-- This Lua code provides some built-in utilities for writing Lua add-ons
|
-- This Lua code provides some built-in utilities for writing Lua add-ons
|
||||||
-- It is eval'd automatically once BLLua3 has loaded the TS API and environment
|
-- It is eval'd automatically once BLLua3 has loaded the TS API and environment
|
||||||
-- It only has access to the sandboxed lua environment, just like user code.
|
-- It only has access to the sandboxed lua environment, just like user code.
|
||||||
@@ -7,7 +6,10 @@ ts = _bllua_ts
|
|||||||
|
|
||||||
-- Provide limited OS functions
|
-- Provide limited OS functions
|
||||||
os = os or {}
|
os = os or {}
|
||||||
|
---@diagnostic disable-next-line: duplicate-set-field
|
||||||
function os.time() return math.floor(tonumber(_bllua_ts.call('getSimTime')) / 1000) end
|
function os.time() return math.floor(tonumber(_bllua_ts.call('getSimTime')) / 1000) end
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: duplicate-set-field
|
||||||
function os.clock() return tonumber(_bllua_ts.call('getSimTime')) / 1000 end
|
function os.clock() return tonumber(_bllua_ts.call('getSimTime')) / 1000 end
|
||||||
|
|
||||||
-- Virtual file class, emulating a file object as returned by io.open
|
-- Virtual file class, emulating a file object as returned by io.open
|
||||||
@@ -82,15 +84,20 @@ local function new_file_obj(fn)
|
|||||||
return file
|
return file
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tflip(t) local u = {}; for _, n in ipairs(t) do u[n] = true end; return u; end
|
local function tflip(t)
|
||||||
|
local u = {}; for _, n in ipairs(t) do u[n] = true end; return u;
|
||||||
|
end
|
||||||
local allowed_zip_dirs = tflip {
|
local allowed_zip_dirs = tflip {
|
||||||
'add-ons', 'base', 'config', 'saves', 'screenshots', 'shaders'
|
'add-ons', 'base', 'config', 'saves', 'screenshots', 'shaders'
|
||||||
}
|
}
|
||||||
local function io_open_absolute(fn, mode)
|
local function io_open_absolute(fn, mode)
|
||||||
-- if file exists, use original mode
|
-- if file exists, use original mode
|
||||||
local res, err = _bllua_io_open(fn, mode)
|
local res, err = _bllua_io_open(fn, mode)
|
||||||
if res then return res
|
if res then
|
||||||
elseif err and not err:find('No such file or directory$') then return nil, err end
|
return res
|
||||||
|
elseif err and not err:find('No such file or directory$') then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
-- otherwise, if TS sees file but Lua doesn't, it must be in a zip, so use TS reader
|
-- otherwise, if TS sees file but Lua doesn't, it must be in a zip, so use TS reader
|
||||||
local dir = fn:match('^[^/]+')
|
local dir = fn:match('^[^/]+')
|
||||||
@@ -99,7 +106,8 @@ local function io_open_absolute(fn, mode)
|
|||||||
if not exist then return nil, err end
|
if not exist then return nil, err end
|
||||||
|
|
||||||
if mode ~= nil and mode ~= 'r' and mode ~= 'rb' then
|
if mode ~= nil and mode ~= 'r' and mode ~= 'rb' then
|
||||||
return nil, 'Files in zips can only be opened in read mode' end
|
return nil, 'Files in zips can only be opened in read mode'
|
||||||
|
end
|
||||||
|
|
||||||
-- return a temp lua file object with the data
|
-- return a temp lua file object with the data
|
||||||
local fi = new_file_obj(fn)
|
local fi = new_file_obj(fn)
|
||||||
@@ -107,6 +115,7 @@ local function io_open_absolute(fn, mode)
|
|||||||
end
|
end
|
||||||
|
|
||||||
io = io or {}
|
io = io or {}
|
||||||
|
---@diagnostic disable-next-line: duplicate-set-field
|
||||||
function io.open(fn, mode, errn)
|
function io.open(fn, mode, errn)
|
||||||
errn = errn or 1
|
errn = errn or 1
|
||||||
|
|
||||||
@@ -127,13 +136,19 @@ function io.open(fn, mode, errn)
|
|||||||
return fi, err, fn
|
return fi, err, fn
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: duplicate-set-field
|
||||||
function io.lines(fn)
|
function io.lines(fn)
|
||||||
local fi, err, fn2 = io.open(fn, nil, 2)
|
local fi, err, fn2 = io.open(fn, nil, 2)
|
||||||
if not fi then error('Error opening file \'' .. fn2 .. '\': ' .. 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
|
||||||
function io.type(f)
|
function io.type(f)
|
||||||
|
---@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
|
||||||
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)
|
||||||
@@ -199,7 +214,8 @@ local function isValidCode(code)
|
|||||||
end
|
end
|
||||||
function _bllua_smarteval(code)
|
function _bllua_smarteval(code)
|
||||||
if (not code:find('^print%(')) and isValidCode('print(' .. code .. ')') then
|
if (not code:find('^print%(')) and isValidCode('print(' .. code .. ')') then
|
||||||
code = 'print('..code..')' end
|
code = 'print(' .. code .. ')'
|
||||||
|
end
|
||||||
local f, e = loadstring(code)
|
local f, e = loadstring(code)
|
||||||
if f then
|
if f then
|
||||||
return f()
|
return f()
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
-- todo
|
-- todo
|
||||||
-- Matrix class with math operators
|
-- Matrix class with math operators
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
-- Basic functionality that should be standard in Lua
|
-- Basic functionality that should be standard in Lua
|
||||||
|
|
||||||
|
|
||||||
@@ -7,6 +6,7 @@
|
|||||||
function table.empty(t)
|
function table.empty(t)
|
||||||
return next(t) == nil
|
return next(t) == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Apply a function to each key in a table
|
-- Apply a function to each key in a table
|
||||||
function table.map(f, ...)
|
function table.map(f, ...)
|
||||||
local ts = { ... }
|
local ts = { ... }
|
||||||
@@ -18,6 +18,7 @@ function table.map(f, ...)
|
|||||||
end
|
end
|
||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.mapk(f, ...)
|
function table.mapk(f, ...)
|
||||||
local ts = { ... }
|
local ts = { ... }
|
||||||
local u = {}
|
local u = {}
|
||||||
@@ -28,6 +29,7 @@ function table.mapk(f, ...)
|
|||||||
end
|
end
|
||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.map_list(f, ...)
|
function table.map_list(f, ...)
|
||||||
local ts = { ... }
|
local ts = { ... }
|
||||||
local u = {}
|
local u = {}
|
||||||
@@ -38,6 +40,7 @@ function table.map_list(f, ...)
|
|||||||
end
|
end
|
||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.mapi_list(f, ...)
|
function table.mapi_list(f, ...)
|
||||||
local ts = { ... }
|
local ts = { ... }
|
||||||
local u = {}
|
local u = {}
|
||||||
@@ -48,18 +51,21 @@ function table.mapi_list(f, ...)
|
|||||||
end
|
end
|
||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Swap keys/values
|
-- Swap keys/values
|
||||||
function table.swap(t)
|
function table.swap(t)
|
||||||
local u = {}
|
local u = {}
|
||||||
for k, v in pairs(t) do u[v] = k end
|
for k, v in pairs(t) do u[v] = k end
|
||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reverse a list
|
-- Reverse a list
|
||||||
function table.reverse(l)
|
function table.reverse(l)
|
||||||
local m = {}
|
local m = {}
|
||||||
for i = 1, #l do m[#l - i + 1] = l[i] end
|
for i = 1, #l do m[#l - i + 1] = l[i] end
|
||||||
return m
|
return m
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Whether a table is a list/array (has only monotonic integer keys)
|
-- Whether a table is a list/array (has only monotonic integer keys)
|
||||||
function table.islist(t)
|
function table.islist(t)
|
||||||
local n = 0
|
local n = 0
|
||||||
@@ -69,6 +75,7 @@ function table.islist(t)
|
|||||||
end
|
end
|
||||||
return n == #t
|
return n == #t
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Append contents of other tables to first table
|
-- Append contents of other tables to first table
|
||||||
function table.append(t, ...)
|
function table.append(t, ...)
|
||||||
local a = { ... }
|
local a = { ... }
|
||||||
@@ -77,6 +84,7 @@ function table.append(t, ...)
|
|||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create a new table containing all keys from any number of tables
|
-- Create a new table containing all keys from any number of tables
|
||||||
-- latter tables in the arg list override prior ones
|
-- latter tables in the arg list override prior ones
|
||||||
-- overlaps, NOT appends, integer keys
|
-- overlaps, NOT appends, integer keys
|
||||||
@@ -88,6 +96,7 @@ function table.join(...)
|
|||||||
end
|
end
|
||||||
return w
|
return w
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Whether a table contains a certain value in any key
|
-- Whether a table contains a certain value in any key
|
||||||
function table.contains(t, s)
|
function table.contains(t, s)
|
||||||
for _, v in pairs(t) do
|
for _, v in pairs(t) do
|
||||||
@@ -95,29 +104,34 @@ function table.contains(t,s)
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.contains_list(t, s)
|
function table.contains_list(t, s)
|
||||||
for _, v in ipairs(t) do
|
for _, v in ipairs(t) do
|
||||||
if v == s then return true end
|
if v == s then return true end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Copy a table to another table
|
-- Copy a table to another table
|
||||||
function table.copy(t)
|
function table.copy(t)
|
||||||
local u = {}
|
local u = {}
|
||||||
for k, v in pairs(t) do u[k] = v end
|
for k, v in pairs(t) do u[k] = v end
|
||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.copy_list(l)
|
function table.copy_list(l)
|
||||||
local m = {}
|
local m = {}
|
||||||
for i, v in ipairs(l) do m[i] = v end
|
for i, v in ipairs(l) do m[i] = v end
|
||||||
return m
|
return m
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sort a table in a new copy
|
-- Sort a table in a new copy
|
||||||
function table.sortcopy(t, f)
|
function table.sortcopy(t, f)
|
||||||
local u = table.copy_list(t)
|
local u = table.copy_list(t)
|
||||||
table.sort(u, f)
|
table.sort(u, f)
|
||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove a value from a table
|
-- Remove a value from a table
|
||||||
function table.removevalue(t, r)
|
function table.removevalue(t, r)
|
||||||
local rem = {}
|
local rem = {}
|
||||||
@@ -126,6 +140,7 @@ function table.removevalue(t, r)
|
|||||||
end
|
end
|
||||||
for _, k in ipairs(rem) do t[k] = nil end
|
for _, k in ipairs(rem) do t[k] = nil end
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.removevalue_list(t, r)
|
function table.removevalue_list(t, r)
|
||||||
for i = #t, 1, -1 do
|
for i = #t, 1, -1 do
|
||||||
if t[i] == r then
|
if t[i] == r then
|
||||||
@@ -133,6 +148,7 @@ function table.removevalue_list(t, r)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Export tables into formatted executable strings
|
-- Export tables into formatted executable strings
|
||||||
local function tabs(tabLevel)
|
local function tabs(tabLevel)
|
||||||
return (' '):rep(tabLevel)
|
return (' '):rep(tabLevel)
|
||||||
@@ -206,7 +222,6 @@ function table.tostring(t)
|
|||||||
return tableToString(t, 0, {})
|
return tableToString(t, 0, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- String
|
-- String
|
||||||
|
|
||||||
-- Split string into table by separator
|
-- Split string into table by separator
|
||||||
@@ -214,7 +229,8 @@ end
|
|||||||
-- if regex is not true, sep is treated as a regex pattern
|
-- if regex is not true, sep is treated as a regex pattern
|
||||||
function string.split(str, sep, noregex)
|
function string.split(str, sep, noregex)
|
||||||
if type(str) ~= 'string' then
|
if type(str) ~= 'string' then
|
||||||
error('string.split: argument #1: expected string, got '..type(str), 2) end
|
error('string.split: argument #1: expected string, got ' .. type(str), 2)
|
||||||
|
end
|
||||||
if sep == nil or sep == '' then
|
if sep == nil or sep == '' then
|
||||||
local t = {}
|
local t = {}
|
||||||
local ns = #str
|
local ns = #str
|
||||||
@@ -240,6 +256,7 @@ function string.split(str, sep, noregex)
|
|||||||
'string.split: argument #2: expected string or nil, got ' .. type(sep), 2)
|
'string.split: argument #2: expected string or nil, got ' .. type(sep), 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Split string to a list of char bytes
|
-- Split string to a list of char bytes
|
||||||
function string.bytes(s)
|
function string.bytes(s)
|
||||||
local b = {}
|
local b = {}
|
||||||
@@ -249,11 +266,13 @@ function string.bytes(s)
|
|||||||
end
|
end
|
||||||
return b
|
return b
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Trim leading and trailing whitespace
|
-- Trim leading and trailing whitespace
|
||||||
function string.trim(s, ws)
|
function string.trim(s, ws)
|
||||||
ws = ws or ' \t\r\n'
|
ws = ws or ' \t\r\n'
|
||||||
return s:gsub('^[' .. ws .. ']+', ''):gsub('[' .. ws .. ']+$', '') .. ''
|
return s:gsub('^[' .. ws .. ']+', ''):gsub('[' .. ws .. ']+$', '') .. ''
|
||||||
end
|
end
|
||||||
|
|
||||||
-- String slicing and searching using [] operator
|
-- String slicing and searching using [] operator
|
||||||
local str_meta = getmetatable('')
|
local str_meta = getmetatable('')
|
||||||
local str_meta_index_old = str_meta.__index
|
local str_meta_index_old = str_meta.__index
|
||||||
@@ -269,15 +288,20 @@ function str_meta.__index(s,k)
|
|||||||
return string.sub(s, a, b)
|
return string.sub(s, a, b)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- String iterator
|
-- String iterator
|
||||||
function string.chars(s)
|
function string.chars(s)
|
||||||
local i = 0
|
local i = 0
|
||||||
return function()
|
return function()
|
||||||
i = i + 1
|
i = i + 1
|
||||||
if i<=#s then return s:sub(i,i)
|
if i <= #s then
|
||||||
else return nil end
|
return s:sub(i, i)
|
||||||
|
else
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Escape sequences
|
-- Escape sequences
|
||||||
local defaultEscapes = {
|
local defaultEscapes = {
|
||||||
['\\'] = '\\\\',
|
['\\'] = '\\\\',
|
||||||
@@ -297,6 +321,7 @@ function string.escape(s, escapes)
|
|||||||
end
|
end
|
||||||
return table.concat(t)
|
return table.concat(t)
|
||||||
end
|
end
|
||||||
|
|
||||||
local defaultEscapeChar = '\\'
|
local defaultEscapeChar = '\\'
|
||||||
local defaultUnescapes = {
|
local defaultUnescapes = {
|
||||||
['\\'] = '\\',
|
['\\'] = '\\',
|
||||||
@@ -327,7 +352,6 @@ function string.unescape(s, escapeChar, unescapes)
|
|||||||
return table.concat(t)
|
return table.concat(t)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- IO
|
-- IO
|
||||||
|
|
||||||
io = io or {}
|
io = io or {}
|
||||||
@@ -339,6 +363,7 @@ function io.readall(filename)
|
|||||||
fi:close()
|
fi:close()
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Write data to file all at once, return true if success / false,err if failure
|
-- Write data to file all at once, return true if success / false,err if failure
|
||||||
function io.writeall(filename, data)
|
function io.writeall(filename, data)
|
||||||
local fi, err = io.open(filename, 'wb')
|
local fi, err = io.open(filename, 'wb')
|
||||||
@@ -348,23 +373,26 @@ function io.writeall(filename, data)
|
|||||||
return true, nil
|
return true, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Math
|
-- Math
|
||||||
|
|
||||||
-- Round
|
-- Round
|
||||||
function math.round(x)
|
function math.round(x)
|
||||||
return math.floor(x + 0.5)
|
return math.floor(x + 0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mod that accounts for floating point inaccuracy
|
-- Mod that accounts for floating point inaccuracy
|
||||||
function math.mod(a, b)
|
function math.mod(a, b)
|
||||||
local m = a % b
|
local m = a % b
|
||||||
if m==0 or math.abs(m)<1e-15 or math.abs(m-b)<1e-15 then return 0
|
if m == 0 or math.abs(m) < 1e-15 or math.abs(m - b) < 1e-15 then
|
||||||
else return m end
|
return 0
|
||||||
|
else
|
||||||
|
return m
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Clamp value between min and max
|
-- Clamp value between min and max
|
||||||
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')
|
print(' Executed std.lua')
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
|
|
||||||
-- Vector math class with operators
|
-- Vector math class with operators
|
||||||
local vector_meta
|
local vector_meta
|
||||||
local vector_new
|
local vector_new
|
||||||
local function vector_check(v, n, name, argn)
|
local function vector_check(v, n, name, argn)
|
||||||
if not v.__is_vector then
|
if not v.__is_vector then
|
||||||
error('vector ' .. name .. ': argument #' .. (argn or 1)
|
error('vector ' .. name .. ': argument #' .. (argn or 1)
|
||||||
..': expected vector, got '..type(v), n+1) end
|
.. ': expected vector, got ' .. type(v), n + 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local function vector_checksamelen(v1, v2, name)
|
local function vector_checksamelen(v1, v2, name)
|
||||||
vector_check(v1, 3, name, 1)
|
vector_check(v1, 3, name, 1)
|
||||||
vector_check(v2, 3, name, 2)
|
vector_check(v2, 3, name, 2)
|
||||||
if #v1 ~= #v2 then
|
if #v1 ~= #v2 then
|
||||||
error('vector ' .. name .. ': vector lengths do not match (lengths are '
|
error('vector ' .. name .. ': vector lengths do not match (lengths are '
|
||||||
..#v1..' and '..#v2..')', 3) end
|
.. #v1 .. ' and ' .. #v2 .. ')', 3)
|
||||||
|
end
|
||||||
return #v1
|
return #v1
|
||||||
end
|
end
|
||||||
local function vector_checklen(v1, v2, name, len)
|
local function vector_checklen(v1, v2, name, len)
|
||||||
@@ -20,7 +21,8 @@ local function vector_checklen(v1, v2, name, len)
|
|||||||
vector_check(v2, 3, name, 2)
|
vector_check(v2, 3, name, 2)
|
||||||
if #v1 ~= len or #v2 ~= len then
|
if #v1 ~= len or #v2 ~= len then
|
||||||
error('vector ' .. name .. ': vector lengths are not ' .. len .. ' (lengths are '
|
error('vector ' .. name .. ': vector lengths are not ' .. len .. ' (lengths are '
|
||||||
..#v1..' and '..#v2..')', 3) end
|
.. #v1 .. ' and ' .. #v2 .. ')', 3)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local function vector_opnnn(name, op)
|
local function vector_opnnn(name, op)
|
||||||
return function(v1, v2)
|
return function(v1, v2)
|
||||||
@@ -69,15 +71,21 @@ local vector_indices = {x = 1, y = 2, z = 3, w = 4, r = 1, g = 2, b = 3, a = 4}
|
|||||||
local vector_meta = {
|
local vector_meta = {
|
||||||
__is_vector = true,
|
__is_vector = true,
|
||||||
__index = function(t, k)
|
__index = function(t, k)
|
||||||
if tonumber(k) then return rawget(t, k)
|
if tonumber(k) then
|
||||||
elseif vector_indices[k] then return rawget(t, vector_indices[k])
|
return rawget(t, k)
|
||||||
else return getmetatable(t)[k]
|
elseif vector_indices[k] then
|
||||||
|
return rawget(t, vector_indices[k])
|
||||||
|
else
|
||||||
|
return getmetatable(t)[k]
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
__newindex = function(t, k, v)
|
__newindex = function(t, k, v)
|
||||||
if tonumber(k) then rawset(t, k, v)
|
if tonumber(k) then
|
||||||
elseif vector_indices[k] then rawset(t, vector_indices[k], v)
|
rawset(t, k, v)
|
||||||
else return
|
elseif vector_indices[k] then
|
||||||
|
rawset(t, vector_indices[k], v)
|
||||||
|
else
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
__add = vector_opnnn('add', function(x1, x2) return x1 + x2 end),
|
__add = vector_opnnn('add', function(x1, x2) return x1 + x2 end),
|
||||||
@@ -115,8 +123,11 @@ local vector_meta = {
|
|||||||
local len = #v1
|
local len = #v1
|
||||||
local v3 = {}
|
local v3 = {}
|
||||||
for i = 1, len do
|
for i = 1, len do
|
||||||
if length==0 then v3[i] = 0
|
if length == 0 then
|
||||||
else v3[i] = v1[i]/length end
|
v3[i] = 0
|
||||||
|
else
|
||||||
|
v3[i] = v1[i] / length
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return vector_new(v3)
|
return vector_new(v3)
|
||||||
end,
|
end,
|
||||||
@@ -152,20 +163,28 @@ local vector_meta = {
|
|||||||
rotateByAngleId = function(v1, r)
|
rotateByAngleId = function(v1, r)
|
||||||
--vector_check(v1, 2, 'rotate')
|
--vector_check(v1, 2, 'rotate')
|
||||||
if type(r) ~= 'number' or r % 1 ~= 0 then
|
if type(r) ~= 'number' or r % 1 ~= 0 then
|
||||||
error('vector rotateByAngleId: invalid rotation '..tostring(r), 2) end
|
error('vector rotateByAngleId: invalid rotation ' .. tostring(r), 2)
|
||||||
|
end
|
||||||
r = r % 4
|
r = r % 4
|
||||||
local v2
|
local v2
|
||||||
if r==0 then v2 = vector_new{ v1[1], v1[2], v1[3] }
|
if r == 0 then
|
||||||
elseif r==1 then v2 = vector_new{ v1[2], -v1[1], v1[3] }
|
v2 = vector_new { v1[1], v1[2], v1[3] }
|
||||||
elseif r==2 then v2 = vector_new{ -v1[1], -v1[2], v1[3] }
|
elseif r == 1 then
|
||||||
elseif r==3 then v2 = vector_new{ -v1[2], v1[1], v1[3] }
|
v2 = vector_new { v1[2], -v1[1], v1[3] }
|
||||||
else error('vector rotateByAngleId: invalid rotation '..r, 2) end
|
elseif r == 2 then
|
||||||
|
v2 = vector_new { -v1[1], -v1[2], v1[3] }
|
||||||
|
elseif r == 3 then
|
||||||
|
v2 = vector_new { -v1[2], v1[1], v1[3] }
|
||||||
|
else
|
||||||
|
error('vector rotateByAngleId: invalid rotation ' .. r, 2)
|
||||||
|
end
|
||||||
return v2
|
return v2
|
||||||
end,
|
end,
|
||||||
rotateZ = function(v, r)
|
rotateZ = function(v, r)
|
||||||
--vector_check(v, 2, 'rotate2d')
|
--vector_check(v, 2, 'rotate2d')
|
||||||
if type(r) ~= 'number' then
|
if type(r) ~= 'number' then
|
||||||
error('vector rotateZ: invalid rotation '..tostring(r), 2) end
|
error('vector rotateZ: invalid rotation ' .. tostring(r), 2)
|
||||||
|
end
|
||||||
local len = math.sqrt(v[1] ^ 2 + v[2] ^ 2)
|
local len = math.sqrt(v[1] ^ 2 + v[2] ^ 2)
|
||||||
local ang = math.atan2(v[2], v[1]) + r
|
local ang = math.atan2(v[2], v[1]) + r
|
||||||
local v2 = vector_new { math.cos(ang) * len, math.sin(ang) * len }
|
local v2 = vector_new { math.cos(ang) * len, math.sin(ang) * len }
|
||||||
|
|||||||
Reference in New Issue
Block a user