commit 36ba54b24832cedbef570bf86b0079c8f1ce35dc Author: Redo Date: Wed Oct 1 16:26:18 2025 -0700 initial diff --git a/.compileInject.bat b/.compileInject.bat new file mode 100644 index 0000000..5dcc05e --- /dev/null +++ b/.compileInject.bat @@ -0,0 +1,15 @@ +@for /F "tokens=2" %%K in (' + tasklist /FI "ImageName eq Blockland.exe" /FO LIST ^| findstr /B "PID:" +') do ( + DllRemover32 %%K BlockLua.dll +) + +@call %~dp0compile.bat || exit + +@for /F "tokens=2" %%K in (' + tasklist /FI "ImageName eq Blockland.exe" /FO LIST ^| findstr /B "PID:" +') do ( + RemoteDllInjector32 %%K %~dp0BlockLua.dll +) + +@pause diff --git a/BlockLua-Unsafe.dll b/BlockLua-Unsafe.dll new file mode 100644 index 0000000..0062c02 Binary files /dev/null and b/BlockLua-Unsafe.dll differ diff --git a/BlockLua.dll b/BlockLua.dll new file mode 100644 index 0000000..e991cb1 Binary files /dev/null and b/BlockLua.dll differ diff --git a/compile.bat b/compile.bat new file mode 100644 index 0000000..343a7c5 --- /dev/null +++ b/compile.bat @@ -0,0 +1,13 @@ +@echo off +cd /d %~dp0 + +set buildargs=-Wall -Werror -m32 -shared -Isrc -Iinc/tsfuncs -Iinc/lua -lpsapi -L. -llua5.1 -static-libgcc -static-libstdc++ + +echo on +g++ src/bllua4.cpp %buildargs% -o BlockLua.dll && g++ -DBLLUA_UNSAFE src/bllua4.cpp %buildargs% -o BlockLua-Unsafe.dll +@echo off + +rem objdump -d BlockLua.dll > BlockLua.dll.dump.txt +rem objdump -d BlockLua-Unsafe.dll > BlockLua-Unsafe.dll.dump.txt + +pause diff --git a/inc/lua/lauxlib.h b/inc/lua/lauxlib.h new file mode 100644 index 0000000..a44f027 --- /dev/null +++ b/inc/lua/lauxlib.h @@ -0,0 +1,161 @@ +/* +** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +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_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_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + 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_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_optinteger) (lua_State *L, int nArg, + lua_Integer def); + +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_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +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 int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +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_loadbuffer) (lua_State *L, const char *buff, size_t sz, + const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +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_findtable) (lua_State *L, int idx, + const char *fname, int szhint); + +/* From Lua 5.2. */ +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_loadfilex) (lua_State *L, const char *filename, + 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 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_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), 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_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#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))) + +/* From Lua 5.2. */ +#define luaL_newlibtable(L, l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) +#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0)) + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); + + +/* }====================================================== */ + +#endif diff --git a/inc/lua/lua.h b/inc/lua/lua.h new file mode 100644 index 0000000..850bd79 --- /dev/null +++ b/inc/lua/lua.h @@ -0,0 +1,402 @@ +/* +** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.4" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +/* mark for precompiled code (`Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +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); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (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); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +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_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +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_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getfenv) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +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_setfenv) (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +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_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_strlen(L,i) lua_objlen(L, (i)) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_setglobal(L,s) lua_setfield(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) + + + +/* +** compatibility macros and functions +*/ + +#define lua_open() luaL_newstate() + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) + +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) + +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer + + +/* hack */ +LUA_API void lua_setlevel (lua_State *from, lua_State *to); + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +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_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_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + +/* From Lua 5.2. */ +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 int lua_loadx (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); +LUA_API const lua_Number *lua_version (lua_State *L); +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_Integer lua_tointegerx (lua_State *L, int idx, int *isnum); + +/* From Lua 5.3. */ +LUA_API int lua_isyieldable (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/inc/lua/lua.hpp b/inc/lua/lua.hpp new file mode 100644 index 0000000..07e9002 --- /dev/null +++ b/inc/lua/lua.hpp @@ -0,0 +1,9 @@ +// C++ wrapper for LuaJIT header files. + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "luajit.h" +} + diff --git a/inc/lua/lua5.1.lib b/inc/lua/lua5.1.lib new file mode 100644 index 0000000..1b8d57c Binary files /dev/null and b/inc/lua/lua5.1.lib differ diff --git a/inc/lua/luaconf.h b/inc/lua/luaconf.h new file mode 100644 index 0000000..c2d29d9 --- /dev/null +++ b/inc/lua/luaconf.h @@ -0,0 +1,152 @@ +/* +** Configuration header. +** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h +*/ + +#ifndef luaconf_h +#define luaconf_h + +#ifndef WINVER +#define WINVER 0x0501 +#endif +#include +#include + +/* Default path for loading Lua and C modules with require(). */ +#if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" +#else +/* +** Note to distribution maintainers: do NOT patch the following lines! +** Please read ../doc/install.html#distro and pass PREFIX=/usr instead. +*/ +#ifndef LUA_MULTILIB +#define LUA_MULTILIB "lib" +#endif +#ifndef LUA_LMULTILIB +#define LUA_LMULTILIB "lib" +#endif +#define LUA_LROOT "/usr/local" +#define LUA_LUADIR "/lua/5.1/" +#define LUA_LJDIR "/luajit-2.1.0-beta3/" + +#ifdef LUA_ROOT +#define LUA_JROOT LUA_ROOT +#define LUA_RLDIR LUA_ROOT "/share" LUA_LUADIR +#define LUA_RCDIR LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR +#define LUA_RLPATH ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua" +#define LUA_RCPATH ";" LUA_RCDIR "?.so" +#else +#define LUA_JROOT LUA_LROOT +#define LUA_RLPATH +#define LUA_RCPATH +#endif + +#define LUA_JPATH ";" LUA_JROOT "/share" LUA_LJDIR "?.lua" +#define LUA_LLDIR LUA_LROOT "/share" LUA_LUADIR +#define LUA_LCDIR LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR +#define LUA_LLPATH ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua" +#define LUA_LCPATH1 ";" LUA_LCDIR "?.so" +#define LUA_LCPATH2 ";" LUA_LCDIR "loadall.so" + +#define LUA_PATH_DEFAULT "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH +#define LUA_CPATH_DEFAULT "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2 +#endif + +/* Environment variable names for path overrides and initialization code. */ +#define LUA_PATH "LUA_PATH" +#define LUA_CPATH "LUA_CPATH" +#define LUA_INIT "LUA_INIT" + +/* Special file system characters. */ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" +#define LUA_PATH_CONFIG \ + LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \ + LUA_EXECDIR "\n" LUA_IGMARK "\n" + +/* Quoting in error messages. */ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + +/* Various tunables. */ +#define LUAI_MAXSTACK 65500 /* Max. # of stack slots for a thread (<64K). */ +#define LUAI_MAXCSTACK 8000 /* Max. # of stack slots for a C func (<10K). */ +#define LUAI_GCPAUSE 200 /* Pause GC until memory is at 200%. */ +#define LUAI_GCMUL 200 /* Run GC at 200% of allocation speed. */ +#define LUA_MAXCAPTURES 32 /* Max. pattern captures. */ + +/* Configuration for the frontend (the luajit executable). */ +#if defined(luajit_c) +#define LUA_PROGNAME "luajit" /* Fallback frontend name. */ +#define LUA_PROMPT "> " /* Interactive prompt. */ +#define LUA_PROMPT2 ">> " /* Continuation prompt. */ +#define LUA_MAXINPUT 512 /* Max. input line length. */ +#endif + +/* Note: changing the following defines breaks the Lua 5.1 ABI. */ +#define LUA_INTEGER ptrdiff_t +#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */ +/* +** Size of lauxlib and io.* on-stack buffers. Weird workaround to avoid using +** unreasonable amounts of stack space, but still retain ABI compatibility. +** Blame Lua for depending on BUFSIZ in the ABI, blame **** for wrecking it. +*/ +#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ) + +/* The following defines are here only for compatibility with luaconf.h +** from the standard Lua distribution. They must not be changed for LuaJIT. +*/ +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double +#define LUAI_UACNUMBER double +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +/* Linkage of public API functions. */ +#if defined(LUA_BUILD_AS_DLL) +#if defined(LUA_CORE) || defined(LUA_LIB) +#define LUA_API __declspec(dllexport) +#else +#define LUA_API __declspec(dllimport) +#endif +#else +#define LUA_API extern +#endif + +#define LUALIB_API LUA_API + +/* Support for internal assertions. */ +#if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK) +#include +#endif +#ifdef LUA_USE_ASSERT +#define lua_assert(x) assert(x) +#endif +#ifdef LUA_USE_APICHECK +#define luai_apicheck(L, o) { (void)L; assert(o); } +#else +#define luai_apicheck(L, o) { (void)L; } +#endif + +#endif diff --git a/inc/lua/luajit.h b/inc/lua/luajit.h new file mode 100644 index 0000000..708a5a1 --- /dev/null +++ b/inc/lua/luajit.h @@ -0,0 +1,79 @@ +/* +** LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/ +** +** Copyright (C) 2005-2017 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#ifndef _LUAJIT_H +#define _LUAJIT_H + +#include "lua.h" + +#define LUAJIT_VERSION "LuaJIT 2.1.0-beta3" +#define LUAJIT_VERSION_NUM 20100 /* Version 2.1.0 = 02.01.00. */ +#define LUAJIT_VERSION_SYM luaJIT_version_2_1_0_beta3 +#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2017 Mike Pall" +#define LUAJIT_URL "http://luajit.org/" + +/* Modes for luaJIT_setmode. */ +#define LUAJIT_MODE_MASK 0x00ff + +enum { + LUAJIT_MODE_ENGINE, /* Set mode for whole JIT engine. */ + LUAJIT_MODE_DEBUG, /* Set debug mode (idx = level). */ + + LUAJIT_MODE_FUNC, /* Change mode for a function. */ + LUAJIT_MODE_ALLFUNC, /* Recurse into subroutine protos. */ + LUAJIT_MODE_ALLSUBFUNC, /* Change only the subroutines. */ + + LUAJIT_MODE_TRACE, /* Flush a compiled trace. */ + + LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */ + + LUAJIT_MODE_MAX +}; + +/* Flags or'ed in to the mode. */ +#define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */ +#define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */ +#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */ + +/* LuaJIT public C API. */ + +/* Control the JIT engine. */ +LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode); + +/* Low-overhead profiling API. */ +typedef void (*luaJIT_profile_callback)(void *data, lua_State *L, + 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_stop(lua_State *L); +LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt, + int depth, size_t *len); + +/* Enforce (dynamic) linker error for version mismatches. Call from main. */ +LUA_API void LUAJIT_VERSION_SYM(void); + +#endif diff --git a/inc/lua/lualib.h b/inc/lua/lualib.h new file mode 100644 index 0000000..bfc130a --- /dev/null +++ b/inc/lua/lualib.h @@ -0,0 +1,43 @@ +/* +** Standard library header. +** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h +*/ + +#ifndef _LUALIB_H +#define _LUALIB_H + +#include "lua.h" + +#define LUA_FILEHANDLE "FILE*" + +#define LUA_COLIBNAME "coroutine" +#define LUA_MATHLIBNAME "math" +#define LUA_STRLIBNAME "string" +#define LUA_TABLIBNAME "table" +#define LUA_IOLIBNAME "io" +#define LUA_OSLIBNAME "os" +#define LUA_LOADLIBNAME "package" +#define LUA_DBLIBNAME "debug" +#define LUA_BITLIBNAME "bit" +#define LUA_JITLIBNAME "jit" +#define LUA_FFILIBNAME "ffi" + +LUALIB_API int luaopen_base(lua_State *L); +LUALIB_API int luaopen_math(lua_State *L); +LUALIB_API int luaopen_string(lua_State *L); +LUALIB_API int luaopen_table(lua_State *L); +LUALIB_API int luaopen_io(lua_State *L); +LUALIB_API int luaopen_os(lua_State *L); +LUALIB_API int luaopen_package(lua_State *L); +LUALIB_API int luaopen_debug(lua_State *L); +LUALIB_API int luaopen_bit(lua_State *L); +LUALIB_API int luaopen_jit(lua_State *L); +LUALIB_API int luaopen_ffi(lua_State *L); + +LUALIB_API void luaL_openlibs(lua_State *L); + +#ifndef lua_assert +#define lua_assert(x) ((void)0) +#endif + +#endif diff --git a/inc/tsfuncs/BlFuncs.cpp b/inc/tsfuncs/BlFuncs.cpp new file mode 100644 index 0000000..68b789d --- /dev/null +++ b/inc/tsfuncs/BlFuncs.cpp @@ -0,0 +1,238 @@ + +////////////////////////////////////////////////// +// BlFuncs Version 1.0 + + +// Includes + +#include "BlHooks.hpp" +#include "BlFuncs.hpp" + +#include + + +// Scanned structures + +ADDR tsf_mCacheSequence; +ADDR tsf_mCacheAllocator; +ADDR tsf_gIdDictionary; +ADDR tsf_gEvalState_globalVars; + +BlFunctionDefIntern(tsf_BlStringTable__insert ); +BlFunctionDefIntern(tsf_BlNamespace__find ); +BlFunctionDefIntern(tsf_BlNamespace__createLocalEntry); +BlFunctionDefIntern(tsf_BlDataChunker__freeBlocks ); +BlFunctionDefIntern(tsf_BlCon__evaluate ); +BlFunctionDefIntern(tsf_BlCon__executef ); +BlFunctionDefIntern(tsf_BlCon__executefSimObj ); +BlFunctionDefIntern(tsf_BlCon__getVariable ); +BlFunctionDefIntern(tsf_BlDictionary__addVariable ); +BlFunctionDefIntern(tsf_BlSim__findObject_name ); +BlFunctionDefIntern(tsf_BlStringStack__getArgBuffer ); +BlFunctionDefIntern(tsf_BlSimObject__getDataField ); +BlFunctionDefIntern(tsf_BlSimObject__setDataField ); +BlFunctionDefIntern(tsf_BlCon__getReturnBuffer ); + + +// C->TS Args + +char* tsf_GetIntArg(signed int value) { + char* ret = tsf_BlStringStack__getArgBuffer(16); + snprintf(ret, 16, "%d", value); + return ret; +} +char* tsf_GetFloatArg(float value) { + char* ret = tsf_BlStringStack__getArgBuffer(32); + snprintf(ret, 32, "%g", value); + return ret; +} +char* tsf_GetStringArg(char* value) { + int len = strlen(value)+1; + char* ret = tsf_BlStringStack__getArgBuffer(len); + memcpy(ret, value, len); + return ret; +} +char* tsf_GetThisArg(ADDR obj) { + return tsf_GetIntArg(*(signed int *)(obj + 32)); +} + + +// Eval + +const char* tsf_Eval(const char *code) { + const char *argv[] = {nullptr, code}; + return tsf_BlCon__evaluate(0, 2, argv); +} + +const char* tsf_Evalf(const char *fmt, ...) { + va_list args; + char code[4096]; + va_start(args, fmt); + vsnprintf(code, 4096, fmt, args); + va_end(args); + + return tsf_Eval((const char*)code); +} + + +// Objects + +ADDR tsf_FindObject(unsigned int id) { + ADDR obj = *(ADDR*)(*(ADDR*)(tsf_gIdDictionary) + 4*(id & 0xFFF)); + if(!obj) return 0; + + while(obj && *(unsigned int *)(obj + 32) != id) { + obj = *(ADDR*)(obj + 16); + if(!obj) return 0; + } + + return obj; +} + +ADDR tsf_FindObject(const char* name) { + return (ADDR)tsf_BlSim__findObject_name(name); +} + +ADDR tsf_LookupNamespace(const char* ns, const char* package) { + const char* ste_package; + if(package) { + ste_package = tsf_BlStringTable__insert(package, 0); + } else { + ste_package = nullptr; + } + + if(ns) { + const char* ste_namespace = tsf_BlStringTable__insert(ns, 0); + return tsf_BlNamespace__find(ste_namespace, ste_package); + } else { + return tsf_BlNamespace__find(nullptr, ste_package); + } +} +ADDR tsf_LookupNamespace(const char* ns) { + return tsf_LookupNamespace(ns, nullptr); +} + + +// Object Fields + +const char* tsf_GetDataField(ADDR simObject, const char* slotName, const char* array) { + const char *ste_slotName; + if(slotName) { + ste_slotName = tsf_BlStringTable__insert(slotName, 0); + } else { + ste_slotName = nullptr; + } + + return tsf_BlSimObject__getDataField(simObject, ste_slotName, array); +} + +void tsf_SetDataField(ADDR simObject, const char* slotName, const char* array, const char* value) { + const char* ste_slotName; + if(slotName) { + ste_slotName = tsf_BlStringTable__insert(slotName, 0); + } else { + ste_slotName = nullptr; + } + + tsf_BlSimObject__setDataField(simObject, ste_slotName, array, value); +} + + +// TS Global Variables + +const char *tsf_GetVar(const char* name) { + return tsf_BlCon__getVariable(name); +} + +void tsf_AddVarInternal(const char* name, signed int varType, void* data) { + tsf_BlDictionary__addVariable((ADDR *)tsf_gEvalState_globalVars, name, varType, data); +} + +void tsf_AddVar(const char* name, const char** 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); +} + + +// 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) { + const char *ste_fname = tsf_BlStringTable__insert(fname, 0); + ADDR ns = tsf_LookupNamespace(cname, pname); + ADDR ent = tsf_BlNamespace__createLocalEntry(ns, ste_fname); + + *(signed int *)tsf_mCacheSequence += 1; + tsf_BlDataChunker__freeBlocks(*(ADDR *)tsf_mCacheAllocator); + + *(const char**)(ent + 24) = usage ; + *(signed int* )(ent + 16) = mina ; + *(signed int* )(ent + 20) = maxa ; + *(signed int* )(ent + 12) = cbtype; + + 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) { + ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 1, usage, mina, maxa); + *(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) { + ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 2, usage, mina, maxa); + *(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) { + ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 3, usage, mina, maxa); + *(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) { + ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 4, usage, mina, maxa); + *(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) { + ADDR ent = tsf_AddConsoleFuncInternal(pname, cname, fname, 5, usage, mina, maxa); + *(tsf_BoolCallback *)(ent + 40) = bc; +} + + +// Initialization + +bool tsf_InitInternal() { + 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(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_BlDictionary__addVariable , "8B 44 24 04 56 57 8B F9" ); + 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_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_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 (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_gEvalState_globalVarsLoc , "B9 ? ? ? ? E8 ? ? ? ? 68 ? ? ? ? 6A 0A 68 ? ? ? ? B9 ? ? ? ? E8 ? ? ? ? E8 ? ? ? ?" ); + + tsf_mCacheSequence = *(ADDR*)(tsf_mCacheSequenceLoc + 2); + tsf_mCacheAllocator = *(ADDR*)(tsf_mCacheAllocatorLoc + 2); + tsf_gIdDictionary = *(ADDR*)(tsf_gIdDictionaryLoc + 2); + tsf_gEvalState_globalVars = *(ADDR*)(tsf_gEvalState_globalVarsLoc + 1); + + return true; +} + +bool tsf_DeinitInternal() { + return true; +} diff --git a/inc/tsfuncs/BlFuncs.hpp b/inc/tsfuncs/BlFuncs.hpp new file mode 100644 index 0000000..b14626d --- /dev/null +++ b/inc/tsfuncs/BlFuncs.hpp @@ -0,0 +1,109 @@ + +////////////////////////////////////////////////// +// BlFuncs Version 1.0 + +#ifndef _H_BLFUNCS +#define _H_BLFUNCS + +// Require BlHooks to be included before this header +#ifndef _H_BLHOOKS + #error "BlFuncs.hpp: You must include BlHooks.hpp first" +#else + +typedef const char * (*tsf_StringCallback)(ADDR, signed int, const char *[]); +typedef signed int (*tsf_IntCallback )(ADDR, signed int, const char *[]); +typedef float (*tsf_FloatCallback )(ADDR, signed int, const char *[]); +typedef void (*tsf_VoidCallback )(ADDR, signed int, const char *[]); +typedef bool (*tsf_BoolCallback )(ADDR, signed int, const char *[]); + +/* These functions are used for tsf_BlCon__executefSimObj. + They refer to a special buffer for the argument stack. + For tsf_BlCon__executef, you need to use your own buffers. */ +char *tsf_GetIntArg(int); +char *tsf_GetFloatArg(float); +char *tsf_ScriptThis(ADDR); + +const char *tsf_Eval(const char *); +const char *tsf_Evalf(const char *, ...); + +ADDR tsf_FindObject(unsigned int); +ADDR tsf_FindObject(const char *); + +ADDR tsf_LookupNamespace(const char *, const char *); + +const char *tsf_GetDataField(ADDR, const char *, const char *); +void tsf_SetDataField(ADDR, const char *, const char *, const char *); + +const char *tsf_GetVar(const char *); + +void tsf_AddVarInternal(const char *, signed int, void *); +void tsf_AddVar(const char *, const char **); +void tsf_AddVar(const char *, signed int *); +void tsf_AddVar(const char *, float *); +void tsf_AddVar(const char *, bool *); + +ADDR tsf_AddConsoleFuncInternal(const char *, const char *, const char *, signed int, const char *, signed int, signed int); +void tsf_AddConsoleFunc(const char *, const char *, const char *, tsf_StringCallback, const char *, signed int, signed int); +void tsf_AddConsoleFunc(const char *, const char *, const char *, tsf_IntCallback, const char *, signed int, signed int); +void tsf_AddConsoleFunc(const char *, const char *, const char *, tsf_FloatCallback, const char *, signed int, signed int); +void tsf_AddConsoleFunc(const char *, const char *, const char *, tsf_VoidCallback, const char *, signed int, signed int); +void tsf_AddConsoleFunc(const char *, const char *, const char *, tsf_BoolCallback, const char *, signed int, signed int); + +bool tsf_InitInternal(); + +extern ADDR tsf_mCacheSequence; +extern ADDR tsf_mCacheAllocator; +extern ADDR tsf_gIdDictionary; +extern ADDR tsf_gEvalState_globalVars; + +BlFunctionDefExtern(const char *, __stdcall, tsf_BlStringTable__insert, const char *, bool); +BlFunctionDefExtern(ADDR, __fastcall, tsf_BlNamespace__find, const char *, const char *); +BlFunctionDefExtern(ADDR, __thiscall, tsf_BlNamespace__createLocalEntry, ADDR, const char *); +BlFunctionDefExtern(void, __thiscall, tsf_BlDataChunker__freeBlocks, ADDR); +BlFunctionDefExtern(const char *, , tsf_BlCon__evaluate, ADDR, signed int, const char **); +BlFunctionDefExtern(const char *, , tsf_BlCon__executef, signed int, ...); +BlFunctionDefExtern(const char *, , tsf_BlCon__executefSimObj, ADDR *, signed int, ...); +BlFunctionDefExtern(const char *, __thiscall, tsf_BlCon__getVariable, const char *); +BlFunctionDefExtern(void, __thiscall, tsf_BlDictionary__addVariable, ADDR *, const char *, signed int, void *); +BlFunctionDefExtern(ADDR *, __thiscall, tsf_BlSim__findObject_name, const char *); +BlFunctionDefExtern(char *, __stdcall, tsf_BlStringStack__getArgBuffer, unsigned int); +BlFunctionDefExtern(const char *, __thiscall, tsf_BlSimObject__getDataField, ADDR, 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); + + +// Function short names + +#define BlEval tsf_Eval +#define BlEvalf tsf_Evalf + +#define BlIntArg tsf_GetIntArg +#define BlFloatArg tsf_GetFloatArg +#define BlThisArg tsf_GetThisArg +#define BlStringArg(x) tsf_GetStringArg((char*)x) +#define BlReturnBuffer tsf_BlCon__getReturnBuffer + +#define BlObject tsf_FindObject +#define BlNamespace tsf_LookupNamespace + +#define BlGetField tsf_GetDataField +#define BlSetField tsf_SetDataField + +#define BlGetVar tsf_GetVar +#define BlAddVar tsf_AddVar + +#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 __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) +#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; } + + +#endif +#endif diff --git a/inc/tsfuncs/BlHooks.cpp b/inc/tsfuncs/BlHooks.cpp new file mode 100644 index 0000000..e46a852 --- /dev/null +++ b/inc/tsfuncs/BlHooks.cpp @@ -0,0 +1,207 @@ + +////////////////////////////////////////////////// +// RedoBlHooks Version 3.0 + + +// Includes + +#include +#include +//#include + +#include "BlHooks.hpp" + + +// Scanned structures + +BlFunctionDefIntern(tsh_BlPrintf); + + +// Sig Scanning + +ADDR ImageBase; +ADDR ImageSize; + +void tsh_i_InitScanner(){ + HMODULE module = GetModuleHandle(NULL); + if(module) { + MODULEINFO info; + GetModuleInformation(GetCurrentProcess(), module, &info, sizeof(MODULEINFO)); + ImageBase = (ADDR)info.lpBaseOfDll; + ImageSize = info.SizeOfImage; + } +} + +bool tsh_i_CompareData(BYTE *data, BYTE *pattern, char* mask){ + for (; *mask; ++data, ++pattern, ++mask){ + if (*mask=='x' && *data!=*pattern) + return false; + } + return (*mask)==0; +} + +ADDR tsh_i_FindPattern(ADDR imageBase, ADDR imageSize, BYTE *pattern, char *mask){ + for (ADDR i=imageBase; i < imageBase+imageSize; i++){ + if(tsh_i_CompareData((PBYTE)i, pattern, mask)){ + return i; + } + } + return 0; +} + +// Convert a text-style pattern into code-style +void tsh_i_PatternTextToCode(char* text, char** opatt, char** omask) { + unsigned int len = strlen(text); + char* patt = (char*)malloc(len); + char* mask = (char*)malloc(len); + + int outidx = 0; + int val = 0; + bool uk = false; + for(unsigned int i=0; i='0' && c<='9'){ + val = (val<<4) + (c-'0'); + }else if(c>='A' && c<='F'){ + val = (val<<4) + (c-'A'+10); + }else if(c>='a' && c<='f'){ + val = (val<<4) + (c-'a'+10); + }else if(c==' '){ + patt[outidx] = uk ? 0 : val; + mask[outidx] = uk ? '?' : 'x'; + val = 0; + uk = false; + outidx++; + } + } + + patt[outidx] = uk ? 0 : val; + mask[outidx] = uk ? '?' : 'x'; + outidx++; + patt[outidx] = 0; + mask[outidx] = 0; + + *opatt = patt; + *omask = mask; +} + + +// Public functions for sig scanning + +// Scan using code-style pattern +ADDR tsh_ScanCode(char* pattern, char* mask) { + return tsh_i_FindPattern(ImageBase, ImageSize-strlen(mask), (BYTE*)pattern, mask); +} + +// Scan using a text-style pattern +ADDR tsh_ScanText(char* text) { + char* patt; + char* mask; + tsh_i_PatternTextToCode(text, &patt, &mask); + + ADDR res = tsh_ScanCode(patt, mask); + + free(patt); + free(mask); + + return res; +} + + +// Call Patching and Hooking + +// Remove protection from address +//std::map> tsh_DeprotectedAddresses; + +void tsh_DeprotectAddress(ADDR length, ADDR location) { + DWORD oldProtection; + VirtualProtect((void*)location, length, PAGE_EXECUTE_READWRITE, &oldProtection); + //tsh_DeprotectedAddresses[location] = {length, oldProtection}; +} + +// Patch a string of bytes by deprotecting and then overwriting +void tsh_PatchBytes(ADDR length, ADDR location, BYTE* repl) { + tsh_DeprotectAddress(length, location); + memcpy((void*)location, (void*)repl, (size_t)length); +} + +void tsh_PatchByte(ADDR location, BYTE value) { + tsh_PatchBytes(location, 1, &value); +} + +void tsh_ReplaceInt(ADDR addr, int rval) { + tsh_PatchBytes(4, addr, (BYTE*)(&rval)); +} + +int tsh_i_CallOffset(ADDR instr, ADDR func) { + return func - (instr+4); +} + +void tsh_i_ReplaceCall(ADDR instr, ADDR target) { + tsh_ReplaceInt(instr, tsh_i_CallOffset(instr, target)); +} + +void tsh_i_PatchCopy(ADDR dest, ADDR src, unsigned int len) { + for(unsigned int i=0; i bool: success +#define BlHooksInit() if(!tsh_InitInternal()) { BlPrintf("BlHooksInit failed"); return false; } +// BlHooksDeinit() -> bool: success +#define BlHooksDeinit() if(!tsh_DeinitInternal()) { BlPrintf("BlHooksDeinit failed"); return false; } + + +// Scanned structures + +BlFunctionDefExtern(void, , tsh_BlPrintf, const char*, ...); + + +#endif diff --git a/lua5.1.dll b/lua5.1.dll new file mode 100644 index 0000000..752c9c1 Binary files /dev/null and b/lua5.1.dll differ diff --git a/lualib/https.dll b/lualib/https.dll new file mode 100644 index 0000000..af815bb Binary files /dev/null and b/lualib/https.dll differ diff --git a/lualib/ltn12.lua b/lualib/ltn12.lua new file mode 100644 index 0000000..b42689a --- /dev/null +++ b/lualib/ltn12.lua @@ -0,0 +1,292 @@ +----------------------------------------------------------------------------- +-- LTN12 - Filters, sources, sinks and pumps. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: ltn12.lua,v 1.31 2006/04/03 04:45:42 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module +----------------------------------------------------------------------------- +local string = require("string") +local table = require("table") +local base = _G +module("ltn12") + +filter = {} +source = {} +sink = {} +pump = {} + +-- 2048 seems to be better in windows... +BLOCKSIZE = 2048 +_VERSION = "LTN12 1.0.1" + +----------------------------------------------------------------------------- +-- Filter stuff +----------------------------------------------------------------------------- +-- returns a high level filter that cycles a low-level filter +function filter.cycle(low, ctx, extra) + base.assert(low) + return function(chunk) + local ret + ret, ctx = low(ctx, chunk, extra) + return ret + end +end + +-- chains a bunch of filters together +-- (thanks to Wim Couwenberg) +function filter.chain(...) + local n = table.getn(arg) + local top, index = 1, 1 + local retry = "" + return function(chunk) + retry = chunk and retry + while true do + if index == top then + chunk = arg[index](chunk) + if chunk == "" or top == n then return chunk + elseif chunk then index = index + 1 + else + top = top+1 + index = top + end + else + chunk = arg[index](chunk or "") + if chunk == "" then + index = index - 1 + chunk = retry + elseif chunk then + if index == n then return chunk + else index = index + 1 end + else base.error("filter returned inappropriate nil") end + end + end + end +end + +----------------------------------------------------------------------------- +-- Source stuff +----------------------------------------------------------------------------- +-- create an empty source +local function empty() + return nil +end + +function source.empty() + return empty +end + +-- returns a source that just outputs an error +function source.error(err) + return function() + return nil, err + end +end + +-- creates a file source +function source.file(handle, io_err) + if handle then + return function() + local chunk = handle:read(BLOCKSIZE) + if not chunk then handle:close() end + return chunk + end + else return source.error(io_err or "unable to open file") end +end + +-- turns a fancy source into a simple source +function source.simplify(src) + base.assert(src) + return function() + local chunk, err_or_new = src() + src = err_or_new or src + if not chunk then return nil, err_or_new + else return chunk end + end +end + +-- creates string source +function source.string(s) + if s then + local i = 1 + return function() + local chunk = string.sub(s, i, i+BLOCKSIZE-1) + i = i + BLOCKSIZE + if chunk ~= "" then return chunk + else return nil end + end + else return source.empty() end +end + +-- creates rewindable source +function source.rewind(src) + base.assert(src) + local t = {} + return function(chunk) + if not chunk then + chunk = table.remove(t) + if not chunk then return src() + else return chunk end + else + table.insert(t, chunk) + end + end +end + +function source.chain(src, f) + base.assert(src and f) + local last_in, last_out = "", "" + local state = "feeding" + local err + return function() + if not last_out then + base.error('source is empty!', 2) + end + while true do + if state == "feeding" then + last_in, err = src() + if err then return nil, err end + last_out = f(last_in) + if not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + elseif last_out ~= "" then + state = "eating" + if last_in then last_in = "" end + return last_out + end + else + last_out = f(last_in) + if last_out == "" then + if last_in == "" then + state = "feeding" + else + base.error('filter returned ""') + end + elseif not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + else + return last_out + end + end + end + end +end + +-- creates a source that produces contents of several sources, one after the +-- other, as if they were concatenated +-- (thanks to Wim Couwenberg) +function source.cat(...) + local src = table.remove(arg, 1) + return function() + while src do + local chunk, err = src() + if chunk then return chunk end + if err then return nil, err end + src = table.remove(arg, 1) + end + end +end + +----------------------------------------------------------------------------- +-- Sink stuff +----------------------------------------------------------------------------- +-- creates a sink that stores into a table +function sink.table(t) + t = t or {} + local f = function(chunk, err) + if chunk then table.insert(t, chunk) end + return 1 + end + return f, t +end + +-- turns a fancy sink into a simple sink +function sink.simplify(snk) + base.assert(snk) + return function(chunk, err) + local ret, err_or_new = snk(chunk, err) + if not ret then return nil, err_or_new end + snk = err_or_new or snk + return 1 + end +end + +-- creates a file sink +function sink.file(handle, io_err) + if handle then + return function(chunk, err) + if not chunk then + handle:close() + return 1 + else return handle:write(chunk) end + end + else return sink.error(io_err or "unable to open file") end +end + +-- creates a sink that discards data +local function null() + return 1 +end + +function sink.null() + return null +end + +-- creates a sink that just returns an error +function sink.error(err) + return function() + return nil, err + end +end + +-- chains a sink with a filter +function sink.chain(f, snk) + base.assert(f and snk) + return function(chunk, err) + if chunk ~= "" then + local filtered = f(chunk) + local done = chunk and "" + while true do + local ret, snkerr = snk(filtered, err) + if not ret then return nil, snkerr end + if filtered == done then return 1 end + filtered = f(done) + end + else return 1 end + end +end + +----------------------------------------------------------------------------- +-- Pump stuff +----------------------------------------------------------------------------- +-- pumps one chunk from the source to the sink +function pump.step(src, snk) + local chunk, src_err = src() + local ret, snk_err = snk(chunk, src_err) + if chunk and ret then return 1 + else return nil, src_err or snk_err end +end + +-- pumps all data from a source to a sink, using a step function +function pump.all(src, snk, step) + base.assert(src and snk) + step = step or pump.step + while true do + local ret, err = step(src, snk) + if not ret then + if err then return nil, err + else return 1 end + end + end +end + diff --git a/lualib/mime.lua b/lualib/mime.lua new file mode 100644 index 0000000..7fdd9ed --- /dev/null +++ b/lualib/mime.lua @@ -0,0 +1,87 @@ +----------------------------------------------------------------------------- +-- MIME support for the Lua language. +-- Author: Diego Nehab +-- Conforming to RFCs 2045-2049 +-- RCS ID: $Id: mime.lua,v 1.29 2007/06/11 23:44:54 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local ltn12 = require("ltn12") +local mime = require("mime.core") +--local io = require("io") +local string = require("string") +module("mime") + +-- encode, decode and wrap algorithm tables +encodet = {} +decodet = {} +wrapt = {} + +-- creates a function that chooses a filter by name from a given table +local function choose(table) + return function(name, opt1, opt2) + if base.type(name) ~= "string" then + name, opt1, opt2 = "default", name, opt1 + end + local f = table[name or "nil"] + if not f then + base.error("unknown key (" .. base.tostring(name) .. ")", 3) + else return f(opt1, opt2) end + end +end + +-- define the encoding filters +encodet['base64'] = function() + return ltn12.filter.cycle(b64, "") +end + +encodet['quoted-printable'] = function(mode) + return ltn12.filter.cycle(qp, "", + (mode == "binary") and "=0D=0A" or "\r\n") +end + +-- define the decoding filters +decodet['base64'] = function() + return ltn12.filter.cycle(unb64, "") +end + +decodet['quoted-printable'] = function() + return ltn12.filter.cycle(unqp, "") +end + +local function format(chunk) + if chunk then + if chunk == "" then return "''" + else return string.len(chunk) end + else return "nil" end +end + +-- define the line-wrap filters +wrapt['text'] = function(length) + length = length or 76 + return ltn12.filter.cycle(wrp, length, length) +end +wrapt['base64'] = wrapt['text'] +wrapt['default'] = wrapt['text'] + +wrapt['quoted-printable'] = function() + return ltn12.filter.cycle(qpwrp, 76, 76) +end + +-- function that choose the encoding, decoding or wrap algorithm +encode = choose(encodet) +decode = choose(decodet) +wrap = choose(wrapt) + +-- define the end-of-line normalization filter +function normalize(marker) + return ltn12.filter.cycle(eol, 0, marker) +end + +-- high level stuffing filter +function stuff() + return ltn12.filter.cycle(dot, 2) +end diff --git a/lualib/mime/core.dll b/lualib/mime/core.dll new file mode 100644 index 0000000..8de5805 Binary files /dev/null and b/lualib/mime/core.dll differ diff --git a/lualib/socket.lua b/lualib/socket.lua new file mode 100644 index 0000000..211adcd --- /dev/null +++ b/lualib/socket.lua @@ -0,0 +1,133 @@ +----------------------------------------------------------------------------- +-- LuaSocket helper module +-- Author: Diego Nehab +-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local string = require("string") +local math = require("math") +local socket = require("socket.core") +module("socket") + +----------------------------------------------------------------------------- +-- Exported auxiliar functions +----------------------------------------------------------------------------- +function connect(address, port, laddress, lport) + local sock, err = socket.tcp() + if not sock then return nil, err end + if laddress then + local res, err = sock:bind(laddress, lport, -1) + if not res then return nil, err end + end + local res, err = sock:connect(address, port) + if not res then return nil, err end + return sock +end + +function bind(host, port, backlog) + local sock, err = socket.tcp() + if not sock then return nil, err end + sock:setoption("reuseaddr", true) + local res, err = sock:bind(host, port) + if not res then return nil, err end + res, err = sock:listen(backlog) + if not res then return nil, err end + return sock +end + +try = newtry() + +function choose(table) + return function(name, opt1, opt2) + if base.type(name) ~= "string" then + name, opt1, opt2 = "default", name, opt1 + end + local f = table[name or "nil"] + if not f then base.error("unknown key (".. base.tostring(name) ..")", 3) + else return f(opt1, opt2) end + end +end + +----------------------------------------------------------------------------- +-- Socket sources and sinks, conforming to LTN12 +----------------------------------------------------------------------------- +-- create namespaces inside LuaSocket namespace +sourcet = {} +sinkt = {} + +BLOCKSIZE = 2048 + +sinkt["close-when-done"] = function(sock) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function(self, chunk, err) + if not chunk then + sock:close() + return 1 + else return sock:send(chunk) end + end + }) +end + +sinkt["keep-open"] = function(sock) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function(self, chunk, err) + if chunk then return sock:send(chunk) + else return 1 end + end + }) +end + +sinkt["default"] = sinkt["keep-open"] + +sink = choose(sinkt) + +sourcet["by-length"] = function(sock, length) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function() + if length <= 0 then return nil end + local size = math.min(socket.BLOCKSIZE, length) + local chunk, err = sock:receive(size) + if err then return nil, err end + length = length - string.len(chunk) + return chunk + end + }) +end + +sourcet["until-closed"] = function(sock) + local done + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function() + if done then return nil end + local chunk, err, partial = sock:receive(socket.BLOCKSIZE) + if not err then return chunk + elseif err == "closed" then + sock:close() + done = 1 + return partial + else return nil, err end + end + }) +end + + +sourcet["default"] = sourcet["until-closed"] + +source = choose(sourcet) + diff --git a/lualib/socket/core.dll b/lualib/socket/core.dll new file mode 100644 index 0000000..9cb49ee Binary files /dev/null and b/lualib/socket/core.dll differ diff --git a/lualib/socket/ftp.lua b/lualib/socket/ftp.lua new file mode 100644 index 0000000..598f65d --- /dev/null +++ b/lualib/socket/ftp.lua @@ -0,0 +1,281 @@ +----------------------------------------------------------------------------- +-- FTP support for the Lua language +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: ftp.lua,v 1.45 2007/07/11 19:25:47 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local table = require("table") +local string = require("string") +local math = require("math") +local socket = require("socket") +local url = require("socket.url") +local tp = require("socket.tp") +local ltn12 = require("ltn12") +module("socket.ftp") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +-- timeout in seconds before the program gives up on a connection +TIMEOUT = 60 +-- default port for ftp service +PORT = 21 +-- this is the default anonymous password. used when no password is +-- provided in url. should be changed to your e-mail. +USER = "ftp" +PASSWORD = "anonymous@anonymous.org" + +----------------------------------------------------------------------------- +-- Low level FTP API +----------------------------------------------------------------------------- +local metat = { __index = {} } + +function open(server, port, create) + local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT, create)) + local f = base.setmetatable({ tp = tp }, metat) + -- make sure everything gets closed in an exception + f.try = socket.newtry(function() f:close() end) + return f +end + +function metat.__index:portconnect() + self.try(self.server:settimeout(TIMEOUT)) + self.data = self.try(self.server:accept()) + self.try(self.data:settimeout(TIMEOUT)) +end + +function metat.__index:pasvconnect() + self.data = self.try(socket.tcp()) + self.try(self.data:settimeout(TIMEOUT)) + self.try(self.data:connect(self.pasvt.ip, self.pasvt.port)) +end + +function metat.__index:login(user, password) + self.try(self.tp:command("user", user or USER)) + local code, reply = self.try(self.tp:check{"2..", 331}) + if code == 331 then + self.try(self.tp:command("pass", password or PASSWORD)) + self.try(self.tp:check("2..")) + end + return 1 +end + +function metat.__index:pasv() + self.try(self.tp:command("pasv")) + local code, reply = self.try(self.tp:check("2..")) + local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" + local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) + self.try(a and b and c and d and p1 and p2, reply) + self.pasvt = { + ip = string.format("%d.%d.%d.%d", a, b, c, d), + port = p1*256 + p2 + } + if self.server then + self.server:close() + self.server = nil + end + return self.pasvt.ip, self.pasvt.port +end + +function metat.__index:port(ip, port) + self.pasvt = nil + if not ip then + ip, port = self.try(self.tp:getcontrol():getsockname()) + self.server = self.try(socket.bind(ip, 0)) + ip, port = self.try(self.server:getsockname()) + self.try(self.server:settimeout(TIMEOUT)) + end + local pl = math.mod(port, 256) + local ph = (port - pl)/256 + local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",") + self.try(self.tp:command("port", arg)) + self.try(self.tp:check("2..")) + return 1 +end + +function metat.__index:send(sendt) + self.try(self.pasvt or self.server, "need port or pasv first") + -- if there is a pasvt table, we already sent a PASV command + -- we just get the data connection into self.data + if self.pasvt then self:pasvconnect() end + -- get the transfer argument and command + local argument = sendt.argument or + url.unescape(string.gsub(sendt.path or "", "^[/\\]", "")) + if argument == "" then argument = nil end + local command = sendt.command or "stor" + -- send the transfer command and check the reply + self.try(self.tp:command(command, argument)) + local code, reply = self.try(self.tp:check{"2..", "1.."}) + -- if there is not a a pasvt table, then there is a server + -- and we already sent a PORT command + if not self.pasvt then self:portconnect() end + -- get the sink, source and step for the transfer + local step = sendt.step or ltn12.pump.step + local readt = {self.tp.c} + local checkstep = function(src, snk) + -- check status in control connection while downloading + local readyt = socket.select(readt, nil, 0) + if readyt[tp] then code = self.try(self.tp:check("2..")) end + return step(src, snk) + end + local sink = socket.sink("close-when-done", self.data) + -- transfer all data and check error + self.try(ltn12.pump.all(sendt.source, sink, checkstep)) + if string.find(code, "1..") then self.try(self.tp:check("2..")) end + -- done with data connection + self.data:close() + -- find out how many bytes were sent + local sent = socket.skip(1, self.data:getstats()) + self.data = nil + return sent +end + +function metat.__index:receive(recvt) + self.try(self.pasvt or self.server, "need port or pasv first") + if self.pasvt then self:pasvconnect() end + local argument = recvt.argument or + url.unescape(string.gsub(recvt.path or "", "^[/\\]", "")) + if argument == "" then argument = nil end + local command = recvt.command or "retr" + self.try(self.tp:command(command, argument)) + local code = self.try(self.tp:check{"1..", "2.."}) + if not self.pasvt then self:portconnect() end + local source = socket.source("until-closed", self.data) + local step = recvt.step or ltn12.pump.step + self.try(ltn12.pump.all(source, recvt.sink, step)) + if string.find(code, "1..") then self.try(self.tp:check("2..")) end + self.data:close() + self.data = nil + return 1 +end + +function metat.__index:cwd(dir) + self.try(self.tp:command("cwd", dir)) + self.try(self.tp:check(250)) + return 1 +end + +function metat.__index:type(type) + self.try(self.tp:command("type", type)) + self.try(self.tp:check(200)) + return 1 +end + +function metat.__index:greet() + local code = self.try(self.tp:check{"1..", "2.."}) + if string.find(code, "1..") then self.try(self.tp:check("2..")) end + return 1 +end + +function metat.__index:quit() + self.try(self.tp:command("quit")) + self.try(self.tp:check("2..")) + return 1 +end + +function metat.__index:close() + if self.data then self.data:close() end + if self.server then self.server:close() end + return self.tp:close() +end + +----------------------------------------------------------------------------- +-- High level FTP API +----------------------------------------------------------------------------- +local function override(t) + if t.url then + local u = url.parse(t.url) + for i,v in base.pairs(t) do + u[i] = v + end + return u + else return t end +end + +local function tput(putt) + putt = override(putt) + socket.try(putt.host, "missing hostname") + local f = open(putt.host, putt.port, putt.create) + f:greet() + f:login(putt.user, putt.password) + if putt.type then f:type(putt.type) end + f:pasv() + local sent = f:send(putt) + f:quit() + f:close() + return sent +end + +local default = { + path = "/", + scheme = "ftp" +} + +local function parse(u) + local t = socket.try(url.parse(u, default)) + socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") + socket.try(t.host, "missing hostname") + local pat = "^type=(.)$" + if t.params then + t.type = socket.skip(2, string.find(t.params, pat)) + socket.try(t.type == "a" or t.type == "i", + "invalid type '" .. t.type .. "'") + end + return t +end + +local function sput(u, body) + local putt = parse(u) + putt.source = ltn12.source.string(body) + return tput(putt) +end + +put = socket.protect(function(putt, body) + if base.type(putt) == "string" then return sput(putt, body) + else return tput(putt) end +end) + +local function tget(gett) + gett = override(gett) + socket.try(gett.host, "missing hostname") + local f = open(gett.host, gett.port, gett.create) + f:greet() + f:login(gett.user, gett.password) + if gett.type then f:type(gett.type) end + f:pasv() + f:receive(gett) + f:quit() + return f:close() +end + +local function sget(u) + local gett = parse(u) + local t = {} + gett.sink = ltn12.sink.table(t) + tget(gett) + return table.concat(t) +end + +command = socket.protect(function(cmdt) + cmdt = override(cmdt) + socket.try(cmdt.host, "missing hostname") + socket.try(cmdt.command, "missing command") + local f = open(cmdt.host, cmdt.port, cmdt.create) + f:greet() + f:login(cmdt.user, cmdt.password) + f.try(f.tp:command(cmdt.command, cmdt.argument)) + if cmdt.check then f.try(f.tp:check(cmdt.check)) end + f:quit() + return f:close() +end) + +get = socket.protect(function(gett) + if base.type(gett) == "string" then return sget(gett) + else return tget(gett) end +end) + diff --git a/lualib/socket/http.lua b/lualib/socket/http.lua new file mode 100644 index 0000000..c020d8e --- /dev/null +++ b/lualib/socket/http.lua @@ -0,0 +1,350 @@ +----------------------------------------------------------------------------- +-- HTTP/1.1 client support for the Lua language. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: http.lua,v 1.70 2007/03/12 04:08:40 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +------------------------------------------------------------------------------- +local socket = require("socket") +local url = require("socket.url") +local ltn12 = require("ltn12") +local mime = require("mime") +local string = require("string") +local base = _G +local table = require("table") +module("socket.http") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +-- connection timeout in seconds +TIMEOUT = 60 +-- default port for document retrieval +PORT = 80 +-- user agent field sent in request +USERAGENT = socket._VERSION + +----------------------------------------------------------------------------- +-- Reads MIME headers from a connection, unfolding where needed +----------------------------------------------------------------------------- +local function receiveheaders(sock, headers) + local line, name, value, err + headers = headers or {} + -- get first line + line, err = sock:receive() + if err then return nil, err end + -- headers go until a blank line is found + while line ~= "" do + -- get field-name and value + name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) + if not (name and value) then return nil, "malformed reponse headers" end + name = string.lower(name) + -- get next line (value might be folded) + line, err = sock:receive() + if err then return nil, err end + -- unfold any folded values + while string.find(line, "^%s") do + value = value .. line + line = sock:receive() + if err then return nil, err end + end + -- save pair in table + if headers[name] then headers[name] = headers[name] .. ", " .. value + else headers[name] = value end + end + return headers +end + +----------------------------------------------------------------------------- +-- Extra sources and sinks +----------------------------------------------------------------------------- +socket.sourcet["http-chunked"] = function(sock, headers) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function() + -- get chunk size, skip extention + local line, err = sock:receive() + if err then return nil, err end + local size = base.tonumber(string.gsub(line, ";.*", ""), 16) + if not size then return nil, "invalid chunk size" end + -- was it the last chunk? + if size > 0 then + -- if not, get chunk and skip terminating CRLF + local chunk, err, part = sock:receive(size) + if chunk then sock:receive() end + return chunk, err + else + -- if it was, read trailers into headers table + headers, err = receiveheaders(sock, headers) + if not headers then return nil, err end + end + end + }) +end + +socket.sinkt["http-chunked"] = function(sock) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function(self, chunk, err) + if not chunk then return sock:send("0\r\n\r\n") end + local size = string.format("%X\r\n", string.len(chunk)) + return sock:send(size .. chunk .. "\r\n") + end + }) +end + +----------------------------------------------------------------------------- +-- Low level HTTP API +----------------------------------------------------------------------------- +local metat = { __index = {} } + +function open(host, port, create) + -- create socket with user connect function, or with default + local c = socket.try((create or socket.tcp)()) + local h = base.setmetatable({ c = c }, metat) + -- create finalized try + h.try = socket.newtry(function() h:close() end) + -- set timeout before connecting + h.try(c:settimeout(TIMEOUT)) + h.try(c:connect(host, port or PORT)) + -- here everything worked + return h +end + +function metat.__index:sendrequestline(method, uri) + local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri) + return self.try(self.c:send(reqline)) +end + +function metat.__index:sendheaders(headers) + local h = "\r\n" + for i, v in base.pairs(headers) do + h = i .. ": " .. v .. "\r\n" .. h + end + self.try(self.c:send(h)) + return 1 +end + +function metat.__index:sendbody(headers, source, step) + source = source or ltn12.source.empty() + step = step or ltn12.pump.step + -- if we don't know the size in advance, send chunked and hope for the best + local mode = "http-chunked" + if headers["content-length"] then mode = "keep-open" end + return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step)) +end + +function metat.__index:receivestatusline() + local status = self.try(self.c:receive(5)) + -- identify HTTP/0.9 responses, which do not contain a status line + -- this is just a heuristic, but is what the RFC recommends + if status ~= "HTTP/" then return nil, status end + -- otherwise proceed reading a status line + status = self.try(self.c:receive("*l", status)) + local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) + return self.try(base.tonumber(code), status) +end + +function metat.__index:receiveheaders() + return self.try(receiveheaders(self.c)) +end + +function metat.__index:receivebody(headers, sink, step) + sink = sink or ltn12.sink.null() + step = step or ltn12.pump.step + local length = base.tonumber(headers["content-length"]) + local t = headers["transfer-encoding"] -- shortcut + local mode = "default" -- connection close + if t and t ~= "identity" then mode = "http-chunked" + elseif base.tonumber(headers["content-length"]) then mode = "by-length" end + return self.try(ltn12.pump.all(socket.source(mode, self.c, length), + sink, step)) +end + +function metat.__index:receive09body(status, sink, step) + local source = ltn12.source.rewind(socket.source("until-closed", self.c)) + source(status) + return self.try(ltn12.pump.all(source, sink, step)) +end + +function metat.__index:close() + return self.c:close() +end + +----------------------------------------------------------------------------- +-- High level HTTP API +----------------------------------------------------------------------------- +local function adjusturi(reqt) + local u = reqt + -- if there is a proxy, we need the full url. otherwise, just a part. + if not reqt.proxy and not PROXY then + u = { + path = socket.try(reqt.path, "invalid path 'nil'"), + params = reqt.params, + query = reqt.query, + fragment = reqt.fragment + } + end + return url.build(u) +end + +local function adjustproxy(reqt) + local proxy = reqt.proxy or PROXY + if proxy then + proxy = url.parse(proxy) + return proxy.host, proxy.port or 3128 + else + return reqt.host, reqt.port + end +end + +local function adjustheaders(reqt) + -- default headers + local lower = { + ["user-agent"] = USERAGENT, + ["host"] = reqt.host, + ["connection"] = "close, TE", + ["te"] = "trailers" + } + -- if we have authentication information, pass it along + if reqt.user and reqt.password then + lower["authorization"] = + "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password)) + end + -- override with user headers + for i,v in base.pairs(reqt.headers or lower) do + lower[string.lower(i)] = v + end + return lower +end + +-- default url parts +local default = { + host = "", + port = PORT, + path ="/", + scheme = "http" +} + +local function adjustrequest(reqt) + -- parse url if provided + local nreqt = reqt.url and url.parse(reqt.url, default) or {} + -- explicit components override url + for i,v in base.pairs(reqt) do nreqt[i] = v end + if nreqt.port == "" then nreqt.port = 80 end + socket.try(nreqt.host and nreqt.host ~= "", + "invalid host '" .. base.tostring(nreqt.host) .. "'") + -- compute uri if user hasn't overriden + nreqt.uri = reqt.uri or adjusturi(nreqt) + -- ajust host and port if there is a proxy + nreqt.host, nreqt.port = adjustproxy(nreqt) + -- adjust headers in request + nreqt.headers = adjustheaders(nreqt) + return nreqt +end + +local function shouldredirect(reqt, code, headers) + return headers.location and + string.gsub(headers.location, "%s", "") ~= "" and + (reqt.redirect ~= false) and + (code == 301 or code == 302) and + (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") + and (not reqt.nredirects or reqt.nredirects < 5) +end + +local function shouldreceivebody(reqt, code) + if reqt.method == "HEAD" then return nil end + if code == 204 or code == 304 then return nil end + if code >= 100 and code < 200 then return nil end + return 1 +end + +-- forward declarations +local trequest, tredirect + +function tredirect(reqt, location) + local result, code, headers, status = trequest { + -- the RFC says the redirect URL has to be absolute, but some + -- servers do not respect that + url = url.absolute(reqt.url, location), + source = reqt.source, + sink = reqt.sink, + headers = reqt.headers, + proxy = reqt.proxy, + nredirects = (reqt.nredirects or 0) + 1, + create = reqt.create + } + -- pass location header back as a hint we redirected + headers = headers or {} + headers.location = headers.location or location + return result, code, headers, status +end + +function trequest(reqt) + -- we loop until we get what we want, or + -- until we are sure there is no way to get it + local nreqt = adjustrequest(reqt) + local h = open(nreqt.host, nreqt.port, nreqt.create) + -- send request line and headers + h:sendrequestline(nreqt.method, nreqt.uri) + h:sendheaders(nreqt.headers) + -- if there is a body, send it + if nreqt.source then + h:sendbody(nreqt.headers, nreqt.source, nreqt.step) + end + local code, status = h:receivestatusline() + -- if it is an HTTP/0.9 server, simply get the body and we are done + if not code then + h:receive09body(status, nreqt.sink, nreqt.step) + return 1, 200 + end + local headers + -- ignore any 100-continue messages + while code == 100 do + headers = h:receiveheaders() + code, status = h:receivestatusline() + end + headers = h:receiveheaders() + -- at this point we should have a honest reply from the server + -- we can't redirect if we already used the source, so we report the error + if shouldredirect(nreqt, code, headers) and not nreqt.source then + h:close() + return tredirect(reqt, headers.location) + end + -- here we are finally done + if shouldreceivebody(nreqt, code) then + h:receivebody(headers, nreqt.sink, nreqt.step) + end + h:close() + return 1, code, headers, status +end + +local function srequest(u, b) + local t = {} + local reqt = { + url = u, + sink = ltn12.sink.table(t) + } + if b then + reqt.source = ltn12.source.string(b) + reqt.headers = { + ["content-length"] = string.len(b), + ["content-type"] = "application/x-www-form-urlencoded" + } + reqt.method = "POST" + end + local code, headers, status = socket.skip(1, trequest(reqt)) + return table.concat(t), code, headers, status +end + +request = socket.protect(function(reqt, body) + if base.type(reqt) == "string" then return srequest(reqt, body) + else return trequest(reqt) end +end) diff --git a/lualib/socket/smtp.lua b/lualib/socket/smtp.lua new file mode 100644 index 0000000..8f3cfcf --- /dev/null +++ b/lualib/socket/smtp.lua @@ -0,0 +1,251 @@ +----------------------------------------------------------------------------- +-- SMTP client support for the Lua language. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: smtp.lua,v 1.46 2007/03/12 04:08:40 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local coroutine = require("coroutine") +local string = require("string") +local math = require("math") +local os = require("os") +local socket = require("socket") +local tp = require("socket.tp") +local ltn12 = require("ltn12") +local mime = require("mime") +module("socket.smtp") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +-- timeout for connection +TIMEOUT = 60 +-- default server used to send e-mails +SERVER = "localhost" +-- default port +PORT = 25 +-- domain used in HELO command and default sendmail +-- If we are under a CGI, try to get from environment +DOMAIN = os.getenv("SERVER_NAME") or "localhost" +-- default time zone (means we don't know) +ZONE = "-0000" + +--------------------------------------------------------------------------- +-- Low level SMTP API +----------------------------------------------------------------------------- +local metat = { __index = {} } + +function metat.__index:greet(domain) + self.try(self.tp:check("2..")) + self.try(self.tp:command("EHLO", domain or DOMAIN)) + return socket.skip(1, self.try(self.tp:check("2.."))) +end + +function metat.__index:mail(from) + self.try(self.tp:command("MAIL", "FROM:" .. from)) + return self.try(self.tp:check("2..")) +end + +function metat.__index:rcpt(to) + self.try(self.tp:command("RCPT", "TO:" .. to)) + return self.try(self.tp:check("2..")) +end + +function metat.__index:data(src, step) + self.try(self.tp:command("DATA")) + self.try(self.tp:check("3..")) + self.try(self.tp:source(src, step)) + self.try(self.tp:send("\r\n.\r\n")) + return self.try(self.tp:check("2..")) +end + +function metat.__index:quit() + self.try(self.tp:command("QUIT")) + return self.try(self.tp:check("2..")) +end + +function metat.__index:close() + return self.tp:close() +end + +function metat.__index:login(user, password) + self.try(self.tp:command("AUTH", "LOGIN")) + self.try(self.tp:check("3..")) + self.try(self.tp:command(mime.b64(user))) + self.try(self.tp:check("3..")) + self.try(self.tp:command(mime.b64(password))) + return self.try(self.tp:check("2..")) +end + +function metat.__index:plain(user, password) + local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password) + self.try(self.tp:command("AUTH", auth)) + return self.try(self.tp:check("2..")) +end + +function metat.__index:auth(user, password, ext) + if not user or not password then return 1 end + if string.find(ext, "AUTH[^\n]+LOGIN") then + return self:login(user, password) + elseif string.find(ext, "AUTH[^\n]+PLAIN") then + return self:plain(user, password) + else + self.try(nil, "authentication not supported") + end +end + +-- send message or throw an exception +function metat.__index:send(mailt) + self:mail(mailt.from) + if base.type(mailt.rcpt) == "table" then + for i,v in base.ipairs(mailt.rcpt) do + self:rcpt(v) + end + else + self:rcpt(mailt.rcpt) + end + self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step) +end + +function open(server, port, create) + local tp = socket.try(tp.connect(server or SERVER, port or PORT, + TIMEOUT, create)) + local s = base.setmetatable({tp = tp}, metat) + -- make sure tp is closed if we get an exception + s.try = socket.newtry(function() + s:close() + end) + return s +end + +-- convert headers to lowercase +local function lower_headers(headers) + local lower = {} + for i,v in base.pairs(headers or lower) do + lower[string.lower(i)] = v + end + return lower +end + +--------------------------------------------------------------------------- +-- Multipart message source +----------------------------------------------------------------------------- +-- returns a hopefully unique mime boundary +local seqno = 0 +local function newboundary() + seqno = seqno + 1 + return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'), + math.random(0, 99999), seqno) +end + +-- send_message forward declaration +local send_message + +-- yield the headers all at once, it's faster +local function send_headers(headers) + local h = "\r\n" + for i,v in base.pairs(headers) do + h = i .. ': ' .. v .. "\r\n" .. h + end + coroutine.yield(h) +end + +-- yield multipart message body from a multipart message table +local function send_multipart(mesgt) + -- make sure we have our boundary and send headers + local bd = newboundary() + local headers = lower_headers(mesgt.headers or {}) + headers['content-type'] = headers['content-type'] or 'multipart/mixed' + headers['content-type'] = headers['content-type'] .. + '; boundary="' .. bd .. '"' + send_headers(headers) + -- send preamble + if mesgt.body.preamble then + coroutine.yield(mesgt.body.preamble) + coroutine.yield("\r\n") + end + -- send each part separated by a boundary + for i, m in base.ipairs(mesgt.body) do + coroutine.yield("\r\n--" .. bd .. "\r\n") + send_message(m) + end + -- send last boundary + coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") + -- send epilogue + if mesgt.body.epilogue then + coroutine.yield(mesgt.body.epilogue) + coroutine.yield("\r\n") + end +end + +-- yield message body from a source +local function send_source(mesgt) + -- make sure we have a content-type + local headers = lower_headers(mesgt.headers or {}) + headers['content-type'] = headers['content-type'] or + 'text/plain; charset="iso-8859-1"' + send_headers(headers) + -- send body from source + while true do + local chunk, err = mesgt.body() + if err then coroutine.yield(nil, err) + elseif chunk then coroutine.yield(chunk) + else break end + end +end + +-- yield message body from a string +local function send_string(mesgt) + -- make sure we have a content-type + local headers = lower_headers(mesgt.headers or {}) + headers['content-type'] = headers['content-type'] or + 'text/plain; charset="iso-8859-1"' + send_headers(headers) + -- send body from string + coroutine.yield(mesgt.body) +end + +-- message source +function send_message(mesgt) + if base.type(mesgt.body) == "table" then send_multipart(mesgt) + elseif base.type(mesgt.body) == "function" then send_source(mesgt) + else send_string(mesgt) end +end + +-- set defaul headers +local function adjust_headers(mesgt) + local lower = lower_headers(mesgt.headers) + lower["date"] = lower["date"] or + os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE) + lower["x-mailer"] = lower["x-mailer"] or socket._VERSION + -- this can't be overriden + lower["mime-version"] = "1.0" + return lower +end + +function message(mesgt) + mesgt.headers = adjust_headers(mesgt) + -- create and return message source + local co = coroutine.create(function() send_message(mesgt) end) + return function() + local ret, a, b = coroutine.resume(co) + if ret then return a, b + else return nil, a end + end +end + +--------------------------------------------------------------------------- +-- High level SMTP API +----------------------------------------------------------------------------- +send = socket.protect(function(mailt) + local s = open(mailt.server, mailt.port, mailt.create) + local ext = s:greet(mailt.domain) + s:auth(mailt.user, mailt.password, ext) + s:send(mailt) + s:quit() + return s:close() +end) diff --git a/lualib/socket/tp.lua b/lualib/socket/tp.lua new file mode 100644 index 0000000..0683869 --- /dev/null +++ b/lualib/socket/tp.lua @@ -0,0 +1,123 @@ +----------------------------------------------------------------------------- +-- Unified SMTP/FTP subsystem +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: tp.lua,v 1.22 2006/03/14 09:04:15 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local string = require("string") +local socket = require("socket") +local ltn12 = require("ltn12") +module("socket.tp") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +TIMEOUT = 60 + +----------------------------------------------------------------------------- +-- Implementation +----------------------------------------------------------------------------- +-- gets server reply (works for SMTP and FTP) +local function get_reply(c) + local code, current, sep + local line, err = c:receive() + local reply = line + if err then return nil, err end + code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) + if not code then return nil, "invalid server reply" end + if sep == "-" then -- reply is multiline + repeat + line, err = c:receive() + if err then return nil, err end + current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) + reply = reply .. "\n" .. line + -- reply ends with same code + until code == current and sep == " " + end + return code, reply +end + +-- metatable for sock object +local metat = { __index = {} } + +function metat.__index:check(ok) + local code, reply = get_reply(self.c) + if not code then return nil, reply end + if base.type(ok) ~= "function" then + if base.type(ok) == "table" then + for i, v in base.ipairs(ok) do + if string.find(code, v) then + return base.tonumber(code), reply + end + end + return nil, reply + else + if string.find(code, ok) then return base.tonumber(code), reply + else return nil, reply end + end + else return ok(base.tonumber(code), reply) end +end + +function metat.__index:command(cmd, arg) + if arg then + return self.c:send(cmd .. " " .. arg.. "\r\n") + else + return self.c:send(cmd .. "\r\n") + end +end + +function metat.__index:sink(snk, pat) + local chunk, err = c:receive(pat) + return snk(chunk, err) +end + +function metat.__index:send(data) + return self.c:send(data) +end + +function metat.__index:receive(pat) + return self.c:receive(pat) +end + +function metat.__index:getfd() + return self.c:getfd() +end + +function metat.__index:dirty() + return self.c:dirty() +end + +function metat.__index:getcontrol() + return self.c +end + +function metat.__index:source(source, step) + local sink = socket.sink("keep-open", self.c) + local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step) + return ret, err +end + +-- closes the underlying c +function metat.__index:close() + self.c:close() + return 1 +end + +-- connect with server and return c object +function connect(host, port, timeout, create) + local c, e = (create or socket.tcp)() + if not c then return nil, e end + c:settimeout(timeout or TIMEOUT) + local r, e = c:connect(host, port) + if not r then + c:close() + return nil, e + end + return base.setmetatable({c = c}, metat) +end + diff --git a/lualib/socket/url.lua b/lualib/socket/url.lua new file mode 100644 index 0000000..0e31d8a --- /dev/null +++ b/lualib/socket/url.lua @@ -0,0 +1,297 @@ +----------------------------------------------------------------------------- +-- URI parsing, composition and relative URL resolution +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: url.lua,v 1.38 2006/04/03 04:45:42 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module +----------------------------------------------------------------------------- +local string = require("string") +local base = _G +local table = require("table") +module("socket.url") + +----------------------------------------------------------------------------- +-- Module version +----------------------------------------------------------------------------- +_VERSION = "URL 1.0.1" + +----------------------------------------------------------------------------- +-- Encodes a string into its escaped hexadecimal representation +-- Input +-- s: binary string to be encoded +-- Returns +-- escaped representation of string binary +----------------------------------------------------------------------------- +function escape(s) + return string.gsub(s, "([^A-Za-z0-9_])", function(c) + return string.format("%%%02x", string.byte(c)) + end) +end + +----------------------------------------------------------------------------- +-- Protects a path segment, to prevent it from interfering with the +-- url parsing. +-- Input +-- s: binary string to be encoded +-- Returns +-- escaped representation of string binary +----------------------------------------------------------------------------- +local function make_set(t) + local s = {} + for i,v in base.ipairs(t) do + s[t[i]] = 1 + end + return s +end + +-- these are allowed withing a path segment, along with alphanum +-- other characters must be escaped +local segment_set = make_set { + "-", "_", ".", "!", "~", "*", "'", "(", + ")", ":", "@", "&", "=", "+", "$", ",", +} + +local function protect_segment(s) + return string.gsub(s, "([^A-Za-z0-9_])", function (c) + if segment_set[c] then return c + else return string.format("%%%02x", string.byte(c)) end + end) +end + +----------------------------------------------------------------------------- +-- Encodes a string into its escaped hexadecimal representation +-- Input +-- s: binary string to be encoded +-- Returns +-- escaped representation of string binary +----------------------------------------------------------------------------- +function unescape(s) + return string.gsub(s, "%%(%x%x)", function(hex) + return string.char(base.tonumber(hex, 16)) + end) +end + +----------------------------------------------------------------------------- +-- Builds a path from a base path and a relative path +-- Input +-- base_path +-- relative_path +-- Returns +-- corresponding absolute path +----------------------------------------------------------------------------- +local function absolute_path(base_path, relative_path) + if string.sub(relative_path, 1, 1) == "/" then return relative_path end + local path = string.gsub(base_path, "[^/]*$", "") + path = path .. relative_path + path = string.gsub(path, "([^/]*%./)", function (s) + if s ~= "./" then return s else return "" end + end) + path = string.gsub(path, "/%.$", "/") + local reduced + while reduced ~= path do + reduced = path + path = string.gsub(reduced, "([^/]*/%.%./)", function (s) + if s ~= "../../" then return "" else return s end + end) + end + path = string.gsub(reduced, "([^/]*/%.%.)$", function (s) + if s ~= "../.." then return "" else return s end + end) + return path +end + +----------------------------------------------------------------------------- +-- Parses a url and returns a table with all its parts according to RFC 2396 +-- The following grammar describes the names given to the URL parts +-- ::= :///;?# +-- ::= @: +-- ::= [:] +-- :: = {/} +-- Input +-- url: uniform resource locator of request +-- default: table with default values for each field +-- Returns +-- table with the following fields, where RFC naming conventions have +-- been preserved: +-- scheme, authority, userinfo, user, password, host, port, +-- path, params, query, fragment +-- Obs: +-- the leading '/' in {/} is considered part of +----------------------------------------------------------------------------- +function parse(url, default) + -- initialize default parameters + local parsed = {} + for i,v in base.pairs(default or parsed) do parsed[i] = v end + -- empty url is parsed to nil + if not url or url == "" then return nil, "invalid url" end + -- remove whitespace + -- url = string.gsub(url, "%s", "") + -- get fragment + url = string.gsub(url, "#(.*)$", function(f) + parsed.fragment = f + return "" + end) + -- get scheme + url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", + function(s) parsed.scheme = s; return "" end) + -- get authority + url = string.gsub(url, "^//([^/]*)", function(n) + parsed.authority = n + return "" + end) + -- get query stringing + url = string.gsub(url, "%?(.*)", function(q) + parsed.query = q + return "" + end) + -- get params + url = string.gsub(url, "%;(.*)", function(p) + parsed.params = p + return "" + end) + -- path is whatever was left + if url ~= "" then parsed.path = url end + local authority = parsed.authority + if not authority then return parsed end + authority = string.gsub(authority,"^([^@]*)@", + function(u) parsed.userinfo = u; return "" end) + authority = string.gsub(authority, ":([^:]*)$", + function(p) parsed.port = p; return "" end) + if authority ~= "" then parsed.host = authority end + local userinfo = parsed.userinfo + if not userinfo then return parsed end + userinfo = string.gsub(userinfo, ":([^:]*)$", + function(p) parsed.password = p; return "" end) + parsed.user = userinfo + return parsed +end + +----------------------------------------------------------------------------- +-- Rebuilds a parsed URL from its components. +-- Components are protected if any reserved or unallowed characters are found +-- Input +-- parsed: parsed URL, as returned by parse +-- Returns +-- a stringing with the corresponding URL +----------------------------------------------------------------------------- +function build(parsed) + local ppath = parse_path(parsed.path or "") + local url = build_path(ppath) + if parsed.params then url = url .. ";" .. parsed.params end + if parsed.query then url = url .. "?" .. parsed.query end + local authority = parsed.authority + if parsed.host then + authority = parsed.host + if parsed.port then authority = authority .. ":" .. parsed.port end + local userinfo = parsed.userinfo + if parsed.user then + userinfo = parsed.user + if parsed.password then + userinfo = userinfo .. ":" .. parsed.password + end + end + if userinfo then authority = userinfo .. "@" .. authority end + end + if authority then url = "//" .. authority .. url end + if parsed.scheme then url = parsed.scheme .. ":" .. url end + if parsed.fragment then url = url .. "#" .. parsed.fragment end + -- url = string.gsub(url, "%s", "") + return url +end + +----------------------------------------------------------------------------- +-- Builds a absolute URL from a base and a relative URL according to RFC 2396 +-- Input +-- base_url +-- relative_url +-- Returns +-- corresponding absolute url +----------------------------------------------------------------------------- +function absolute(base_url, relative_url) + if base.type(base_url) == "table" then + base_parsed = base_url + base_url = build(base_parsed) + else + base_parsed = parse(base_url) + end + local relative_parsed = parse(relative_url) + if not base_parsed then return relative_url + elseif not relative_parsed then return base_url + elseif relative_parsed.scheme then return relative_url + else + relative_parsed.scheme = base_parsed.scheme + if not relative_parsed.authority then + relative_parsed.authority = base_parsed.authority + if not relative_parsed.path then + relative_parsed.path = base_parsed.path + if not relative_parsed.params then + relative_parsed.params = base_parsed.params + if not relative_parsed.query then + relative_parsed.query = base_parsed.query + end + end + else + relative_parsed.path = absolute_path(base_parsed.path or "", + relative_parsed.path) + end + end + return build(relative_parsed) + end +end + +----------------------------------------------------------------------------- +-- Breaks a path into its segments, unescaping the segments +-- Input +-- path +-- Returns +-- segment: a table with one entry per segment +----------------------------------------------------------------------------- +function parse_path(path) + local parsed = {} + path = path or "" + --path = string.gsub(path, "%s", "") + string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) + for i = 1, table.getn(parsed) do + parsed[i] = unescape(parsed[i]) + end + if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end + if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end + return parsed +end + +----------------------------------------------------------------------------- +-- Builds a path component from its segments, escaping protected characters. +-- Input +-- parsed: path segments +-- unsafe: if true, segments are not protected before path is built +-- Returns +-- path: corresponding path stringing +----------------------------------------------------------------------------- +function build_path(parsed, unsafe) + local path = "" + local n = table.getn(parsed) + if unsafe then + for i = 1, n-1 do + path = path .. parsed[i] + path = path .. "/" + end + if n > 0 then + path = path .. parsed[n] + if parsed.is_directory then path = path .. "/" end + end + else + for i = 1, n-1 do + path = path .. protect_segment(parsed[i]) + path = path .. "/" + end + if n > 0 then + path = path .. protect_segment(parsed[n]) + if parsed.is_directory then path = path .. "/" end + end + end + if parsed.is_absolute then path = "/" .. path end + return path +end diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..dd791bf --- /dev/null +++ b/readme.md @@ -0,0 +1,36 @@ + +# BlockLua +## How to Install +- Install RedBlocklandLoader +- Copy `BlockLua.dll`, `lua5.1.dll`, into the `modules` folder next to `Blockland.exe` +- Optional: Copy the `lualib` folder into `modules` + + +## Quick Reference + +### From TorqueScript +`'print('hello world')` - Execute Lua code in the console by prepending a `'` (single quote) +`luaeval("code");` - Eval Lua code from Torque +`luacall("funcName", %args);` - Eval Lua code from Torque +`luaexec("fileName");` - Execute a Lua file from Torque +`luaget("varName");` - Read a Lua global variable +`luaset("varName");` - Write a Lua global variable + +### From Lua +`bl.funcName(args)` - Call a TorqueScript function +`bl.varName` - Read a TorqueScript global variable +`bl['varName']` - Read a TorqueScript global variable (with special characters in the name, or from an array) +`bl.set('varName', value)` - Write a TorqueScript global variable + +### Accessing Torque Objects from Lua +`bl.objectName` - Access a Torque object by name +`bl[objectID]` - Access a Torque object by ID (or name) +`bl.objectName.field` - Read a field or Lua key from a Torque object +`bl.objectName:set('field', value)` - Write a field on a Torque object +`bl.objectName.key = value` - Associate Lua data with a Torque object +`bl.objectName:method(args)` - Call a Torque object method + + +### Unsafe Mode +BlockLua-Unsafe.dll can be used in place of BlockLua.dll, to remove the sandboxing of Lua code. +This allows Lua code to access any file and use any library, including ffi. diff --git a/src/bllua4.cpp b/src/bllua4.cpp new file mode 100644 index 0000000..fa75efd --- /dev/null +++ b/src/bllua4.cpp @@ -0,0 +1,105 @@ +// BlockLua (bllua4): Simple Lua interface for TorqueScript + +// Includes + +#include +#include + +#include "lua.hpp" +#include "BlHooks.cpp" +#include "BlFuncs.cpp" + +#include "luainterp.cpp" +#include "lualibts.cpp" +lua_State* gL; +#include "tsliblua.cpp" + +// Global variables + +// Setup + +// Hack to encode the contents of text files as static strings +#define INCLUDE_BIN(varname, filename) \ + asm("_" #varname ": .incbin \"" filename "\""); \ + asm(".byte 0"); \ + extern char varname[]; +INCLUDE_BIN(bll_fileLuaEnvSafe, "lua-env-safe.lua"); +INCLUDE_BIN(bll_fileLuaEnv , "lua-env.lua"); +INCLUDE_BIN(bll_fileTsEnv , "ts-env.cs" ); +INCLUDE_BIN(bll_fileLuaStd , "util/std.lua"); +INCLUDE_BIN(bll_fileLuaVector , "util/vector.lua"); +INCLUDE_BIN(bll_fileLuaLibts , "util/libts.lua"); +INCLUDE_BIN(bll_fileTsLibtsSupport, "util/libts-support.cs"); +INCLUDE_BIN(bll_fileLuaLibbl , "util/libbl.lua" ); +INCLUDE_BIN(bll_fileLuaLibblTypes , "util/libbl-types.lua"); +INCLUDE_BIN(bll_fileTsLibblSupport, "util/libbl-support.cs"); +INCLUDE_BIN(bll_fileLoadaddons , "util/loadaddons.cs"); + +#define BLL_LOAD_LUA(lstate, vname) \ + if(!bll_LuaEval(lstate, vname)) { \ + BlPrintf(" Error executing " #vname); \ + return false; \ + } + +bool init() { + BlHooksInit(); + BlPrintf("BlockLua: Loading"); + + BlFuncsInit(); + + // Initialize Lua environment + gL = lua_open(); + luaL_openlibs(gL); + + // Expose TS API to Lua + llibbl_init(gL); + + // Set up Lua environment + BLL_LOAD_LUA(gL, bll_fileLuaEnv); + #ifndef BLLUA_UNSAFE + BLL_LOAD_LUA(gL, bll_fileLuaEnvSafe); + #endif + + // Expose Lua API to TS + BlAddFunction(NULL, NULL, "_bllua_luacall", bll_ts_luacall, "LuaCall(name, ...) - Call Lua function and return result", 2, 20); + BlEval(bll_fileTsEnv); + + // Load utilities + BLL_LOAD_LUA(gL, bll_fileLuaStd); + BLL_LOAD_LUA(gL, bll_fileLuaVector); + BLL_LOAD_LUA(gL, bll_fileLuaLibts); + BlEval(bll_fileTsLibtsSupport); + BLL_LOAD_LUA(gL, bll_fileLuaLibbl); + BLL_LOAD_LUA(gL, bll_fileLuaLibblTypes); + BlEval(bll_fileTsLibblSupport); + BlEval(bll_fileLoadaddons); + + BlEval("$_bllua_active = 1;"); + + BlPrintf(" BlockLua: Done Loading"); + return true; +} + +bool deinit() { + BlPrintf("BlockLua: Unloading"); + + BlEval("deactivatePackage(_bllua_main);"); + BlEval("$_bllua_active = 0;"); + bll_LuaEval(gL, "for _,f in pairs(_bllua_on_unload) do f() end"); + + lua_close(gL); + + BlHooksDeinit(); + BlFuncsDeinit(); + + BlPrintf(" BlockLua: Done Unloading"); + return true; +} + +bool __stdcall DllMain(HINSTANCE hinstance, DWORD reason, void* reserved) { + switch(reason) { + case DLL_PROCESS_ATTACH: return init(); + case DLL_PROCESS_DETACH: return deinit(); + default : return true; + } +} diff --git a/src/lua-env-safe.lua b/src/lua-env-safe.lua new file mode 100644 index 0000000..c64a30e --- /dev/null +++ b/src/lua-env-safe.lua @@ -0,0 +1,142 @@ +-- Sanitize the Lua environment to: +-- Prevent scripts from accessing files outside the game directory +-- Prevent usage of libraries other than + + +-- 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 + +-- Save banned global variables for wrapping with safe functions +local old_io = io +local old_require = require +local old_os = os +local old_debug = debug +local old_package = package + +-- Remove all global variables except a whitelist +local ok_names = tmap { + '_G', '_bllua_ts', '_bllua_on_unload', '_bllua_on_error', + 'string', 'table', 'math', 'coroutine', 'bit', + 'pairs', 'ipairs', 'next', 'unpack', 'select', + 'error', 'assert', 'pcall', 'xpcall', + 'type', 'tostring', 'tonumber', + 'loadstring', + 'getmetatable', 'setmetatable', + 'rawget', 'rawset', 'rawequal', 'rawlen', + 'module', '_VERSION', +} +local not_ok_names = {} +for n, _ in pairs(_G) do + if not ok_names[n] then + table.insert(not_ok_names, n) + end +end +for _, n in ipairs(not_ok_names) do + _G[n] = nil +end + +-- Sanitize file paths to point only to allowed files within the game directory +-- List of allowed directories for reading/writing +local allowed_dirs = tmap { + 'add-ons', 'base', 'config', 'saves', 'screenshots', 'shaders' +} +-- List of allowed directories for reading only +local allowed_dirs_readonly = tmap { + 'lualib' +} +-- List of disallowed file extensions - basically executable file extensions +-- Note that even without this protection, exploiting would still require somehow +-- getting a file within the allowed directories to autorun, +-- so this is just a precaution. +local disallowed_exts = tmap { + -- windows + 'bat','bin','cab','cmd','com','cpl','ex_','exe','gadget','inf','ins','inx','isu', + 'job','jse','lnk','msc','msi','msp','mst','paf','pif','ps1','reg','rgs','scr', + 'sct','shb','shs','u3p','vb','vbe','vbs','vbscript','ws','wsf','wsh', + -- linux + 'csh','ksh','out','run','sh', + -- mac/other + 'action','apk','app','command','ipa','osx','prg','workflow', +} +-- Arguments: file name (relative to game directory), boolean true if only reading +-- Return: clean file path if allowed (or nil if disallowed), +-- error string (or nil if allowed) +local function safe_path(fn, readonly) + fn = fn:gsub('\\', '/') + fn = fn:gsub('^ +', '') + fn = fn:gsub(' +$', '') + -- whitelist characters + local ic = fn:find('[^a-zA-Z0-9_%-/ %.]') + if ic then + return nil, 'Filename \''..fn..'\' contains invalid character \''.. + fn:sub(ic, ic)..'\' at position '..ic + end + -- disallow up-dirs, absolute paths, and relative paths + -- './' and '../' are possible in scripts, because they're processed into + -- absolute paths in util.lua before reaching here + if fn:find('^%.') or fn:find('%.%.') or fn:find(':') or fn:find('^/') then + return nil, 'Filename \''..fn..'\' contains invalid sequence' + end + -- allow only whitelisted dirs + local dir = fn:match('^([^/]+)/') + if (not dir) or ( + (not allowed_dirs[dir:lower()]) and + ((not readonly) or (not allowed_dirs_readonly[dir:lower()])) ) then + return nil, 'filename is in disallowed directory '..(dir or 'nil') + end + -- disallow blacklisted extensions or no extension + local ext = fn:match('%.([^/%.]+)$') + if (not ext) or (disallowed_exts[ext:lower()]) then + return nil, 'Filename \''..fn..'\' has disallowed extension \''.. + (ext or '')..'\'' + end + return fn, nil +end + +-- Wrap io.open with path sanitization +function _bllua_io_open(fn, md) + md = md or 'r' + local readonly = md=='r' or md=='rb' + local fns, err = safe_path(fn, readonly) + if fns then + return old_io.open(fns, md) + else + return nil, err + end +end +-- Allow io.type (works on file handles returned by io.open) +function _bllua_io_type(f) + return old_io.type(f) +end + +-- Wrap require with a blacklist for unsafe built-in modules +-- List of allowed packages to require +-- Note that util.lua wraps this and provides 'require', +-- only falling back here if the package is not found in user files +local disallowed_packages = tmap { + 'ffi', 'debug', 'package', 'io', 'os', + '_bllua_ts', +} +function _bllua_requiresecure(name) + if name:find('[^a-zA-Z0-9_%-%.]') or name:find('%.%.') or + name:find('^%.') or name:find('%.$') then + error('require: package name contains invalid character', 3) + elseif disallowed_packages[name] then + error('require: attempt to require disallowed module \''..name..'\'', 3) + else + -- todo: reimplement require to not use package.* stuff? + return old_require(name) + end +end +package = { + seeall = old_package.seeall, +} + +-- Provide limited debug +debug = { + traceback = old_debug.traceback, + getinfo = old_debug.getinfo, + getfilename = old_debug.getfilename, -- defined in lua.env.lua +} + +_bllua_ts.echo(' Executed bllua-env-safe.lua') diff --git a/src/lua-env.lua b/src/lua-env.lua new file mode 100644 index 0000000..f485ee2 --- /dev/null +++ b/src/lua-env.lua @@ -0,0 +1,40 @@ +-- Set up the Lua environment + +-- Point old require to modules/lua in game directory +package.path = 'modules\\lualib\\?.lua;modules\\lualib\\?\\init.lua;' +package.cpath = 'modules\\lualib\\?.dll;' + +-- Set up table of unload/cleanup callbacks +_bllua_on_unload = {} + +-- Utility for getting the current filename +function debug.getfilename(level) + if type(level) == 'number' then level = level+1 end + local info = debug.getinfo(level) + if not info then return nil end + local filename = info.source:match('^%-%-%[%[([^%]]+)%]%]') + return filename +end + +-- Called when pcall fails on a ts->lua call, used to print detailed error info +function _bllua_on_error(err) + err = err:match(': (.+)$') or err + local tracelines = {err} + local level = 2 + while true do + local info = debug.getinfo(level) + if not info then break end + local filename = debug.getfilename(level) or info.short_src + local funcname = info.name + if funcname=='dofile' then break end + table.insert(tracelines, string.format('%s:%s in function \'%s\'', + filename, + info.currentline==-1 and '' or info.currentline..':', + funcname + )) + level = level+1 + end + return table.concat(tracelines, '\n') +end + +_bllua_ts.echo(' Executed bllua-env.lua') diff --git a/src/luainterp.cpp b/src/luainterp.cpp new file mode 100644 index 0000000..86f22a6 --- /dev/null +++ b/src/luainterp.cpp @@ -0,0 +1,68 @@ + +// Handle errors with a Lua function, defined in lua-env.lua +int bll_error_handler(lua_State *L) { + lua_getfield(L, LUA_GLOBALSINDEX, "_bllua_on_error"); + if (!lua_isfunction(L, -1)) { + BlPrintf(" Lua error handler: _bllua_on_error not defined."); + lua_pop(L, 1); + return 1; + } + + // move function to before arg + int hpos = lua_gettop(L) - 1; + lua_insert(L, hpos); + + lua_pcall(L, 1, 1, 0); + return 1; +} +int bll_pcall(lua_State* L, int nargs, int nret) { + // calculate stack position for message handler + int hpos = lua_gettop(L) - nargs; + // push custom error message handler + lua_pushcfunction(L, bll_error_handler); + // move it before function and arguments + lua_insert(L, hpos); + // call lua_pcall function with custom handler + int ret = lua_pcall(L, nargs, nret, hpos); + // remove custom error message handler from stack + lua_remove(L, hpos); + return ret; +} + +// Display the last Lua error in the BL console +void bll_printError(lua_State* L, const char* operation, const char* item) { + //error_handler(L); + BlPrintf("\x03Lua error: %s", lua_tostring(L, -1)); + BlPrintf("\x03 (%s: %s)", operation, item); + lua_pop(L, 1); +} + +// Eval a string of Lua code +bool bll_LuaEval(lua_State* L, const char* str) { + if(luaL_loadbuffer(L, str, strlen(str), "input") || bll_pcall(L, 0, 1)) { + bll_printError(L, "eval", str); + return false; + } + return true; +} + +// Convert a Lua stack entry into a string for providing to TS +// 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]; +bool bll_toarg(lua_State* L, char* buf, int i, bool err) { + if(lua_isstring(L, i)) { + const char* str = lua_tostring(L, i); + if(strlen(str) >= BLL_ARG_MAX) { + if(err) luaL_error(L, "argument to TS is too long - max length is 8192"); + return true; + } else { + strcpy(buf, str); + return false; + } + } else { + if(err) luaL_error(L, "argument to TS must be a string"); + return true; + } +} diff --git a/src/lualibts.cpp b/src/lualibts.cpp new file mode 100644 index 0000000..ee90a47 --- /dev/null +++ b/src/lualibts.cpp @@ -0,0 +1,159 @@ +//run ../compile + +// TS -> Lua API + +// Call a TS function from Lua, push the result to Lua stack +int bll_TsCall(lua_State* L, const char* oname, const char* fname, int argc, int ofs) { + ADDR obj = (ADDR)NULL; + if(oname) { + obj = BlObject(oname); + 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)"); } + + char* argv[BLL_ARG_COUNT]; + for(int i=0; iTS object call: Too many arguments (Max is 19)"); + } + } else { + switch(argc) { + case 0: res = BlCall(fname); break; + case 1: res = BlCall(fname, argv[0]); break; + case 2: res = BlCall(fname, argv[0], argv[1]); break; + case 3: res = BlCall(fname, argv[0], argv[1], argv[2]); break; + case 4: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3]); break; + case 5: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4]); break; + case 6: res = BlCall(fname, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); 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)"); + } + } + + lua_pushstring(L, res); + + return 1; +} +// Lua lib function: ts.call +int bll_lua_tscall(lua_State* L) { + 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"); + + const char* fname = luaL_checkstring(L, 1); + + return bll_TsCall(L, NULL, fname, argc, 1); +} +// Lua lib function: ts.callobj +int bll_lua_tscallobj(lua_State* L) { + 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"); + + const char* oname = luaL_checkstring(L, 1); + const char* fname = luaL_checkstring(L, 2); + + return bll_TsCall(L, oname, fname, argc, 2); +} + +// Lua lib function: ts.getvar +int bll_lua_tsgetvar(lua_State* L) { + const char* vname = luaL_checkstring(L, 1); + + const char* var = BlGetVar(vname); + lua_pushstring(L, var); + return 1; +} + +// Lua lib function: ts.getfield +int bll_lua_tsgetfield(lua_State* L) { + const char* oname = luaL_checkstring(L, 1); + const char* vname = luaL_checkstring(L, 2); + ADDR obj = BlObject(oname); + if(!obj) { return luaL_error(L, "_bllua_ts.getfield: Object not found"); } + + const char* val = BlGetField(obj, vname, NULL); + lua_pushstring(L, val); + return 1; +} +// Lua lib function: ts.setfield +int bll_lua_tssetfield(lua_State* L) { + const char* oname = luaL_checkstring(L, 1); + const char* vname = luaL_checkstring(L, 2); + const char* val = luaL_checkstring(L, 3); + ADDR obj = BlObject(oname); + if(!obj) { return luaL_error(L, "_bllua_ts.setfield: Object not found"); } + + BlSetField(obj, vname, NULL, val); + return 0; +} + +// Lua lib function: ts.eval +int bll_lua_tseval(lua_State* L) { + const char* str = luaL_checkstring(L, 1); + const char* res = BlEval(str); + lua_pushstring(L, res); + return 1; +} + +// Lua lib function: ts.echo +// Print to BL console - used in Lua print implementation +int bll_lua_tsecho(lua_State* L) { + const char* str = luaL_checkstring(L, 1); + BlPrintf("%s", str); + return 0; +} + +const luaL_Reg bll_lua_reg[] = { + {"call" , bll_lua_tscall }, + {"callobj" , bll_lua_tscallobj }, + {"getvar" , bll_lua_tsgetvar }, + {"getfield", bll_lua_tsgetfield}, + {"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); +} diff --git a/src/ts-env.cs b/src/ts-env.cs new file mode 100644 index 0000000..cda3a2b --- /dev/null +++ b/src/ts-env.cs @@ -0,0 +1,26 @@ +// Built-in functions +// Eval'd after BLLua4 has loaded the Lua environment and API + +// Public Lua library for TS +function luacall(%func, %a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p) { + if($_bllua_active) + return _bllua_luacall(%func, %a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l,%m,%n,%o,%p); +} +function luaexec(%fn) { + if($_bllua_active) + return _bllua_luacall("_bllua_exec", %fn); +} +function luaeval(%code) { + if($_bllua_active) + return _bllua_luacall("_bllua_eval", %code); +} +function luaget(%name) { + if($_bllua_active) + return _bllua_luacall("_bllua_getvar", %name); +} +function luaset(%name, %val) { + if($_bllua_active) + _bllua_luacall("_bllua_setvar", %name, %val); +} + +echo(" Executed bllua-env.cs"); diff --git a/src/tsliblua.cpp b/src/tsliblua.cpp new file mode 100644 index 0000000..03fc03d --- /dev/null +++ b/src/tsliblua.cpp @@ -0,0 +1,25 @@ + +// Call a Lua function from TS, return true if success - result will be on Lua stack +bool bll_LuaCall(const char* fname, int argc, const char* argv[]) { + lua_getglobal(gL, fname); + for(int i=0; i " @ %text); + luacall("_bllua_smarteval", %text); + } else { + echo("Lua: not loaded"); + } + ConsoleEntry.setValue(""); + } else { + %textT = trim(%text); + if(strLen(%textT)>0) { + %lastChar = getSubStr(%textT, strLen(%textT)-1, 1); + if(%lastChar!$=";" && %lastChar!$="}") { + %text = "echo(" @ %text @ ");"; + ConsoleEntry.setValue(%text); + } + } + parent::eval(); + } + } +}; +activatePackage(_bllua_smartEval); + +package _bllua_objectDeletionHook { + // Hook object deletion to clean up its lua data + function SimObject::onRemove(%obj) { + // note: no parent function exists by default, + // and this is loaded before any addons + //parent::onRemove(%obj); + if($_bllua_active) luacall("_bllua_objectDeleted", %obj); + } +}; +activatePackage(_bllua_objectDeletionHook); + +echo(" Executed libbl-support.cs"); diff --git a/src/util/libbl-types.lua b/src/util/libbl-types.lua new file mode 100644 index 0000000..28502e1 --- /dev/null +++ b/src/util/libbl-types.lua @@ -0,0 +1,3706 @@ +-- Pre-defined types for builtin functions and variables +-- Most type conversion is automatic; only need to discern objects and booleans, +-- since both are represented by plain numbers in TS. + +-- Class hierarchy, adapted from https://notabug.org/Queuenard/blockland-DLL-tools/src/master/class_hierarchy +bl.class('SimObject') + bl.class('ScriptObject', 'SimObject') + bl.class('SimSet', 'SimObject') + bl.class('SimGroup', 'SimSet') + bl.class('GuiControl', 'SimGroup') + bl.class('GuiTextCtrl' , 'GuiControl') + bl.class('GuiSwatchCtrl' , 'GuiControl') + bl.class('GuiButtonBaseCtrl' , 'GuiControl') + bl.class('GuiArrayCtrl' , 'GuiControl') + bl.class('GuiScrollCtrl' , 'GuiControl') + bl.class('GuiMouseEventCtrl' , 'GuiControl') + bl.class('GuiProgressCtrl' , 'GuiControl') + bl.class('GuiSliderCtrl' , 'GuiControl') + bl.class('GuiConsoleTextCtrl' , 'GuiControl') + bl.class('GuiTSCtrl' , 'GuiControl') + bl.class('GuiObjectView', 'GuiTSCtrl') + bl.class('GameTSCtrl' , 'GuiTSCtrl') + bl.class('EditTSCtrl' , 'GuiTSCtrl') + bl.class('GuiPlayerView', 'GuiTSCtrl') + bl.class('GuiShapeNameHud' , 'GuiControl') + bl.class('GuiHealthBarHud' , 'GuiControl') + bl.class('GuiGraphCtrl' , 'GuiControl') + bl.class('GuiInspector' , 'GuiControl') + bl.class('GuiChunkedBitmapCtrl', 'GuiControl') + bl.class('GuiInputCtrl' , 'GuiControl') + bl.class('GuiNoMouseCtrl' , 'GuiControl') + bl.class('GuiBitmapBorderCtrl' , 'GuiControl') + bl.class('GuiBackgroundCtrl' , 'GuiControl') + bl.class('GuiEditorRuler' , 'GuiControl') + bl.class('GuiClockHud' , 'GuiControl') + bl.class('GuiEditCtrl' , 'GuiControl') + bl.class('GuiFilterCtrl' , 'GuiControl') + bl.class('GuiFrameSetCtrl' , 'GuiControl') + bl.class('GuiMenuBar' , 'GuiControl') + bl.class('GuiMessageVectorCtrl', 'GuiControl') + bl.class('GuiBitmapCtrl' , 'GuiControl') + bl.class('GuiCrossHairHud', 'GuiBitmapCtrl') + bl.class('ScriptGroup', 'SimGroup') + bl.class('NetConnection', 'SimGroup') + bl.class('GameConnection', 'NetConnection') + bl.class('Path', 'SimGroup') + bl.class('TCPObject', 'SimObject') + bl.class('SOCKObject', 'TCPObject') + bl.class('HTTPObject', 'TCPObject') + bl.class('SimDataBlock', 'SimObject') + bl.class('AudioEnvironment' , 'SimDataBlock') + bl.class('AudioSampleEnvironment', 'SimDataBlock') + bl.class('AudioDescription' , 'SimDataBlock') + bl.class('GameBaseData' , 'SimDataBlock') + bl.class('ShapeBaseData' , 'GameBaseData') + bl.class('CameraData' , 'ShapeBaseData') + bl.class('ItemData' , 'ShapeBaseData') + bl.class('MissionMarkerData', 'ShapeBaseData') + bl.class('PathCameraData' , 'ShapeBaseData') + bl.class('PlayerData' , 'ShapeBaseData') + bl.class('StaticShapeData' , 'ShapeBaseData') + bl.class('VehicleData' , 'ShapeBaseData') + bl.class('FlyingVehicleData' , 'VehicleData') + bl.class('WheeledVehicleData', 'VehicleData') + bl.class('DebrisData' , 'GameBaseData') + bl.class('ProjectileData' , 'GameBaseData') + bl.class('ShapeBaseImageData' , 'GameBaseData') + bl.class('TriggerData' , 'GameBaseData') + bl.class('ExplosionData' , 'GameBaseData') + bl.class('fxLightData' , 'GameBaseData') + bl.class('LightningData' , 'GameBaseData') + bl.class('ParticleEmitterNodeData', 'GameBaseData') + bl.class('SplashData' , 'GameBaseData') + bl.class('fxDTSBrickData' , 'GameBaseData') + bl.class('ParticleEmitterData' , 'GameBaseData') + bl.class('WheeledVehicleTire' , 'SimDataBlock') + bl.class('WheeledVehicleSpring' , 'SimDataBlock') + bl.class('TSShapeConstructor' , 'SimDataBlock') + bl.class('AudioProfile' , 'SimDataBlock') + bl.class('ParticleData' , 'SimDataBlock') + bl.class('MaterialPropertyMap', 'SimObject') + bl.class('NetObject', 'SimObject') + bl.class('SceneObject', 'NetObject') + bl.class('GameBase', 'SceneObject') + bl.class('ShapeBase', 'GameBase') + bl.class('MissionMarker', 'ShapeBase') + bl.class('SpawnSphere' , 'MissionMarker') + bl.class('VehicleSpawnMarker', 'MissionMarker') + bl.class('Waypoint' , 'MissionMarker') + bl.class('StaticShape' , 'ShapeBase') + bl.class('ScopeAlwaysShape', 'StaticShape') + bl.class('Player' , 'ShapeBase') + bl.class('AIPlayer', 'Player') + bl.class('Camera' , 'ShapeBase') + bl.class('Item' , 'ShapeBase') + bl.class('PathCamera' , 'ShapeBase') + bl.class('Vehicle' , 'ShapeBase') + bl.class('FlyingVehicle' , 'Vehicle') + bl.class('WheeledVehicle', 'Vehicle') + bl.class('Explosion' , 'GameBase') + bl.class('Splash' , 'GameBase') + bl.class('Debris' , 'GameBase') + bl.class('Projectile' , 'GameBase') + bl.class('Trigger' , 'GameBase') + bl.class('fxLight' , 'GameBase') + bl.class('Lightning' , 'GameBase') + bl.class('ParticleEmitterNode', 'GameBase') + bl.class('ParticleEmitter' , 'GameBase') + bl.class('Precipitation' , 'GameBase') + bl.class('TSStatic' , 'SceneObject') + bl.class('VehicleBlocker', 'SceneObject') + bl.class('Marker' , 'SceneObject') + bl.class('AudioEmitter' , 'SceneObject') + bl.class('PhysicalZone' , 'SceneObject') + bl.class('fxDayCycle' , 'SceneObject') + bl.class('fxDTSBrick' , 'SceneObject') + bl.class('fxPlane' , 'SceneObject') + bl.class('fxSunLight' , 'SceneObject') + bl.class('Sky' , 'SceneObject') + bl.class('SceneRoot' , 'SceneObject') + bl.class('Sun', 'NetObject') + bl.class('GuiCursor', 'SimObject') + bl.class('ConsoleLogger' , 'SimObject') + bl.class('QuotaObject' , 'SimObject') + bl.class('FileObject' , 'SimObject') + bl.class('BanList' , 'SimObject') + bl.class('GuiControlProfile', 'SimObject') + bl.class('MessageVector' , 'SimObject') + bl.class('ActionMap' , 'SimObject') + +-- Auto-generated from game scripts +bl.type('ActionMap::blockBind:1', 'object') +bl.type('ActionMap::copyBind:1', 'object') +bl.type('addBanGui::ban:1', 'object') +bl.type('addBanGui::clickForever:1', 'object') +bl.type('addBanGui::onSleep:1', 'object') +bl.type('addBanGui::onWake:1', 'object') +bl.type('addBanGui::setVictim:1', 'object') +bl.type('adminGui::ban:1', 'object') +bl.type('adminGui::ClickClearBricks:1', 'object') +bl.type('adminGui::ClickGameMode:1', 'object') +bl.type('adminGui::ClickServerSettings:1', 'object') +bl.type('adminGui::kick:1', 'object') +bl.type('adminGui::onWake:1', 'object') +bl.type('adminGui::openEnvGui:1', 'object') +bl.type('adminGui::sortList:1', 'object') +bl.type('adminGui::sortNumList:1', 'object') +bl.type('adminGui::spy:1', 'object') +bl.type('AdminLoginGui::onSleep:1', 'object') +bl.type('AdminLoginGui::onWake:1', 'object') +bl.type('authTCPobj_Client::onConnected:1', 'object') +bl.type('authTCPobj_Client::onConnectFailed:1', 'object') +bl.type('authTCPobj_Client::onDisconnect:1', 'object') +bl.type('authTCPobj_Client::onDNSFailed:1', 'object') +bl.type('authTCPobj_Client::onLine:1', 'object') +bl.type('AvatarGui::ClickFav:1', 'object') +bl.type('AvatarGui::clickSetFavs:1', 'object') +bl.type('AvatarGui::ClickX:1', 'object') +bl.type('AvatarGui::onSleep:1', 'object') +bl.type('AvatarGui::onWake:1', 'object') +bl.type('AvatarGui::updateFavButtons:1', 'object') +bl.type('BottomPrintText::onResize:1', 'object') +bl.type('BrickManGui::clearAllBricks:1', 'object') +bl.type('BrickManGui::clearBrickGroup:1', 'object') +bl.type('BrickManGui::clickBan:1', 'object') +bl.type('BrickManGui::clickClear:1', 'object') +bl.type('BrickManGui::clickClearAll:1', 'object') +bl.type('BrickManGui::clickHilight:1', 'object') +bl.type('BrickManGui::onSleep:1', 'object') +bl.type('BrickManGui::onWake:1', 'object') +bl.type('BrickManGui::sortList:1', 'object') +bl.type('BrickManGui::sortNumList:1', 'object') +bl.type('BrickSelectorDlg::onSleep:1', 'object') +bl.type('BrickSelectorDlg::onWake:1', 'object') +bl.type('BrickSelectorDlg::updateFavButtons:1', 'object') +bl.type('BSD_category::onRemove:1', 'object') +bl.type('BuildMacroSO::compress:1', 'object') +bl.type('BuildMacroSO::deleteEvent:1', 'object') +bl.type('BuildMacroSO::dump:1', 'object') +bl.type('BuildMacroSO::PlayBack:1', 'object') +bl.type('BuildMacroSO::PlayEvent:1', 'object') +bl.type('BuildMacroSO::pushEvent:1', 'object') +bl.type('CenterPrintText::onResize:1', 'object') +bl.type('clientIsValidAddOn', 'boolean') +bl.type('clientIsValidMusicFilename', 'boolean') +bl.type('ClientVerifyAddOnScripts', 'boolean') +bl.type('colorGui::clickCancel:1', 'object') +bl.type('colorGui::doCallbacks:1', 'object') +bl.type('colorGui::done:1', 'object') +bl.type('colorGui::onSleep:1', 'object') +bl.type('colorGui::onWake:1', 'object') +bl.type('colorGui::popUp:1', 'object') +bl.type('colorGui::setMode:1', 'object') +bl.type('colorGui::update:1', 'object') +bl.type('colorMatch', 'boolean') +bl.type('ColorSetGui::AddColor:1', 'object') +bl.type('ColorSetGui::defaults:1', 'object') +bl.type('ColorSetGui::deleteColor:1', 'object') +bl.type('ColorSetGui::Display:1', 'object') +bl.type('ColorSetGui::load:1', 'object') +bl.type('ColorSetGui::onSleep:1', 'object') +bl.type('ColorSetGui::onWake:1', 'object') +bl.type('ColorSetGui::save:1', 'object') +bl.type('ColorSetGui::selectColor:1', 'object') +bl.type('ColorSetGui::setMode:1', 'object') +bl.type('ColorSetGui::update:1', 'object') +bl.type('connectingGui::cancel:1', 'object') +bl.type('connectingGui::onWake:1', 'object') +bl.type('ConsoleEntry::eval:1', 'object') +bl.type('CreateMiniGameGui::clickColorList:1', 'object') +bl.type('CreateMiniGameGui::ClickCreate:1', 'object') +bl.type('CreateMiniGameGui::clickEnd:1', 'object') +bl.type('CreateMiniGameGui::ClickFav:1', 'object') +bl.type('CreateMiniGameGui::clickReset:1', 'object') +bl.type('CreateMiniGameGui::clickSetFavs:1', 'object') +bl.type('CreateMiniGameGui::dumpColorList:1', 'object') +bl.type('CreateMiniGameGui::end:1', 'object') +bl.type('CreateMiniGameGui::LoadDataBlocks:1', 'object') +bl.type('CreateMiniGameGui::onSleep:1', 'object') +bl.type('CreateMiniGameGui::onWake:1', 'object') +bl.type('CreateMiniGameGui::Refresh:1', 'object') +bl.type('CreateMiniGameGui::send:1', 'object') +bl.type('CustomGameGui::AddAdvancedGuiElement:1', 'object') +bl.type('CustomGameGui::clickAddOnItem:1', 'object') +bl.type('CustomGameGui::clickAddOns:1', 'object') +bl.type('CustomGameGui::clickAdvanced:1', 'object') +bl.type('CustomGameGui::clickAdvancedItem:1', 'object') +bl.type('CustomGameGui::clickAll:1', 'object') +bl.type('CustomGameGui::ClickBack:1', 'object') +bl.type('CustomGameGui::clickDefault:1', 'object') +bl.type('CustomGameGui::clickMusic:1', 'object') +bl.type('CustomGameGui::clickMusicItem:1', 'object') +bl.type('CustomGameGui::clickNone:1', 'object') +bl.type('CustomGameGui::ClickSelect:1', 'object') +bl.type('CustomGameGui::CopyGuiVarsToPrefs:1', 'object') +bl.type('CustomGameGui::CopyPrefsToGuiVars:1', 'object') +bl.type('CustomGameGui::CreateAddOnListGui:1', 'object') +bl.type('CustomGameGui::CreateAdvancedGui:1', 'object') +bl.type('CustomGameGui::CreateMusicListGui:1', 'object') +bl.type('CustomGameGui::hideAllTabs:1', 'object') +bl.type('CustomGameGui::onRender:1', 'object') +bl.type('CustomGameGui::onWake:1', 'object') +bl.type('CustomGameGui::populateAddOnList:1', 'object') +bl.type('CustomGameGui::populateMusicList:1', 'object') +bl.type('CustomGameGui::ScaleText:1', 'object') +bl.type('CustomGameGui::setDefaultAddOns:1', 'object') +bl.type('CustomGameGui::setDefaultMusic:1', 'object') +bl.type('defaultControlsGui::apply:1', 'object') +bl.type('defaultControlsGui::clickClose:1', 'object') +bl.type('defaultControlsGui::onSleep:1', 'object') +bl.type('defaultControlsGui::onWake:1', 'object') +bl.type('EnvGui::apply:1', 'object') +bl.type('EnvGui::cancel:1', 'object') +bl.type('EnvGui::clickAmbientLightColor:1', 'object') +bl.type('EnvGui::ClickDayCycleMenu:1', 'object') +bl.type('EnvGui::ClickDefaults:1', 'object') +bl.type('EnvGui::clickDirectLightColor:1', 'object') +bl.type('EnvGui::clickFogColor:1', 'object') +bl.type('EnvGui::ClickGroundButton:1', 'object') +bl.type('EnvGui::clickGroundColor:1', 'object') +bl.type('EnvGui::clickRandom:1', 'object') +bl.type('EnvGui::clickShadowColor:1', 'object') +bl.type('EnvGui::ClickSkyButton:1', 'object') +bl.type('EnvGui::clickSkyColor:1', 'object') +bl.type('EnvGui::ClickSunFlareBottomButton:1', 'object') +bl.type('EnvGui::clickSunFlareColor:1', 'object') +bl.type('EnvGui::ClickSunFlareTopButton:1', 'object') +bl.type('EnvGui::clickUnderWaterColor:1', 'object') +bl.type('EnvGui::clickVignetteColor:1', 'object') +bl.type('EnvGui::clickVignetteMultiply:1', 'object') +bl.type('EnvGui::ClickWaterButton:1', 'object') +bl.type('EnvGui::clickWaterColor:1', 'object') +bl.type('EnvGui::CreateIconMenu:1', 'object') +bl.type('EnvGui::hideAllMenus:1', 'object') +bl.type('EnvGui::onWake:1', 'object') +bl.type('EnvGui::setGround:1', 'object') +bl.type('EnvGui::setPane:1', 'object') +bl.type('EnvGui::setSky:1', 'object') +bl.type('EnvGui::setSunFlareBottom:1', 'object') +bl.type('EnvGui::setSunFlareTop:1', 'object') +bl.type('EnvGui::setWater:1', 'object') +bl.type('EnvGui::updateDayCycleEnabled:1', 'object') +bl.type('EnvGui::updateDayLength:1', 'object') +bl.type('EnvGui::updateVar:1', 'object') +bl.type('EnvGui_Window::onWindowFocus:1', 'object') +bl.type('escapeMenu::clickAdmin:1', 'object') +bl.type('escapeMenu::clickLoadBricks:1', 'object') +bl.type('escapeMenu::clickMinigames:1', 'object') +bl.type('escapeMenu::clickSaveBricks:1', 'object') +bl.type('escapeMenu::onWake:1', 'object') +bl.type('escapeMenu::toggle:1', 'object') +bl.type('filtersGui::onSleep:1', 'object') +bl.type('filtersGui::onWake:1', 'object') +bl.type('GameConnection::initialControlSet:1', 'object') +bl.type('GameConnection::onConnectionAccepted:1', 'object') +bl.type('GameConnection::onConnectionDropped:1', 'object') +bl.type('GameConnection::onConnectionError:1', 'object') +bl.type('GameConnection::onConnectionTimedOut:1', 'object') +bl.type('GameConnection::onConnectRequestRejected:1', 'object') +bl.type('GameConnection::onConnectRequestTimedOut:1', 'object') +bl.type('GameConnection::prepDemoPlayback:1', 'object') +bl.type('GameConnection::prepDemoRecord:1', 'object') +bl.type('GameConnection::setLagIcon:1', 'object') +bl.type('GameModeGui::ClickBack:1', 'object') +bl.type('GameModeGui::ClickGameMode:1', 'object') +bl.type('GameModeGui::ClickSelect:1', 'object') +bl.type('GameModeGui::CreateListItems:1', 'object') +bl.type('GameModeGui::DumpGameModes:1', 'object') +bl.type('GameModeGui::GetMissingAddOns:1', 'object') +bl.type('GameModeGui::onRender:1', 'object') +bl.type('GameModeGui::onWake:1', 'object') +bl.type('GameModeGui::PopulateGameModeList:1', 'object') +bl.type('GameModeGui::scrollToGameMode:1', 'object') +bl.type('GuiCanvas::checkCursor:1', 'object') +bl.type('GuiCanvas::checkTabFocus:1', 'object') +bl.type('GuiCanvas::popDialog:1', 'object') +bl.type('GuiCanvas::popLayer:1', 'object') +bl.type('GuiCanvas::pushDialog:1', 'object') +bl.type('GuiCanvas::setContent:1', 'object') +bl.type('GuiControl::getHelpPage:1', 'object') +bl.type('GuiControl::ScaleText:1', 'object') +bl.type('GuiMLTextCtrl::onURL:1', 'object') +bl.type('handleAddClientToTeam', 'boolean') +bl.type('handleRemoveClientFromTeam', 'boolean') +bl.type('handleSetTeamCaptain', 'boolean') +bl.type('hatTCPObj::onConnected:1', 'object') +bl.type('hatTCPObj::onConnectFailed:1', 'object') +bl.type('hatTCPObj::onDisconnect:1', 'object') +bl.type('hatTCPObj::onDNSFailed:1', 'object') +bl.type('hatTCPObj::onLine:1', 'object') +bl.type('haveTools', 'boolean') +bl.type('HelpDlg::onWake:1', 'object') +bl.type('HelpFileList::onSelect:1', 'object') +bl.type('isListenServer', 'boolean') +bl.type('isValidDecal', 'boolean') +bl.type('isValidFileName', 'boolean') +bl.type('joinMiniGameGui::ClickCreate:1', 'object') +bl.type('joinMiniGameGui::ClickJoin:1', 'object') +bl.type('joinMiniGameGui::ClickLeave:1', 'object') +bl.type('joinMiniGameGui::clickList:1', 'object') +bl.type('joinMiniGameGui::end:1', 'object') +bl.type('joinMiniGameGui::onSleep:1', 'object') +bl.type('joinMiniGameGui::onWake:1', 'object') +bl.type('joinMiniGameGui::sortList:1', 'object') +bl.type('joinMiniGameGui::sortNumList:1', 'object') +bl.type('JoinServerGuiBS::cancel:1', 'object') +bl.type('JoinServerGuiBS::ClickBack:1', 'object') +bl.type('JoinServerGuiBS::exit:1', 'object') +bl.type('JoinServerGuiBS::join:1', 'object') +bl.type('JoinServerGuiBS::onWake:1', 'object') +bl.type('JoinServerGuiBS::queryLan:1', 'object') +bl.type('JoinServerGuiBS::queryWebMaster:1', 'object') +bl.type('JoinServerGuiBS::update:1', 'object') +bl.type('JoinServerPassGui::cancel:1', 'object') +bl.type('JoinServerPassGui::enterPass:1', 'object') +bl.type('LoadBricksGui::ClickOwnership:1', 'object') +bl.type('LoadBricksGui::onSleep:1', 'object') +bl.type('LoadBricksGui::onWake:1', 'object') +bl.type('LoadingGui::onAdd:1', 'object') +bl.type('LoadingGui::onSleep:1', 'object') +bl.type('LoadingGui::onWake:1', 'object') +bl.type('MainMenuGui::buildScreenshotList:1', 'object') +bl.type('MainMenuGui::clickJoinBS:1', 'object') +bl.type('MainMenuGui::clickNameButton:1', 'object') +bl.type('MainMenuGui::clickOptions:1', 'object') +bl.type('MainMenuGui::clickPlayer:1', 'object') +bl.type('MainMenuGui::clickStart:1', 'object') +bl.type('MainMenuGui::clickSteam:1', 'object') +bl.type('MainMenuGui::clickUnlock:1', 'object') +bl.type('MainMenuGui::hideButtons:1', 'object') +bl.type('MainMenuGui::onRender:1', 'object') +bl.type('MainMenuGui::onSleep:1', 'object') +bl.type('MainMenuGui::onWake:1', 'object') +bl.type('MainMenuGui::PlayMusic:1', 'object') +bl.type('MainMenuGui::retryAuth:1', 'object') +bl.type('MainMenuGui::showButtons:1', 'object') +bl.type('ManualJoin::onWake:1', 'object') +bl.type('MessageBoxOKCancelDlg::onSleep:1', 'object') +bl.type('MessageBoxOKDlg::onSleep:1', 'object') +bl.type('MessageBoxYesNoDlg::onSleep:1', 'object') +bl.type('MiniGameInviteGui::ClickAccept:1', 'object') +bl.type('MiniGameInviteGui::ClickIgnore:1', 'object') +bl.type('MiniGameInviteGui::ClickReject:1', 'object') +bl.type('MiniGameInviteGui::Ignore:1', 'object') +bl.type('MiniGameInviteGui::onSleep:1', 'object') +bl.type('MiniGameInviteGui::onWake:1', 'object') +bl.type('MM_AuthBar::blinkFail:1', 'object') +bl.type('MM_AuthBar::blinkSuccess:1', 'object') +bl.type('mm_Fade::onDone:1', 'object') +bl.type('mm_Fade::OnWait:1', 'object') +bl.type('NewChatSO::addLine:1', 'object') +bl.type('NewChatSO::displayLatest:1', 'object') +bl.type('NewChatSO::displayPage:1', 'object') +bl.type('NewChatSO::dumpLines:1', 'object') +bl.type('NewChatSO::pageDown:1', 'object') +bl.type('NewChatSO::pageUp:1', 'object') +bl.type('NewChatSO::update:1', 'object') +bl.type('newMessageHud::onSleep:1', 'object') +bl.type('newMessageHud::onWake:1', 'object') +bl.type('newMessageHud::open:1', 'object') +bl.type('newMessageHud::updatePosition:1', 'object') +bl.type('newMessageHud::updateTypePosition:1', 'object') +bl.type('NewPlayerListGui::ClearInYourMiniGame:1', 'object') +bl.type('NewPlayerListGui::clickList:1', 'object') +bl.type('NewPlayerListGui::ClickMiniGameInvite:1', 'object') +bl.type('NewPlayerListGui::ClickMiniGameRemove:1', 'object') +bl.type('NewPlayerListGui::ClickTrustDemoteBUILD:1', 'object') +bl.type('NewPlayerListGui::ClickTrustDemoteNONE:1', 'object') +bl.type('NewPlayerListGui::ClickTrustInviteBuild:1', 'object') +bl.type('NewPlayerListGui::ClickTrustInviteFull:1', 'object') +bl.type('NewPlayerListGui::ClickUnIgnore:1', 'object') +bl.type('NewPlayerListGui::getIgnoringBL_ID:1', 'object') +bl.type('NewPlayerListGui::onSleep:1', 'object') +bl.type('NewPlayerListGui::onWake:1', 'object') +bl.type('NewPlayerListGui::setIgnoring:1', 'object') +bl.type('NewPlayerListGui::setIgnoringBL_ID:1', 'object') +bl.type('NewPlayerListGui::showTrustMessage:1', 'object') +bl.type('NewPlayerListGui::sortList:1', 'object') +bl.type('NewPlayerListGui::sortNumList:1', 'object') +bl.type('NewPlayerListGui::toggle:1', 'object') +bl.type('NewPlayerListGui::update:1', 'object') +bl.type('NewPlayerListGui::updateInYourMiniGame:1', 'object') +bl.type('NewPlayerListGui::updateScore:1', 'object') +bl.type('NewPlayerListGui::updateTrust:1', 'object') +bl.type('NewPlayerListGui::UpdateWindowTitle:1', 'object') +bl.type('NMH_Type::send:1', 'object') +bl.type('NMH_Type::type:1', 'object') +bl.type('noHudGui::onRender:1', 'object') +bl.type('noHudGui::onSleep:1', 'object') +bl.type('noHudGui::onWake:1', 'object') +bl.type('OptAudioDriverList::onSelect:1', 'object') +bl.type('OptGraphicsBorderlessToggle::onAction:1', 'object') +bl.type('OptGraphicsBPPMenu::init:1', 'object') +bl.type('OptGraphicsDriverMenu::onSelect:1', 'object') +bl.type('OptGraphicsFullscreenToggle::onAction:1', 'object') +bl.type('OptGraphicsResolutionMenu::init:1', 'object') +bl.type('OptGraphicsResolutionMenu::onSelect:1', 'object') +bl.type('optionsDlg::applyGraphics:1', 'object') +bl.type('optionsDlg::clearAllBinds:1', 'object') +bl.type('optionsDlg::clickLatencyOption:1', 'object') +bl.type('optionsDlg::onSleep:1', 'object') +bl.type('optionsDlg::onWake:1', 'object') +bl.type('optionsDlg::RemapAll:1', 'object') +bl.type('optionsDlg::RemapNext:1', 'object') +bl.type('optionsDlg::setBrickFXQuality:1', 'object') +bl.type('optionsDlg::setDefaultBinds:1', 'object') +bl.type('optionsDlg::setLightingQuality:1', 'object') +bl.type('optionsDlg::setPane:1', 'object') +bl.type('optionsDlg::setParticleQuality:1', 'object') +bl.type('optionsDlg::setPhysicsQuality:1', 'object') +bl.type('optionsDlg::setShaderQuality:1', 'object') +bl.type('optionsDlg::setTextureQuality:1', 'object') +bl.type('optionsDlg::UpdateAvailableShaders:1', 'object') +bl.type('optionsDlg::updateDrawDistanceBlocker:1', 'object') +bl.type('optionsDlg::updateFOV:1', 'object') +bl.type('optionsDlg::updateMaxViewDistance:1', 'object') +bl.type('optionsDlg::updateTempBrickBlockers:1', 'object') +bl.type('OptRemapInputCtrl::onInputEvent:1', 'object') +bl.type('OptRemapList::doRemap:1', 'object') +bl.type('OptRemapList::fillList:1', 'object') +bl.type('OptScreenshotMenu::init:1', 'object') +bl.type('PlayGui::createInvHUD:1', 'object') +bl.type('PlayGui::createToolHUD:1', 'object') +bl.type('PlayGui::FadePaintRow:1', 'object') +bl.type('PlayGui::FadePaintRows:1', 'object') +bl.type('PlayGui::hideBrickBox:1', 'object') +bl.type('PlayGui::hidePaintBox:1', 'object') +bl.type('PlayGui::hideToolBox:1', 'object') +bl.type('PlayGui::killInvHud:1', 'object') +bl.type('PlayGui::killpaint:1', 'object') +bl.type('PlayGui::killToolHud:1', 'object') +bl.type('PlayGui::loadPaint:1', 'object') +bl.type('PlayGui::onRender:1', 'object') +bl.type('PlayGui::onSleep:1', 'object') +bl.type('PlayGui::onWake:1', 'object') +bl.type('PlayGui::UnFadePaintRow:1', 'object') +bl.type('PlayGui::updatePaintActive:1', 'object') +bl.type('PrintSelectorDlg::onSleep:1', 'object') +bl.type('PrintSelectorDlg::onWake:1', 'object') +bl.type('queryMasterTCPObj::onConnected:1', 'object') +bl.type('queryMasterTCPObj::onConnectFailed:1', 'object') +bl.type('queryMasterTCPObj::onDisconnect:1', 'object') +bl.type('queryMasterTCPObj::onDNSFailed:1', 'object') +bl.type('queryMasterTCPObj::onLine:1', 'object') +bl.type('recordingsDlg::onWake:1', 'object') +bl.type('regNameGui::onClose:1', 'object') +bl.type('regNameGui::onSleep:1', 'object') +bl.type('regNameGui::onType:1', 'object') +bl.type('regNameGui::onWake:1', 'object') +bl.type('regNameGui::register:1', 'object') +bl.type('regName_tcpObj::onConnected:1', 'object') +bl.type('regName_tcpObj::onConnectFailed:1', 'object') +bl.type('regName_tcpObj::onDisconnect:1', 'object') +bl.type('regName_tcpObj::onDNSFailed:1', 'object') +bl.type('regName_tcpObj::onLine:1', 'object') +bl.type('saveBricksGui::onSleep:1', 'object') +bl.type('saveBricksGui::onWake:1', 'object') +bl.type('SavingGui::onRender:1', 'object') +bl.type('SavingGui::onWake:1', 'object') +bl.type('SavingGui::save:1', 'object') +bl.type('selectBLIDGui::onSleep:1', 'object') +bl.type('selectBLIDGui::onWake:1', 'object') +bl.type('selectBLIDGui::select:1', 'object') +bl.type('SelectNetworkGui::onSleep:1', 'object') +bl.type('SelectNetworkGui::onWake:1', 'object') +bl.type('ServerSettingsGui::ApplyVariablesToGui:1', 'object') +bl.type('ServerSettingsGui::ClickBack:1', 'object') +bl.type('ServerSettingsGui::clickInternet:1', 'object') +bl.type('ServerSettingsGui::clickLAN:1', 'object') +bl.type('ServerSettingsGui::clickLaunchGame:1', 'object') +bl.type('ServerSettingsGui::clickSinglePlayer:1', 'object') +bl.type('ServerSettingsGui::copyVariablesToPrefs:1', 'object') +bl.type('ServerSettingsGui::getVariablesFromFile:1', 'object') +bl.type('ServerSettingsGui::getVariablesFromGui:1', 'object') +bl.type('ServerSettingsGui::onRender:1', 'object') +bl.type('ServerSettingsGui::onWake:1', 'object') +bl.type('ServerSO::Display:1', 'object') +bl.type('ServerSO::serialize:1', 'object') +bl.type('setJoinIP_tcpObj::onConnected:1', 'object') +bl.type('setJoinIP_tcpObj::onConnectFailed:1', 'object') +bl.type('setJoinIP_tcpObj::onDisconnect:1', 'object') +bl.type('setJoinIP_tcpObj::onDNSFailed:1', 'object') +bl.type('setJoinIP_tcpObj::onLine:1', 'object') +bl.type('setScrollMode', 'boolean') +bl.type('SimGroup::CLIENTaddNTName:1', 'object') +bl.type('SimGroup::CLIENTDumpNTNames:1', 'object') +bl.type('SimGroup::CLIENTremoveNTName:1', 'object') +bl.type('SO_ClientTeam::addMember:1', 'object') +bl.type('SO_ClientTeam::removeMember', 'boolean') +bl.type('SO_ClientTeam::removeMember:1', 'object') +bl.type('SO_ClientTeam::setCaptain:1', 'object') +bl.type('SO_ClientTeamManager::addTeam', 'boolean') +bl.type('SO_ClientTeamManager::addTeam:1', 'object') +bl.type('SO_ClientTeamManager::dumpTeams:1', 'object') +bl.type('SO_ClientTeamManager::findTeamByID:1', 'object') +bl.type('SO_ClientTeamManager::removeTeam', 'boolean') +bl.type('SO_ClientTeamManager::removeTeam:1', 'object') +bl.type('SO_ClientTeamManager::setTeamName:1', 'object') +bl.type('SteamGreenLightGui::ClickBack:1', 'object') +bl.type('SteamGreenLightGui::clickForward:1', 'object') +bl.type('SteamGreenLightGui::onRender:1', 'object') +bl.type('SteamGreenLightGui::onWake:1', 'object') +bl.type('TrustInviteGui::ClickAccept:1', 'object') +bl.type('TrustInviteGui::ClickIgnore:1', 'object') +bl.type('TrustInviteGui::ClickReject:1', 'object') +bl.type('TrustInviteGui::Ignore:1', 'object') +bl.type('unBanGui::clickUnBan:1', 'object') +bl.type('unBanGui::onSleep:1', 'object') +bl.type('unBanGui::onWake:1', 'object') +bl.type('unBanGui::sortList:1', 'object') +bl.type('unBanGui::sortNumList:1', 'object') +bl.type('unBanGui::unBan:1', 'object') +bl.type('WhoTalkSO::addID:1', 'object') +bl.type('WhoTalkSO::Display:1', 'object') +bl.type('WhoTalkSO::HasID', 'boolean') +bl.type('WhoTalkSO::HasID:1', 'object') +bl.type('WhoTalkSO::removeID:1', 'object') +bl.type('wrenchDlg::LoadDataBlocks:1', 'object') +bl.type('wrenchDlg::onSleep:1', 'object') +bl.type('wrenchDlg::onWake:1', 'object') +bl.type('wrenchDlg::send:1', 'object') +bl.type('wrenchEventsDlg::clear:1', 'object') +bl.type('wrenchEventsDlg::closeColorMenu:1', 'object') +bl.type('wrenchEventsDlg::CreateColorMenu:1', 'object') +bl.type('wrenchEventsDlg::CreateNamedBrickList:1', 'object') +bl.type('wrenchEventsDlg::createOutputList:1', 'object') +bl.type('wrenchEventsDlg::createOutputParameters:1', 'object') +bl.type('wrenchEventsDlg::createTargetList:1', 'object') +bl.type('wrenchEventsDlg::newEvent:1', 'object') +bl.type('wrenchEventsDlg::onSleep:1', 'object') +bl.type('wrenchEventsDlg::onWake:1', 'object') +bl.type('wrenchEventsDlg::pickColor:1', 'object') +bl.type('wrenchEventsDlg::reshuffleScrollbox:1', 'object') +bl.type('wrenchEventsDlg::send:1', 'object') +bl.type('wrenchEventsDlg::VerifyInt:1', 'object') +bl.type('wrenchSoundDlg::onSleep:1', 'object') +bl.type('wrenchSoundDlg::onWake:1', 'object') +bl.type('wrenchSoundDlg::send:1', 'object') +bl.type('wrenchVehicleSpawnDlg::onSleep:1', 'object') +bl.type('wrenchVehicleSpawnDlg::onWake:1', 'object') +bl.type('wrenchVehicleSpawnDlg::Respawn:1', 'object') +bl.type('wrenchVehicleSpawnDlg::send:1', 'object') +bl.type('AdminWandImage::onFire:1', 'object') +bl.type('AdminWandImage::onHitObject:1', 'object') +bl.type('AdminWandImage::onPreFire:1', 'object') +bl.type('AdminWandImage::onStopFire:1', 'object') +bl.type('ammo::onInventory:1', 'object') +bl.type('Armor::Damage:1', 'object') +bl.type('Armor::doDismount:1', 'object') +bl.type('Armor::onAdd:1', 'object') +bl.type('Armor::onCollision:1', 'object') +bl.type('Armor::onDamage:1', 'object') +bl.type('Armor::onDisabled:1', 'object') +bl.type('Armor::onEnterLiquid:1', 'object') +bl.type('Armor::onEnterMissionArea:1', 'object') +bl.type('Armor::onImpact:1', 'object') +bl.type('Armor::onLeaveLiquid:1', 'object') +bl.type('Armor::onLeaveMissionArea:1', 'object') +bl.type('Armor::onMount:1', 'object') +bl.type('Armor::onNewDataBlock:1', 'object') +bl.type('Armor::onReachDestination:1', 'object') +bl.type('Armor::onRemove:1', 'object') +bl.type('Armor::onStuck:1', 'object') +bl.type('Armor::onTargetEnterLOS:1', 'object') +bl.type('Armor::onTargetExitLOS:1', 'object') +bl.type('Armor::onTrigger:1', 'object') +bl.type('Armor::onUnMount:1', 'object') +bl.type('BanManagerSO::addBan:1', 'object') +bl.type('BanManagerSO::dumpBans:1', 'object') +bl.type('BanManagerSO::isBanned:1', 'object') +bl.type('BanManagerSO::loadBans:1', 'object') +bl.type('BanManagerSO::removeBan:1', 'object') +bl.type('BanManagerSO::RemoveBanBL_ID:1', 'object') +bl.type('BanManagerSO::saveBans:1', 'object') +bl.type('BanManagerSO::sendBanList:1', 'object') +bl.type('blankaBallImage::onAbortCharge:1', 'object') +bl.type('blankaBallImage::onCharge:1', 'object') +bl.type('blankaBallImage::onFire:1', 'object') +bl.type('blankaBallImage::onMount:1', 'object') +bl.type('blankaBallImage::onUnMount:1', 'object') +bl.type('blankaBallProjectile::onCollision:1', 'object') +bl.type('blinkPaintProjectile::onCollision:1', 'object') +bl.type('brickDeployProjectile::onCollision:1', 'object') +bl.type('brickImage::onDeploy:1', 'object') +bl.type('brickSpawnPointData::onLoadPlant:1', 'object') +bl.type('brickSpawnPointData::onPlant:1', 'object') +bl.type('brickSpawnPointData::onRemove:1', 'object') +bl.type('brickVehicleSpawnData::onColorChange:1', 'object') +bl.type('Camera::onAdd:1', 'object') +bl.type('Camera::setMode:1', 'object') +bl.type('chromePaintProjectile::onCollision:1', 'object') +bl.type('colorMatch', 'boolean') +bl.type('CustomGameGuiServer::populateAddOnList:1', 'object') +bl.type('CustomGameGuiServer::populateMusicList:1', 'object') +bl.type('EnvGuiServer::AddToResourceList:1', 'object') +bl.type('EnvGuiServer::fillAdvancedVarsFromSimple:1', 'object') +bl.type('EnvGuiServer::getIdxFromFilenames:1', 'object') +bl.type('EnvGuiServer::PopulateEnvResourceList:1', 'object') +bl.type('EnvGuiServer::readAdvancedVarsFromSimple:1', 'object') +bl.type('EnvGuiServer::SendVignette:1', 'object') +bl.type('EnvGuiServer::SendVignetteAll:1', 'object') +bl.type('EnvGuiServer::SetAdvancedMode:1', 'object') +bl.type('EnvGuiServer::SetSimpleMode:1', 'object') +bl.type('Explosion::onAdd:1', 'object') +bl.type('ExplosionData::onAdd:1', 'object') +bl.type('flatPaintProjectile::onCollision:1', 'object') +bl.type('FlyingVehicleData::Damage:1', 'object') +bl.type('FlyingVehicleData::onCollision:1', 'object') +bl.type('fxDTSBrick::addEvent:1', 'object') +bl.type('fxDTSBrick::chainTrustCheckDown:1', 'object') +bl.type('fxDTSBrick::ChainTrustCheckUp:1', 'object') +bl.type('fxDTSBrick::ChainTrustCheckVolume:1', 'object') +bl.type('fxDTSBrick::chainUndoTrustCheckDown:1', 'object') +bl.type('fxDTSBrick::ChainUndoTrustCheckUp:1', 'object') +bl.type('fxDTSBrick::colorVehicle:1', 'object') +bl.type('fxDTSBrick::decrementPrintCount:1', 'object') +bl.type('fxDTSBrick::disappear:1', 'object') +bl.type('fxDTSBrick::eventFloodCheck', 'boolean') +bl.type('fxDTSBrick::eventFloodCheck:1', 'object') +bl.type('fxDTSBrick::explode:1', 'object') +bl.type('fxDTSBrick::fakeKillBrick:1', 'object') +bl.type('fxDTSBrick::fireRelay:1', 'object') +bl.type('fxDTSBrick::fireRelayDown:1', 'object') +bl.type('fxDTSBrick::fireRelayEast:1', 'object') +bl.type('fxDTSBrick::fireRelayFromBox:1', 'object') +bl.type('fxDTSBrick::fireRelayNorth:1', 'object') +bl.type('fxDTSBrick::fireRelaySouth:1', 'object') +bl.type('fxDTSBrick::fireRelayUp:1', 'object') +bl.type('fxDTSBrick::fireRelayWest:1', 'object') +bl.type('fxDTSBrick::getPrintCount:1', 'object') +bl.type('fxDTSBrick::getSpawnPoint:1', 'object') +bl.type('fxDTSBrick::incrementPrintCount:1', 'object') +bl.type('fxDTSBrick::isBlocked', 'boolean') +bl.type('fxDTSBrick::isBlocked:1', 'object') +bl.type('fxDTSBrick::onActivate:1', 'object') +bl.type('fxDTSBrick::onAdd:1', 'object') +bl.type('fxDTSBrick::onBlownUp:1', 'object') +bl.type('fxDTSBrick::onClearFakeDeath:1', 'object') +bl.type('fxDTSBrick::onColorChange:1', 'object') +bl.type('fxDTSBrick::onDeath:1', 'object') +bl.type('fxDTSBrick::onDisappear:1', 'object') +bl.type('fxDTSBrick::onFakeDeath:1', 'object') +bl.type('fxDTSBrick::onLoadPlant:1', 'object') +bl.type('fxDTSBrick::onMiniGameReset:1', 'object') +bl.type('fxDTSBrick::onPlant:1', 'object') +bl.type('fxDTSBrick::onPlayerTouch:1', 'object') +bl.type('fxDTSBrick::onPrintCountOverFlow:1', 'object') +bl.type('fxDTSBrick::onPrintCountUnderFlow:1', 'object') +bl.type('fxDTSBrick::onProjectileHit:1', 'object') +bl.type('fxDTSBrick::onReappear:1', 'object') +bl.type('fxDTSBrick::onRelay:1', 'object') +bl.type('fxDTSBrick::onRemove:1', 'object') +bl.type('fxDTSBrick::onRespawn:1', 'object') +bl.type('fxDTSBrick::onToolBreak:1', 'object') +bl.type('fxDTSBrick::PlantedTrustCheck:1', 'object') +bl.type('fxDTSBrick::playSound:1', 'object') +bl.type('fxDTSBrick::radiusImpulse:1', 'object') +bl.type('fxDTSBrick::reappear:1', 'object') +bl.type('fxDTSBrick::recoverVehicle:1', 'object') +bl.type('fxDTSBrick::Respawn:1', 'object') +bl.type('fxDTSBrick::respawnVehicle:1', 'object') +bl.type('fxDTSBrick::sendWrenchData:1', 'object') +bl.type('fxDTSBrick::sendWrenchSoundData:1', 'object') +bl.type('fxDTSBrick::sendWrenchVehicleSpawnData:1', 'object') +bl.type('fxDTSBrick::setEmitter:1', 'object') +bl.type('fxDTSBrick::setEmitterDirection:1', 'object') +bl.type('fxDTSBrick::setItem:1', 'object') +bl.type('fxDTSBrick::setItemDirection:1', 'object') +bl.type('fxDTSBrick::setItemPosition:1', 'object') +bl.type('fxDTSBrick::setItemRespawntime:1', 'object') +bl.type('fxDTSBrick::setLight:1', 'object') +bl.type('fxDTSBrick::setMusic:1', 'object') +bl.type('fxDTSBrick::setPrintCount:1', 'object') +bl.type('fxDTSBrick::setReColorVehicle:1', 'object') +bl.type('fxDTSBrick::setSound:1', 'object') +bl.type('fxDTSBrick::setVehicle:1', 'object') +bl.type('fxDTSBrick::setVehiclePowered:1', 'object') +bl.type('fxDTSBrick::spawnExplosion:1', 'object') +bl.type('fxDTSBrick::spawnItem:1', 'object') +bl.type('fxDTSBrick::spawnProjectile:1', 'object') +bl.type('fxDTSBrick::spawnVehicle:1', 'object') +bl.type('fxDTSBrick::TrustCheckFailed:1', 'object') +bl.type('fxDTSBrick::trustCheckFinished:1', 'object') +bl.type('fxDTSBrick::unColorVehicle:1', 'object') +bl.type('fxDTSBrick::undoTrustCheck:1', 'object') +bl.type('fxDTSBrick::vehicleMinigameEject:1', 'object') +bl.type('fxDTSBrickData::disappear:1', 'object') +bl.type('fxDTSBrickData::onAdd:1', 'object') +bl.type('fxDTSBrickData::onClearFakeDeath:1', 'object') +bl.type('fxDTSBrickData::onColorChange:1', 'object') +bl.type('fxDTSBrickData::onDeath:1', 'object') +bl.type('fxDTSBrickData::onFakeDeath:1', 'object') +bl.type('fxDTSBrickData::onLoadPlant:1', 'object') +bl.type('fxDTSBrickData::onPlant:1', 'object') +bl.type('fxDTSBrickData::onPlayerTouch:1', 'object') +bl.type('fxDTSBrickData::onRemove:1', 'object') +bl.type('fxDTSBrickData::onTrustCheckFailed:1', 'object') +bl.type('fxDTSBrickData::onTrustCheckFinished:1', 'object') +bl.type('fxDTSBrickData::onUse:1', 'object') +bl.type('fxDTSBrickData::reappear:1', 'object') +bl.type('fxLight::onRemove:1', 'object') +bl.type('GameConnection::applyBodyColors:1', 'object') +bl.type('GameConnection::applyBodyParts:1', 'object') +bl.type('GameConnection::bottomPrint:1', 'object') +bl.type('GameConnection::CenterPrint:1', 'object') +bl.type('GameConnection::ChatMessage:1', 'object') +bl.type('GameConnection::ClearEventObjects:1', 'object') +bl.type('GameConnection::ClearEventSchedules:1', 'object') +bl.type('GameConnection::ClearInvitePending:1', 'object') +bl.type('GameConnection::eventFloodCheck', 'boolean') +bl.type('GameConnection::eventFloodCheck:1', 'object') +bl.type('GameConnection::getBL_IDTrustLevel:1', 'object') +bl.type('GameConnection::InitializeTrustListUpload:1', 'object') +bl.type('GameConnection::playSound:1', 'object') +bl.type('GameConnection::StartInvitationTimeout:1', 'object') +bl.type('GameConnection::TransmitExtendedBrickInfo:1', 'object') +bl.type('GameConnection::validateAvatarPrefs:1', 'object') +bl.type('GameModeGuiServer::GetMissingAddOns:1', 'object') +bl.type('GameModeGuiServer::ParseGameModeFile', 'boolean') +bl.type('GameModeGuiServer::ParseGameModeFile:1', 'object') +bl.type('GameModeGuiServer::PopulateGameModeList:1', 'object') +bl.type('glowPaintProjectile::onCollision:1', 'object') +bl.type('hammerImage::onFire:1', 'object') +bl.type('hammerImage::onHitObject:1', 'object') +bl.type('hammerImage::onPreFire:1', 'object') +bl.type('hammerImage::onStopFire:1', 'object') +bl.type('isListenServer', 'boolean') +bl.type('isValidAddOn', 'boolean') +bl.type('isValidMap', 'boolean') +bl.type('isValidMusicFilename', 'boolean') +bl.type('Item::fadeIn:1', 'object') +bl.type('Item::fadeOut:1', 'object') +bl.type('Item::Respawn:1', 'object') +bl.type('Item::schedulePop:1', 'object') +bl.type('Item::setThrower:1', 'object') +bl.type('ItemData::create:1', 'object') +bl.type('ItemData::onAdd:1', 'object') +bl.type('ItemData::onCollision:1', 'object') +bl.type('ItemData::onPickup:1', 'object') +bl.type('ItemData::onThrow:1', 'object') +bl.type('ItemData::onUse:1', 'object') +bl.type('ItemImage::onMount:1', 'object') +bl.type('ItemImage::onUnMount:1', 'object') +bl.type('jelloPaintProjectile::onCollision:1', 'object') +bl.type('MiniGameSO::addMember:1', 'object') +bl.type('MiniGameSO::BottomPrintAll:1', 'object') +bl.type('MiniGameSO::CenterPrintAll:1', 'object') +bl.type('MiniGameSO::chatMessageAll:1', 'object') +bl.type('MiniGameSO::ChatMsgAll:1', 'object') +bl.type('MiniGameSO::checkLastManStanding:1', 'object') +bl.type('MiniGameSO::endGame:1', 'object') +bl.type('MiniGameSO::forceEquip:1', 'object') +bl.type('MiniGameSO::getLine:1', 'object') +bl.type('MiniGameSO::isMember', 'boolean') +bl.type('MiniGameSO::isMember:1', 'object') +bl.type('MiniGameSO::MessageAll:1', 'object') +bl.type('MiniGameSO::messageAllExcept:1', 'object') +bl.type('MiniGameSO::onAdd:1', 'object') +bl.type('MiniGameSO::pickSpawnPoint:1', 'object') +bl.type('MiniGameSO::removeMember:1', 'object') +bl.type('MiniGameSO::Report:1', 'object') +bl.type('MiniGameSO::Reset:1', 'object') +bl.type('MiniGameSO::RespawnAll:1', 'object') +bl.type('MiniGameSO::scheduleReset:1', 'object') +bl.type('MiniGameSO::setEnableBuilding:1', 'object') +bl.type('MiniGameSO::setEnablePainting:1', 'object') +bl.type('MiniGameSO::timeLimitTick:1', 'object') +bl.type('MiniGameSO::updateEnableBuilding:1', 'object') +bl.type('MiniGameSO::updateEnablePainting:1', 'object') +bl.type('MiniGameSO::updatePlayerDataBlock:1', 'object') +bl.type('MissionMarkerData::create:1', 'object') +bl.type('Observer::onTrigger:1', 'object') +bl.type('Observer::setMode:1', 'object') +bl.type('PainHighImage::onDone:1', 'object') +bl.type('PainLowImage::onDone:1', 'object') +bl.type('PainMidImage::onDone:1', 'object') +bl.type('paintProjectile::onCollision:1', 'object') +bl.type('ParticleEmitterNode::onRemove:1', 'object') +bl.type('pearlPaintProjectile::onCollision:1', 'object') +bl.type('Player::ActivateStuff:1', 'object') +bl.type('Player::AddHealth:1', 'object') +bl.type('Player::AddVelocity:1', 'object') +bl.type('Player::burn:1', 'object') +bl.type('Player::BurnPlayer:1', 'object') +bl.type('Player::ChangeDataBlock:1', 'object') +bl.type('Player::clearBurn:1', 'object') +bl.type('Player::ClearTempColor:1', 'object') +bl.type('Player::ClearTools:1', 'object') +bl.type('Player::Dismount:1', 'object') +bl.type('Player::emote:1', 'object') +bl.type('Player::GiveDefaultEquipment:1', 'object') +bl.type('Player::InstantRespawn:1', 'object') +bl.type('Player::isPilot', 'boolean') +bl.type('Player::isPilot:1', 'object') +bl.type('Player::kill:1', 'object') +bl.type('Player::lavaDamage:1', 'object') +bl.type('Player::mountVehicles:1', 'object') +bl.type('Player::onDriverLeave:1', 'object') +bl.type('Player::playCelAnimation:1', 'object') +bl.type('Player::playDeathAnimation:1', 'object') +bl.type('Player::playDeathCry:1', 'object') +bl.type('Player::playPain:1', 'object') +bl.type('Player::RemoveBody:1', 'object') +bl.type('Player::SetHealth:1', 'object') +bl.type('Player::SetPlayerScale:1', 'object') +bl.type('Player::setTempColor:1', 'object') +bl.type('Player::spawnExplosion:1', 'object') +bl.type('Player::spawnProjectile:1', 'object') +bl.type('Player::teleportEffect:1', 'object') +bl.type('Player::updateArm:1', 'object') +bl.type('PlayerData::onDriverLeave:1', 'object') +bl.type('PlayerTeleportImage::onDone:1', 'object') +bl.type('PrintGunImage::onFire:1', 'object') +bl.type('PrintGunImage::onHitObject:1', 'object') +bl.type('Projectile::Bounce:1', 'object') +bl.type('Projectile::onAdd:1', 'object') +bl.type('Projectile::Redirect:1', 'object') +bl.type('ProjectileData::Damage:1', 'object') +bl.type('ProjectileData::impactImpulse:1', 'object') +bl.type('ProjectileData::onCollision:1', 'object') +bl.type('ProjectileData::onExplode:1', 'object') +bl.type('ProjectileData::radiusDamage:1', 'object') +bl.type('ProjectileData::radiusImpulse:1', 'object') +bl.type('QueueSO::dumpVals:1', 'object') +bl.type('QueueSO::pop:1', 'object') +bl.type('QueueSO::push:1', 'object') +bl.type('rainbowPaintProjectile::onCollision:1', 'object') +bl.type('serverCmdAcceptMiniGameInvite:1', 'object') +bl.type('serverCmdAcceptTrustInvite:1', 'object') +bl.type('serverCmdActivateStuff:1', 'object') +bl.type('serverCmdAddEvent:1', 'object') +bl.type('serverCmdBan:1', 'object') +bl.type('serverCmdBrickCount:1', 'object') +bl.type('serverCmdBSD:1', 'object') +bl.type('serverCmdBuyBrick:1', 'object') +bl.type('serverCmdCancelAllEvents:1', 'object') +bl.type('ServerCmdCancelBrick:1', 'object') +bl.type('serverCmdCancelEvents:1', 'object') +bl.type('ServerCmdCancelExtendedBrickInfoRequest:1', 'object') +bl.type('serverCmdCancelSaveFileUpload:1', 'object') +bl.type('serverCmdClearAllBricks:1', 'object') +bl.type('ServerCmdClearBots:1', 'object') +bl.type('serverCmdClearBrickGroup:1', 'object') +bl.type('serverCmdClearBricks:1', 'object') +bl.type('serverCmdClearColors:1', 'object') +bl.type('serverCmdClearEvents:1', 'object') +bl.type('serverCmdClearFarAwayBricks:1', 'object') +bl.type('serverCmdClearFloatingBricks:1', 'object') +bl.type('serverCmdClearInventory:1', 'object') +bl.type('serverCmdClearPreviewCenter:1', 'object') +bl.type('serverCmdClearSpamBricks:1', 'object') +bl.type('ServerCmdClearVehicles:1', 'object') +bl.type('serverCmdColorTest:1', 'object') +bl.type('serverCmdCreateMiniGame:1', 'object') +bl.type('serverCmdCustomGameGui_ListUploadDone:1', 'object') +bl.type('serverCmdCustomGameGui_RequestList:1', 'object') +bl.type('serverCmdCustomGameGui_SetAddOnEnabled:1', 'object') +bl.type('serverCmdCustomGameGui_SetMusicEnabled:1', 'object') +bl.type('serverCmdCustomGameGui_SetPref:1', 'object') +bl.type('serverCmdDFG:1', 'object') +bl.type('serverCmdDoAllIcons:1', 'object') +bl.type('serverCmdDoIcon:1', 'object') +bl.type('serverCmdDoItemIcon:1', 'object') +bl.type('serverCmdDoPackIcons:1', 'object') +bl.type('serverCmdDoPlayerIcons:1', 'object') +bl.type('serverCmdDoSecondPackIcons:1', 'object') +bl.type('serverCmdDPB:1', 'object') +bl.type('serverCmdDropCameraAtPlayer:1', 'object') +bl.type('serverCmdDropPlayerAtCamera:1', 'object') +bl.type('ServerCmdDropTool:1', 'object') +bl.type('serverCmdEndMiniGame:1', 'object') +bl.type('serverCmdEndSaveFileUpload:1', 'object') +bl.type('serverCmdEnvGui_ClickDefaults:1', 'object') +bl.type('serverCmdEnvGui_RequestCurrent:1', 'object') +bl.type('serverCmdEnvGui_RequestCurrentVars:1', 'object') +bl.type('serverCmdEnvGui_RequestLists:1', 'object') +bl.type('serverCmdEnvGui_SetVar:1', 'object') +bl.type('serverCmdFetch:1', 'object') +bl.type('serverCmdFind:1', 'object') +bl.type('serverCmdGameModeGuiServer_ChangeGameMode:1', 'object') +bl.type('serverCmdGameModeGuiServer_RequestList:1', 'object') +bl.type('serverCmdGetID:1', 'object') +bl.type('serverCmdGetPZ:1', 'object') +bl.type('serverCmdGetTransform:1', 'object') +bl.type('serverCmdGreenLight:1', 'object') +bl.type('ServerCmdHilightBrickGroup:1', 'object') +bl.type('serverCmdHug:1', 'object') +bl.type('serverCmdIconInit:1', 'object') +bl.type('serverCmdIgnoreMiniGameInvite:1', 'object') +bl.type('serverCmdIgnoreTrustInvite:1', 'object') +bl.type('serverCmdInitUploadHandshake:1', 'object') +bl.type('serverCmdInstantUseBrick:1', 'object') +bl.type('serverCmdInviteToMiniGame:1', 'object') +bl.type('serverCmdJoinMiniGame:1', 'object') +bl.type('serverCmdKick:1', 'object') +bl.type('serverCmdLeaveMiniGame:1', 'object') +bl.type('serverCmdLight:1', 'object') +bl.type('ServerCmdListAllDataBlocks:1', 'object') +bl.type('serverCmdMagicWand:1', 'object') +bl.type('serverCmdNextSeat:1', 'object') +bl.type('ServerCmdPlantBrick:1', 'object') +bl.type('serverCmdPrevSeat:1', 'object') +bl.type('serverCmdRayPZ:1', 'object') +bl.type('serverCmdRealBrickCount:1', 'object') +bl.type('serverCmdRejectMiniGameInvite:1', 'object') +bl.type('serverCmdRejectTrustInvite:1', 'object') +bl.type('serverCmdReloadBricks:1', 'object') +bl.type('serverCmdRemoveFromMiniGame:1', 'object') +bl.type('serverCmdRequestBanList:1', 'object') +bl.type('ServerCmdRequestBrickManList:1', 'object') +bl.type('serverCmdRequestEventTables:1', 'object') +bl.type('ServerCmdRequestExtendedBrickInfo:1', 'object') +bl.type('serverCmdRequestMiniGameColorList:1', 'object') +bl.type('serverCmdRequestMiniGameList:1', 'object') +bl.type('ServerCmdRequestNamedTargets:1', 'object') +bl.type('ServerCmdRequestWrenchEvents:1', 'object') +bl.type('serverCmdResetMiniGame:1', 'object') +bl.type('ServerCmdResetVehicles:1', 'object') +bl.type('serverCmdRet:1', 'object') +bl.type('ServerCmdRotateBrick:1', 'object') +bl.type('serverCmdServerSettingsGui_ApplyVariables:1', 'object') +bl.type('serverCmdServerSettingsGui_RequestVariables:1', 'object') +bl.type('serverCmdServerSettingsGui_SetVariable:1', 'object') +bl.type('serverCmdSetColorMethod:1', 'object') +bl.type('ServerCmdSetFocalPoint:1', 'object') +bl.type('serverCmdSetHatTicket:1', 'object') +bl.type('ServerCmdSetMiniGameData:1', 'object') +bl.type('serverCmdSetPreviewCenter:1', 'object') +bl.type('serverCmdSetPrint:1', 'object') +bl.type('serverCmdSetSaveUploadDirName:1', 'object') +bl.type('serverCmdSetWrenchData:1', 'object') +bl.type('ServerCmdShiftBrick:1', 'object') +bl.type('serverCmdSit:1', 'object') +bl.type('serverCmdSpy:1', 'object') +bl.type('serverCmdStartSaveFileUpload:1', 'object') +bl.type('serverCmdStartTalking:1', 'object') +bl.type('serverCmdStopTalking:1', 'object') +bl.type('serverCmdSuicide:1', 'object') +bl.type('ServerCmdSuperShiftBrick:1', 'object') +bl.type('serverCmdTimeScale:1', 'object') +bl.type('serverCmdTripOut:1', 'object') +bl.type('serverCmdTrustListUpload_Done:1', 'object') +bl.type('serverCmdTrustListUpload_Line:1', 'object') +bl.type('serverCmdTrust_Demote:1', 'object') +bl.type('serverCmdTrust_Invite:1', 'object') +bl.type('serverCmdUnBan:1', 'object') +bl.type('ServerCmdUndoBrick:1', 'object') +bl.type('serverCmdUnIgnore:1', 'object') +bl.type('ServerCmdUnUseTool:1', 'object') +bl.type('servercmdupdatebodycolors:1', 'object') +bl.type('servercmdupdatebodyparts:1', 'object') +bl.type('serverCmdUploadSaveFileLine:1', 'object') +bl.type('serverCmdUseFXCan:1', 'object') +bl.type('serverCmdUseHammer:1', 'object') +bl.type('ServerCmdUseInventory:1', 'object') +bl.type('serverCmdUseSprayCan:1', 'object') +bl.type('ServerCmdUseTool:1', 'object') +bl.type('serverCmdVehicleSpawn_Respawn:1', 'object') +bl.type('serverCmdWand:1', 'object') +bl.type('serverCmdWarp:1', 'object') +bl.type('serverCmdZombie:1', 'object') +bl.type('setSprayCanColors', 'boolean') +bl.type('ShapeBase::clearInventory:1', 'object') +bl.type('ShapeBase::Damage:1', 'object') +bl.type('ShapeBase::decInventory:1', 'object') +bl.type('ShapeBase::getInventory:1', 'object') +bl.type('ShapeBase::incInventory:1', 'object') +bl.type('ShapeBase::maxInventory:1', 'object') +bl.type('ShapeBase::onInventory:1', 'object') +bl.type('ShapeBase::pickup:1', 'object') +bl.type('ShapeBase::setInventory:1', 'object') +bl.type('ShapeBase::throw', 'boolean') +bl.type('ShapeBase::throw:1', 'object') +bl.type('ShapeBase::throwObject:1', 'object') +bl.type('ShapeBase::use:1', 'object') +bl.type('ShapeBaseData::Damage:1', 'object') +bl.type('ShapeBaseData::onInventory:1', 'object') +bl.type('ShapeBaseData::onPickup', 'boolean') +bl.type('ShapeBaseData::onPickup:1', 'object') +bl.type('ShapeBaseData::onThrow', 'boolean') +bl.type('ShapeBaseData::onThrow:1', 'object') +bl.type('ShapeBaseData::onUse', 'boolean') +bl.type('ShapeBaseData::onUse:1', 'object') +bl.type('SimGroup::addNTName:1', 'object') +bl.type('SimGroup::addPotentialTrust:1', 'object') +bl.type('SimGroup::addSpawnBrick:1', 'object') +bl.type('SimGroup::chainBlink:1', 'object') +bl.type('SimGroup::ChainDeleteAll:1', 'object') +bl.type('SimGroup::ClearAllNTNames:1', 'object') +bl.type('SimGroup::DumpNTNames:1', 'object') +bl.type('SimGroup::dumpSpawnPoints:1', 'object') +bl.type('SimGroup::getBrickSpawnPoint:1', 'object') +bl.type('SimGroup::getClient:1', 'object') +bl.type('SimGroup::hasUser', 'boolean') +bl.type('SimGroup::hasUser:1', 'object') +bl.type('SimGroup::removeNTName:1', 'object') +bl.type('SimGroup::removeSpawnBrick:1', 'object') +bl.type('SimObject::addScheduledEvent:1', 'object') +bl.type('SimObject::cancelEvents:1', 'object') +bl.type('SimObject::clearEvents:1', 'object') +bl.type('SimObject::clearNTObjectName:1', 'object') +bl.type('SimObject::dumpEvents:1', 'object') +bl.type('SimObject::onCameraEnterOrbit:1', 'object') +bl.type('SimObject::onCameraLeaveOrbit:1', 'object') +bl.type('SimObject::processInputEvent:1', 'object') +bl.type('SimObject::serializeEvent:1', 'object') +bl.type('SimObject::serializeEventToString:1', 'object') +bl.type('SimObject::SetEventEnabled:1', 'object') +bl.type('SimObject::setNTObjectName:1', 'object') +bl.type('SimObject::ToggleEventEnabled:1', 'object') +bl.type('stablePaintProjectile::onCollision:1', 'object') +bl.type('StaticShape::explode:1', 'object') +bl.type('StaticShapeData::create:1', 'object') +bl.type('StaticShapeData::Damage:1', 'object') +bl.type('StaticShapeData::onAdd:1', 'object') +bl.type('swirlPaintProjectile::onCollision:1', 'object') +bl.type('Trigger::onAdd:1', 'object') +bl.type('TriggerData::onAdd:1', 'object') +bl.type('TriggerData::onEnterTrigger:1', 'object') +bl.type('TriggerData::onLeaveTrigger:1', 'object') +bl.type('TriggerData::onTickTrigger:1', 'object') +bl.type('validateEnvironmentObjects', 'boolean') +bl.type('Vehicle::finalExplosion:1', 'object') +bl.type('Vehicle::lavaDamage:1', 'object') +bl.type('Vehicle::onActivate:1', 'object') +bl.type('Vehicle::onCollision:1', 'object') +bl.type('Vehicle::onDriverLeave:1', 'object') +bl.type('Vehicle::onRemove:1', 'object') +bl.type('Vehicle::teleportEffect:1', 'object') +bl.type('VehicleData::onCollision:1', 'object') +bl.type('VehicleData::onDriverLeave:1', 'object') +bl.type('VehicleData::onEnterLiquid:1', 'object') +bl.type('VehicleData::onLeaveLiquid:1', 'object') +bl.type('VehicleSpawnMarker::onAdd:1', 'object') +bl.type('VehicleSpawnMarker::onRemove:1', 'object') +bl.type('VerifyAddOnScripts', 'boolean') +bl.type('WandImage::onFire:1', 'object') +bl.type('WandImage::onHitObject:1', 'object') +bl.type('WandImage::onPreFire:1', 'object') +bl.type('WandImage::onStopFire:1', 'object') +bl.type('WandItem::onUse:1', 'object') +bl.type('Weapon::onInventory:1', 'object') +bl.type('Weapon::onPickup:1', 'object') +bl.type('Weapon::onUse:1', 'object') +bl.type('WeaponImage::onFire:1', 'object') +bl.type('WeaponImage::onMount:1', 'object') +bl.type('WeaponImage::onUnMount:1', 'object') +bl.type('WheeledVehicleData::create:1', 'object') +bl.type('WheeledVehicleData::Damage:1', 'object') +bl.type('WheeledVehicleData::onAdd:1', 'object') +bl.type('WheeledVehicleData::onCollision:1', 'object') +bl.type('WheeledVehicleData::onDamage:1', 'object') +bl.type('WheeledVehicleData::onDriverLeave:1', 'object') +bl.type('WrenchImage::onFire:1', 'object') +bl.type('WrenchImage::onHitObject:1', 'object') +bl.type('WrenchImage::onPreFire:1', 'object') +bl.type('WrenchImage::onStopFire:1', 'object') +bl.type('GameConnection::Cheat:1', 'object') +bl.type('GameConnection::createPlayer:1', 'object') +bl.type('GameConnection::getSimpleName:1', 'object') +bl.type('GameConnection::getSpawnPoint:1', 'object') +bl.type('GameConnection::InstantRespawn:1', 'object') +bl.type('GameConnection::onClientEnterGame:1', 'object') +bl.type('GameConnection::onClientLeaveGame:1', 'object') +bl.type('GameConnection::onDeath:1', 'object') +bl.type('GameConnection::onEnterMissionArea:1', 'object') +bl.type('GameConnection::onInfiniteLag:1', 'object') +bl.type('GameConnection::onLeaveMissionArea:1', 'object') +bl.type('GameConnection::resetVehicles:1', 'object') +bl.type('GameConnection::sendTrustFailureMessage:1', 'object') +bl.type('GameConnection::setCanRespawn:1', 'object') +bl.type('GameConnection::setLoadingIndicator:1', 'object') +bl.type('GameConnection::spawnPlayer:1', 'object') +bl.type('GameConnection::transmitMaxPlayers:1', 'object') +bl.type('GameConnection::transmitServerName:1', 'object') +bl.type('SimGroup::getTrustFailureMessage:1', 'object') +bl.type('AIConnection::onConnect:1', 'object') +bl.type('authTCPobj_Server::onConnected:1', 'object') +bl.type('authTCPobj_Server::onConnectFailed:1', 'object') +bl.type('authTCPobj_Server::onDisconnect:1', 'object') +bl.type('authTCPobj_Server::onDNSFailed:1', 'object') +bl.type('authTCPobj_Server::onLine:1', 'object') +bl.type('chatFilter', 'boolean') +bl.type('GameConnection::authCheck:1', 'object') +bl.type('GameConnection::autoAdminCheck:1', 'object') +bl.type('GameConnection::clientWantsGhostAlwaysRetry:1', 'object') +bl.type('GameConnection::endMission:1', 'object') +bl.type('GameConnection::incScore:1', 'object') +bl.type('GameConnection::killDupes:1', 'object') +bl.type('GameConnection::loadMission:1', 'object') +bl.type('GameConnection::onClientEnterGame:1', 'object') +bl.type('GameConnection::onClientLeaveGame:1', 'object') +bl.type('GameConnection::onConnect:1', 'object') +bl.type('GameConnection::onConnectRequest:1', 'object') +bl.type('GameConnection::onDataBlocksDone:1', 'object') +bl.type('GameConnection::onDrop:1', 'object') +bl.type('GameConnection::onGhostAlwaysFailed:1', 'object') +bl.type('GameConnection::onGhostAlwaysObjectsReceived:1', 'object') +bl.type('GameConnection::sendPlayerListUpdate:1', 'object') +bl.type('GameConnection::setScore:1', 'object') +bl.type('GameConnection::spamMessageTimeout:1', 'object') +bl.type('GameConnection::spamReset:1', 'object') +bl.type('GameConnection::startLoad:1', 'object') +bl.type('GameConnection::startMission:1', 'object') +bl.type('GameConnection::syncClock:1', 'object') +bl.type('isNameUnique', 'boolean') +bl.type('postServerTCPObj::onConnected:1', 'object') +bl.type('postServerTCPObj::onConnectFailed:1', 'object') +bl.type('postServerTCPObj::onDisconnect:1', 'object') +bl.type('postServerTCPObj::onDNSFailed:1', 'object') +bl.type('postServerTCPObj::onLine:1', 'object') +bl.type('servAuthTCPobj::onConnected:1', 'object') +bl.type('servAuthTCPobj::onConnectFailed:1', 'object') +bl.type('servAuthTCPobj::onDNSFailed:1', 'object') +bl.type('servAuthTCPobj::onLine:1', 'object') +bl.type('serverCmdBlobDownloadFinished:1', 'object') +bl.type('serverCmdClosePlayerList:1', 'object') +bl.type('serverCmdMessageSent:1', 'object') +bl.type('serverCmdMissionStartPhase1Ack:1', 'object') +bl.type('serverCmdMissionStartPhase2Ack:1', 'object') +bl.type('serverCmdMissionStartPhase3Ack:1', 'object') +bl.type('serverCmdOpenPlayerList:1', 'object') +bl.type('serverCmdSAD:1', 'object') +bl.type('serverCmdSADSetPassword:1', 'object') +bl.type('serverCmdTeamMessageSent:1', 'object') +bl.type('spamAlert', 'boolean') + +-- Auto-generated from dumpConsoleClasses() and dumpConsoleFunctions() +bl.type('AIConnection::onConnect:1', 'object') +bl.type('AIPlayer.canSetIFLs', 'bool') +bl.type('AIPlayer::InstantRespawn:1', 'object') +bl.type('AIPlayer::clearAim:1', 'object') +bl.type('AIPlayer::clearMoveDestination:1', 'object') +bl.type('AIPlayer::clearMoveX:1', 'object') +bl.type('AIPlayer::clearMoveY:1', 'object') +bl.type('AIPlayer::clearMoveYaw:1', 'object') +bl.type('AIPlayer::getAimLocation:1', 'object') +bl.type('AIPlayer::getAimObject', 'object') +bl.type('AIPlayer::getAimObject:1', 'object') +bl.type('AIPlayer::getAimVector:1', 'object') +bl.type('AIPlayer::getMoveDestination:1', 'object') +bl.type('AIPlayer::getMoveObject', 'object') +bl.type('AIPlayer::getMoveObject:1', 'object') +bl.type('AIPlayer::getMoveTolerance:1', 'object') +bl.type('AIPlayer::getPlayerName:1', 'object') +bl.type('AIPlayer::hMeleeAttack:1', 'object') +bl.type('AIPlayer::isCrouching', 'bool') +bl.type('AIPlayer::isCrouching:1', 'object') +bl.type('AIPlayer::isJetting', 'bool') +bl.type('AIPlayer::isJetting:1', 'object') +bl.type('AIPlayer::isJumping', 'bool') +bl.type('AIPlayer::isJumping:1', 'object') +bl.type('AIPlayer::setAimLocation:1', 'object') +bl.type('AIPlayer::setAimObject:1', 'object') +bl.type('AIPlayer::setAimObject:2', 'object') +bl.type('AIPlayer::setAimVector:1', 'object') +bl.type('AIPlayer::setCrouching:1', 'object') +bl.type('AIPlayer::setCrouching:2', 'bool') +bl.type('AIPlayer::setEngageDistance:1', 'object') +bl.type('AIPlayer::setHeadAngle:1', 'object') +bl.type('AIPlayer::setHeadAngleSpeed:1', 'object') +bl.type('AIPlayer::setJetting:1', 'object') +bl.type('AIPlayer::setJetting:2', 'bool') +bl.type('AIPlayer::setJumping:1', 'object') +bl.type('AIPlayer::setJumping:2', 'bool') +bl.type('AIPlayer::setMoveDestination:1', 'object') +bl.type('AIPlayer::setMoveObject:1', 'object') +bl.type('AIPlayer::setMoveObject:2', 'object') +bl.type('AIPlayer::setMoveSlowdown:1', 'object') +bl.type('AIPlayer::setMoveSlowdown:2', 'bool') +bl.type('AIPlayer::setMoveSpeed:1', 'object') +bl.type('AIPlayer::setMoveTolerance:1', 'object') +bl.type('AIPlayer::setMoveX:1', 'object') +bl.type('AIPlayer::setMoveY:1', 'object') +bl.type('AIPlayer::setMoveYaw:1', 'object') +bl.type('AIPlayer::stop:1', 'object') +bl.type('ActionMap::bind:1', 'object') +bl.type('ActionMap::bindCmd:1', 'object') +bl.type('ActionMap::blockBind:1', 'object') +bl.type('ActionMap::copyBind:1', 'object') +bl.type('ActionMap::getBinding:1', 'object') +bl.type('ActionMap::getCommand:1', 'object') +bl.type('ActionMap::getDeadZone:1', 'object') +bl.type('ActionMap::getNumBinds:1', 'object') +bl.type('ActionMap::getScale:1', 'object') +bl.type('ActionMap::isInverted', 'bool') +bl.type('ActionMap::isInverted:1', 'object') +bl.type('ActionMap::pop:1', 'object') +bl.type('ActionMap::popUnbind:1', 'object') +bl.type('ActionMap::push:1', 'object') +bl.type('ActionMap::pushBind:1', 'object') +bl.type('ActionMap::save:1', 'object') +bl.type('ActionMap::unbind:1', 'object') +bl.type('AdminLoginGui::onSleep:1', 'object') +bl.type('AdminLoginGui::onWake:1', 'object') +bl.type('AdminWandImage::onFire:1', 'object') +bl.type('AdminWandImage::onHitObject:1', 'object') +bl.type('AdminWandImage::onPreFire:1', 'object') +bl.type('AdminWandImage::onStopFire:1', 'object') +bl.type('AkimboGunImage::onFire:1', 'object') +bl.type('AkimboGunImage::onFireAkimbo:1', 'object') +bl.type('AkimboGunImage::onMount:1', 'object') +bl.type('AkimboGunImage::onUnMount:1', 'object') +bl.type('AllPrintRatios_List::onSelect:1', 'object') +bl.type('Armor::onCollision:1', 'object') +bl.type('AudioDescription.is3D', 'bool') +bl.type('AudioDescription.isLooping', 'bool') +bl.type('AudioDescription.isStreaming', 'bool') +bl.type('AudioEmitter.enableVisualFeedback', 'bool') +bl.type('AudioEmitter.is3D', 'bool') +bl.type('AudioEmitter.isLooping', 'bool') +bl.type('AudioEmitter.outsideAmbient', 'bool') +bl.type('AudioEmitter.useProfileDescription', 'bool') +bl.type('AudioEmitter::getProfileId:1', 'object') +bl.type('AudioEmitter::update:1', 'object') +bl.type('AudioEnvironment.useRoom', 'bool') +bl.type('AudioProfile.preload', 'bool') +bl.type('AudioProfile::getDescription:1', 'object') +bl.type('AudioProfile::isStereo', 'bool') +bl.type('AudioProfile::isStereo:1', 'object') +bl.type('AvatarGui::onWake:1', 'object') +bl.type('BSD_TabBoxShifter::checkButtonVisibility:1', 'object') +bl.type('BSD_TabBoxShifter::checkTabVisibility:1', 'object') +bl.type('BSD_TabBoxShifter::shiftTabsLeft:1', 'object') +bl.type('BSD_TabBoxShifter::shiftTabsRight:1', 'object') +bl.type('BSD_category::onRemove:1', 'object') +bl.type('BanList::add:1', 'object') +bl.type('BanList::addAbsolute:1', 'object') +bl.type('BanList::export:1', 'object') +bl.type('BanList::isBanned', 'bool') +bl.type('BanList::isBanned:1', 'object') +bl.type('BanList::removeBan:1', 'object') +bl.type('BanManagerSO::RemoveBanBL_ID:1', 'object') +bl.type('BanManagerSO::addBan:1', 'object') +bl.type('BanManagerSO::dumpBans:1', 'object') +bl.type('BanManagerSO::isBanned:1', 'object') +bl.type('BanManagerSO::loadBans:1', 'object') +bl.type('BanManagerSO::removeBan:1', 'object') +bl.type('BanManagerSO::saveBans:1', 'object') +bl.type('BanManagerSO::sendBanList:1', 'object') +bl.type('BlockheadHoleBot::onAdd:1', 'object') +bl.type('BlockheadHoleBot::onBotCollision:1', 'object') +bl.type('BlockheadHoleBot::onBotDamage:1', 'object') +bl.type('BlockheadHoleBot::onBotFollow:1', 'object') +bl.type('BlockheadHoleBot::onBotLoop:1', 'object') +bl.type('BottomPrintText::onResize:1', 'object') +bl.type('BrickManGui::clearAllBricks:1', 'object') +bl.type('BrickManGui::clearBrickGroup:1', 'object') +bl.type('BrickManGui::clickBan:1', 'object') +bl.type('BrickManGui::clickClear:1', 'object') +bl.type('BrickManGui::clickClearAll:1', 'object') +bl.type('BrickManGui::clickHilight:1', 'object') +bl.type('BrickManGui::onSleep:1', 'object') +bl.type('BrickManGui::onWake:1', 'object') +bl.type('BrickManGui::sortList:1', 'object') +bl.type('BrickManGui::sortNumList:1', 'object') +bl.type('BrickSelectorDlg::onSleep:1', 'object') +bl.type('BrickSelectorDlg::onWake:1', 'object') +bl.type('BrickSharkBot_HoleSpawnData::onPlant:1', 'object') +bl.type('BuildMacroSO::PlayBack:1', 'object') +bl.type('BuildMacroSO::PlayEvent:1', 'object') +bl.type('BuildMacroSO::compress:1', 'object') +bl.type('BuildMacroSO::deleteEvent:1', 'object') +bl.type('BuildMacroSO::dump:1', 'object') +bl.type('BuildMacroSO::pushEvent:1', 'object') +bl.type('CSVReader::hasNextValue:1', 'object') +bl.type('CSVReader::readNextValue:1', 'object') +bl.type('CSVReader::setDataString:1', 'object') +bl.type('Camera.canSetIFLs', 'bool') +bl.type('Camera::getCameraRelativeMovement', 'bool') +bl.type('Camera::getCameraRelativeMovement:1', 'object') +bl.type('Camera::getControlObject', 'object') +bl.type('Camera::getControlObject:1', 'object') +bl.type('Camera::getOrbitDistance:1', 'object') +bl.type('Camera::getOrbitObject', 'object') +bl.type('Camera::getOrbitObject:1', 'object') +bl.type('Camera::getOrbitPoint:1', 'object') +bl.type('Camera::getPosition:1', 'object') +bl.type('Camera::isOrbitMode', 'bool') +bl.type('Camera::isOrbitMode:1', 'object') +bl.type('Camera::onAdd:1', 'object') +bl.type('Camera::setCameraRelativeMovement:1', 'object') +bl.type('Camera::setCameraRelativeMovement:2', 'bool') +bl.type('Camera::setClampMode:1', 'object') +bl.type('Camera::setControlObject', 'bool') +bl.type('Camera::setControlObject:1', 'object') +bl.type('Camera::setControlObject:2', 'object') +bl.type('Camera::setDollyMode:1', 'object') +bl.type('Camera::setFlyMode:1', 'object') +bl.type('Camera::setMode:1', 'object') +bl.type('Camera::setOrbitMode:1', 'object') +bl.type('Camera::setOrbitMode:2', 'object') +bl.type('Camera::setOrbitMode:7', 'bool') +bl.type('Camera::setOrbitPointMode:1', 'object') +bl.type('CameraData.emap', 'bool') +bl.type('CameraData.firstPersonOnly', 'bool') +bl.type('CameraData.inheritEnergyFromMount', 'bool') +bl.type('CameraData.isInvincible', 'bool') +bl.type('CameraData.observeThroughObject', 'bool') +bl.type('CameraData.renderWhenDestroyed', 'bool') +bl.type('CameraData.thirdPersonOnly', 'bool') +bl.type('CameraData.useEyePoint', 'bool') +bl.type('CannonFuseImage::onDone:1', 'object') +bl.type('CannonSmokeImage::onDone:1', 'object') +bl.type('CannonTurret::onDisabled:1', 'object') +bl.type('Canvas::popDialog:1', 'object') +bl.type('Canvas::pushDialog:1', 'object') +bl.type('CenterPrintText::onResize:1', 'object') +bl.type('ClientBrickSearchNext', 'object') +bl.type('ColorSetGui::AddColor:1', 'object') +bl.type('ColorSetGui::Display:1', 'object') +bl.type('ColorSetGui::defaults:1', 'object') +bl.type('ColorSetGui::deleteColor:1', 'object') +bl.type('ColorSetGui::load:1', 'object') +bl.type('ColorSetGui::onSleep:1', 'object') +bl.type('ColorSetGui::onWake:1', 'object') +bl.type('ColorSetGui::save:1', 'object') +bl.type('ColorSetGui::selectColor:1', 'object') +bl.type('ColorSetGui::setMode:1', 'object') +bl.type('ColorSetGui::update:1', 'object') +bl.type('ConsoleEntry::eval:1', 'object') +bl.type('ConsoleLogger::attach', 'bool') +bl.type('ConsoleLogger::attach:1', 'object') +bl.type('ConsoleLogger::detach', 'bool') +bl.type('ConsoleLogger::detach:1', 'object') +bl.type('CreateMiniGameGui::ClickCreate:1', 'object') +bl.type('CreateMiniGameGui::ClickFav:1', 'object') +bl.type('CreateMiniGameGui::LoadDataBlocks:1', 'object') +bl.type('CreateMiniGameGui::Refresh:1', 'object') +bl.type('CreateMiniGameGui::clickColorList:1', 'object') +bl.type('CreateMiniGameGui::clickEnd:1', 'object') +bl.type('CreateMiniGameGui::clickReset:1', 'object') +bl.type('CreateMiniGameGui::clickSetFavs:1', 'object') +bl.type('CreateMiniGameGui::dumpColorList:1', 'object') +bl.type('CreateMiniGameGui::end:1', 'object') +bl.type('CreateMiniGameGui::onSleep:1', 'object') +bl.type('CreateMiniGameGui::onWake:1', 'object') +bl.type('CreateMiniGameGui::send:1', 'object') +bl.type('CreatorTree.clipToParent', 'bool') +bl.type('CreatorTree.enabled', 'bool') +bl.type('CreatorTree.visible', 'bool') +bl.type('CreatorTree::addGroup:1', 'object') +bl.type('CreatorTree::addItem:1', 'object') +bl.type('CreatorTree::clear:1', 'object') +bl.type('CreatorTree::fileNameMatch', 'bool') +bl.type('CreatorTree::fileNameMatch:1', 'object') +bl.type('CreatorTree::getName:1', 'object') +bl.type('CreatorTree::getParent:1', 'object') +bl.type('CreatorTree::getSelected:1', 'object') +bl.type('CreatorTree::getValue:1', 'object') +bl.type('CreatorTree::isGroup', 'bool') +bl.type('CreatorTree::isGroup:1', 'object') +bl.type('CustomGameGui::AddAdvancedGuiElement:1', 'object') +bl.type('CustomGameGui::ClickBack:1', 'object') +bl.type('CustomGameGui::ClickSelect:1', 'object') +bl.type('CustomGameGui::CopyGuiVarsToPrefs:1', 'object') +bl.type('CustomGameGui::CopyPrefsToGuiVars:1', 'object') +bl.type('CustomGameGui::CreateAddOnListGui:1', 'object') +bl.type('CustomGameGui::CreateAdvancedGui:1', 'object') +bl.type('CustomGameGui::CreateMusicListGui:1', 'object') +bl.type('CustomGameGui::ScaleText:1', 'object') +bl.type('CustomGameGui::clickAddOnItem:1', 'object') +bl.type('CustomGameGui::clickAddOns:1', 'object') +bl.type('CustomGameGui::clickAdvanced:1', 'object') +bl.type('CustomGameGui::clickAdvancedItem:1', 'object') +bl.type('CustomGameGui::clickAll:1', 'object') +bl.type('CustomGameGui::clickDefault:1', 'object') +bl.type('CustomGameGui::clickMusic:1', 'object') +bl.type('CustomGameGui::clickMusicItem:1', 'object') +bl.type('CustomGameGui::clickNone:1', 'object') +bl.type('CustomGameGui::hideAllTabs:1', 'object') +bl.type('CustomGameGui::onRender:1', 'object') +bl.type('CustomGameGui::onWake:1', 'object') +bl.type('CustomGameGui::populateAddOnList:1', 'object') +bl.type('CustomGameGui::populateMusicList:1', 'object') +bl.type('CustomGameGui::setDefaultAddOns:1', 'object') +bl.type('CustomGameGui::setDefaultMusic:1', 'object') +bl.type('CustomGameGuiServer::populateAddOnList:1', 'object') +bl.type('CustomGameGuiServer::populateMusicList:1', 'object') +bl.type('DDS_BackgroundCtrl::onMouseDown:1', 'object') +bl.type('DDS_PopUpInputCtrl::onTabComplete:1', 'object') +bl.type('DDS_PopUpListCtrl::makeSelectedVisible:1', 'object') +bl.type('DDS_PopUpListCtrl::selectLineNoCallback:1', 'object') +bl.type('DDS_PopUpMenuCtrl::addLineBack:1', 'object') +bl.type('DDS_PopUpMenuCtrl::addLineFront:1', 'object') +bl.type('DDS_PopUpMenuCtrl::calcListWidth:1', 'object') +bl.type('DDS_PopUpMenuCtrl::clearLines:1', 'object') +bl.type('DDS_PopUpMenuCtrl::closeMenu:1', 'object') +bl.type('DDS_PopUpMenuCtrl::moveSelection:1', 'object') +bl.type('DDS_PopUpMenuCtrl::onLineSelected:1', 'object') +bl.type('DDS_PopUpMenuCtrl::onMouseDown:1', 'object') +bl.type('DDS_PopUpMenuCtrl::openMenu:1', 'object') +bl.type('DDS_PopUpMenuCtrl::repeatMove:1', 'object') +bl.type('DDS_PopUpMenuCtrl::startMoveDown:1', 'object') +bl.type('DDS_PopUpMenuCtrl::startMoveUp:1', 'object') +bl.type('DDS_PopUpMenuCtrl::stopMove:1', 'object') +bl.type('DDS_PopUpMenuCtrl::updateFilter:1', 'object') +bl.type('DDS_PopUpMenuCtrl::updateScrollRect:1', 'object') +bl.type('DDS_PopUpMenuCtrl::updateTabHint:1', 'object') +bl.type('DNetSetLogging:1', 'bool') +bl.type('DbgFileView.clipToParent', 'bool') +bl.type('DbgFileView.enabled', 'bool') +bl.type('DbgFileView.visible', 'bool') +bl.type('DbgFileView::clearBreakPositions:1', 'object') +bl.type('DbgFileView::findString', 'bool') +bl.type('DbgFileView::findString:1', 'object') +bl.type('DbgFileView::getCurrentLine:1', 'object') +bl.type('DbgFileView::open', 'bool') +bl.type('DbgFileView::open:1', 'object') +bl.type('DbgFileView::removeBreak:1', 'object') +bl.type('DbgFileView::setBreak:1', 'object') +bl.type('DbgFileView::setBreakPosition:1', 'object') +bl.type('DbgFileView::setCurrentLine:1', 'object') +bl.type('DbgFileView::setCurrentLine:3', 'bool') +bl.type('Debris::init', 'bool') +bl.type('Debris::init:1', 'object') +bl.type('DebrisData.explodeOnMaxBounce', 'bool') +bl.type('DebrisData.fade', 'bool') +bl.type('DebrisData.ignoreWater', 'bool') +bl.type('DebrisData.render2D', 'bool') +bl.type('DebrisData.snapOnMaxBounce', 'bool') +bl.type('DebrisData.staticOnMaxBounce', 'bool') +bl.type('DebrisData.useRadiusMass', 'bool') +bl.type('DebugView.clipToParent', 'bool') +bl.type('DebugView.enabled', 'bool') +bl.type('DebugView.visible', 'bool') +bl.type('DebugView::addLine:1', 'object') +bl.type('DebugView::clearLines:1', 'object') +bl.type('DebugView::clearText:1', 'object') +bl.type('DebugView::setText:1', 'object') +bl.type('EGplus_Funcbar::onURL:1', 'object') +bl.type('EGplus_Main::close:1', 'object') +bl.type('EGplus_Main::open:1', 'object') +bl.type('EGplus_Ticker::clear:1', 'object') +bl.type('EGplus_Ticker::showStatus:1', 'object') +bl.type('EditManager.clipToParent', 'bool') +bl.type('EditManager.enabled', 'bool') +bl.type('EditManager.visible', 'bool') +bl.type('EditManager::gotoBookmark:1', 'object') +bl.type('EditManager::setBookmark:1', 'object') +bl.type('EditTSCtrl.clipToParent', 'bool') +bl.type('EditTSCtrl.enabled', 'bool') +bl.type('EditTSCtrl.renderMissionArea', 'bool') +bl.type('EditTSCtrl.visible', 'bool') +bl.type('EditTSCtrl::renderCircle:1', 'object') +bl.type('EditTSCtrl::renderLine:1', 'object') +bl.type('EditTSCtrl::renderSphere:1', 'object') +bl.type('EditTSCtrl::renderTriangle:1', 'object') +bl.type('Editor::Create:1', 'object') +bl.type('Editor::checkActiveLoadDone:1', 'object') +bl.type('Editor::onAdd:1', 'object') +bl.type('EnvFav_List::onSelect:1', 'object') +bl.type('EnvFav_List::update:1', 'object') +bl.type('EnvGui::onWake:1', 'object') +bl.type('EnvGui::setPane:1', 'object') +bl.type('EnvGuiFavorites::doLoad:1', 'object') +bl.type('EnvGuiFavorites::doSave:1', 'object') +bl.type('EnvGuiFavorites::remake:1', 'object') +bl.type('EnvGuiFavorites::saveFavorite:1', 'object') +bl.type('EnvGuiFavorites::setVar:1', 'object') +bl.type('EnvGuiServer::AddToResourceList:1', 'object') +bl.type('EnvGuiServer::PopulateEnvResourceList:1', 'object') +bl.type('EnvGuiServer::SendVignette:1', 'object') +bl.type('EnvGuiServer::SendVignetteAll:1', 'object') +bl.type('EnvGuiServer::SetAdvancedMode:1', 'object') +bl.type('EnvGuiServer::SetSimpleMode:1', 'object') +bl.type('EnvGuiServer::fillAdvancedVarsFromSimple:1', 'object') +bl.type('EnvGuiServer::getIdxFromFilenames:1', 'object') +bl.type('EnvGuiServer::readAdvancedVarsFromSimple:1', 'object') +bl.type('EnvGui_Window::onWindowFocus:1', 'object') +bl.type('Explosion::onAdd:1', 'object') +bl.type('ExplosionData.cameraShakeFalloff', 'bool') +bl.type('ExplosionData.faceViewer', 'bool') +bl.type('ExplosionData.shakeCamera', 'bool') +bl.type('ExplosionData::onAdd:1', 'object') +bl.type('FileObject::close:1', 'object') +bl.type('FileObject::isEOF', 'bool') +bl.type('FileObject::isEOF:1', 'object') +bl.type('FileObject::openForAppend', 'bool') +bl.type('FileObject::openForAppend:1', 'object') +bl.type('FileObject::openForRead', 'bool') +bl.type('FileObject::openForRead:1', 'object') +bl.type('FileObject::openForWrite', 'bool') +bl.type('FileObject::openForWrite:1', 'object') +bl.type('FileObject::readLine:1', 'object') +bl.type('FileObject::writeLine:1', 'object') +bl.type('FlyingVehicle.canSetIFLs', 'bool') +bl.type('FlyingVehicle.disableMove', 'bool') +bl.type('FlyingVehicle::useCreateHeight:1', 'object') +bl.type('FlyingVehicle::useCreateHeight:2', 'bool') +bl.type('FlyingVehicleData.cameraRoll', 'bool') +bl.type('FlyingVehicleData.emap', 'bool') +bl.type('FlyingVehicleData.firstPersonOnly', 'bool') +bl.type('FlyingVehicleData.inheritEnergyFromMount', 'bool') +bl.type('FlyingVehicleData.isInvincible', 'bool') +bl.type('FlyingVehicleData.observeThroughObject', 'bool') +bl.type('FlyingVehicleData.renderWhenDestroyed', 'bool') +bl.type('FlyingVehicleData.rideAble', 'bool') +bl.type('FlyingVehicleData.thirdPersonOnly', 'bool') +bl.type('FlyingVehicleData.useEyePoint', 'bool') +bl.type('FlyingVehicleData::Damage:1', 'object') +bl.type('FlyingVehicleData::onCollision:1', 'object') +bl.type('FootballItem::onBallCollision:1', 'object') +bl.type('GLEW_ARB_shader_objects', 'bool') +bl.type('GLEW_ARB_shading_language_100', 'bool') +bl.type('GLEW_ARB_shadow', 'bool') +bl.type('GLEW_ARB_texture_rg', 'bool') +bl.type('GLEW_EXT_framebuffer_object', 'bool') +bl.type('GLEW_EXT_texture3D', 'bool') +bl.type('GLEW_EXT_texture_array', 'bool') +bl.type('GameBase::getDataBlock:1', 'object') +bl.type('GameBase::inspectPostApply:1', 'object') +bl.type('GameBase::setDataBlock', 'bool') +bl.type('GameBase::setDataBlock:1', 'object') +bl.type('GameConnection::onDrop:1', 'object') +bl.type('GameConnection::setConnectArgs:1', 'object') +bl.type('GameConnection::startMission:1', 'object') +bl.type('GameModeGui::ClickGameMode:1', 'object') +bl.type('GameModeGuiServer::GetMissingAddOns:1', 'object') +bl.type('GameModeGuiServer::ParseGameModeFile:1', 'object') +bl.type('GameModeGuiServer::PopulateGameModeList:1', 'object') +bl.type('GameTSCtrl.clipToParent', 'bool') +bl.type('GameTSCtrl.enabled', 'bool') +bl.type('GameTSCtrl.visible', 'bool') +bl.type('GameWindowExists', 'bool') +bl.type('GuiAnimatedBitmapCtrl.alignLeft', 'bool') +bl.type('GuiAnimatedBitmapCtrl.alignTop', 'bool') +bl.type('GuiAnimatedBitmapCtrl.clipToParent', 'bool') +bl.type('GuiAnimatedBitmapCtrl.enabled', 'bool') +bl.type('GuiAnimatedBitmapCtrl.keepCached', 'bool') +bl.type('GuiAnimatedBitmapCtrl.lockAspectRatio', 'bool') +bl.type('GuiAnimatedBitmapCtrl.mMultiply', 'bool') +bl.type('GuiAnimatedBitmapCtrl.overflowImage', 'bool') +bl.type('GuiAnimatedBitmapCtrl.skipFrames', 'bool') +bl.type('GuiAnimatedBitmapCtrl.visible', 'bool') +bl.type('GuiAnimatedBitmapCtrl.wrap', 'bool') +bl.type('GuiAnimatedBitmapCtrl::setBitmap:1', 'object') +bl.type('GuiArrayCtrl.clipToParent', 'bool') +bl.type('GuiArrayCtrl.enabled', 'bool') +bl.type('GuiArrayCtrl.visible', 'bool') +bl.type('GuiBackgroundCtrl.clipToParent', 'bool') +bl.type('GuiBackgroundCtrl.enabled', 'bool') +bl.type('GuiBackgroundCtrl.visible', 'bool') +bl.type('GuiBitmapBorderCtrl.clipToParent', 'bool') +bl.type('GuiBitmapBorderCtrl.enabled', 'bool') +bl.type('GuiBitmapBorderCtrl.visible', 'bool') +bl.type('GuiBitmapButtonCtrl.alignLeft', 'bool') +bl.type('GuiBitmapButtonCtrl.alignTop', 'bool') +bl.type('GuiBitmapButtonCtrl.clipToParent', 'bool') +bl.type('GuiBitmapButtonCtrl.enabled', 'bool') +bl.type('GuiBitmapButtonCtrl.lockAspectRatio', 'bool') +bl.type('GuiBitmapButtonCtrl.mKeepCached', 'bool') +bl.type('GuiBitmapButtonCtrl.overflowImage', 'bool') +bl.type('GuiBitmapButtonCtrl.visible', 'bool') +bl.type('GuiBitmapButtonCtrl::getColor:1', 'object') +bl.type('GuiBitmapButtonCtrl::setBitmap:1', 'object') +bl.type('GuiBitmapButtonCtrl::setColor:1', 'object') +bl.type('GuiBitmapCtrl.alignLeft', 'bool') +bl.type('GuiBitmapCtrl.alignTop', 'bool') +bl.type('GuiBitmapCtrl.clipToParent', 'bool') +bl.type('GuiBitmapCtrl.enabled', 'bool') +bl.type('GuiBitmapCtrl.keepCached', 'bool') +bl.type('GuiBitmapCtrl.lockAspectRatio', 'bool') +bl.type('GuiBitmapCtrl.mMultiply', 'bool') +bl.type('GuiBitmapCtrl.overflowImage', 'bool') +bl.type('GuiBitmapCtrl.visible', 'bool') +bl.type('GuiBitmapCtrl.wrap', 'bool') +bl.type('GuiBitmapCtrl::getColor:1', 'object') +bl.type('GuiBitmapCtrl::getPixelColor:1', 'object') +bl.type('GuiBitmapCtrl::setBitmap:1', 'object') +bl.type('GuiBitmapCtrl::setColor:1', 'object') +bl.type('GuiBitmapCtrl::setValue:1', 'object') +bl.type('GuiBorderButtonCtrl.clipToParent', 'bool') +bl.type('GuiBorderButtonCtrl.enabled', 'bool') +bl.type('GuiBorderButtonCtrl.visible', 'bool') +bl.type('GuiBubbleTextCtrl.clipToParent', 'bool') +bl.type('GuiBubbleTextCtrl.enabled', 'bool') +bl.type('GuiBubbleTextCtrl.visible', 'bool') +bl.type('GuiButtonBaseCtrl.clipToParent', 'bool') +bl.type('GuiButtonBaseCtrl.enabled', 'bool') +bl.type('GuiButtonBaseCtrl.visible', 'bool') +bl.type('GuiButtonBaseCtrl::getText:1', 'object') +bl.type('GuiButtonBaseCtrl::performClick:1', 'object') +bl.type('GuiButtonBaseCtrl::setText:1', 'object') +bl.type('GuiButtonCtrl.clipToParent', 'bool') +bl.type('GuiButtonCtrl.enabled', 'bool') +bl.type('GuiButtonCtrl.visible', 'bool') +bl.type('GuiCanvas.clipToParent', 'bool') +bl.type('GuiCanvas.enabled', 'bool') +bl.type('GuiCanvas.visible', 'bool') +bl.type('GuiCanvas::canTabFocus:1', 'object') +bl.type('GuiCanvas::canTabFocus:2', 'bool') +bl.type('GuiCanvas::checkCursor:1', 'object') +bl.type('GuiCanvas::checkTabFocus:1', 'object') +bl.type('GuiCanvas::cursorOff:1', 'object') +bl.type('GuiCanvas::cursorOn:1', 'object') +bl.type('GuiCanvas::getContent:1', 'object') +bl.type('GuiCanvas::getCursorPos:1', 'object') +bl.type('GuiCanvas::hideCursor:1', 'object') +bl.type('GuiCanvas::isCursorOn', 'bool') +bl.type('GuiCanvas::isCursorOn:1', 'object') +bl.type('GuiCanvas::popDialog:1', 'object') +bl.type('GuiCanvas::popDialog:2', 'object') +bl.type('GuiCanvas::popLayer:1', 'object') +bl.type('GuiCanvas::pushDialog:1', 'object') +bl.type('GuiCanvas::pushDialog:2', 'object') +bl.type('GuiCanvas::renderFront:1', 'object') +bl.type('GuiCanvas::renderFront:2', 'bool') +bl.type('GuiCanvas::repaint:1', 'object') +bl.type('GuiCanvas::reset:1', 'object') +bl.type('GuiCanvas::setContent:1', 'object') +bl.type('GuiCanvas::setContent:2', 'object') +bl.type('GuiCanvas::setCursor:1', 'object') +bl.type('GuiCanvas::setCursor:2', 'bool') +bl.type('GuiCanvas::setCursorPos:1', 'object') +bl.type('GuiCanvas::showCursor:1', 'object') +bl.type('GuiCanvas::tabNext:1', 'object') +bl.type('GuiCheckBoxCtrl.clipToParent', 'bool') +bl.type('GuiCheckBoxCtrl.enabled', 'bool') +bl.type('GuiCheckBoxCtrl.visible', 'bool') +bl.type('GuiChunkedBitmapCtrl.clipToParent', 'bool') +bl.type('GuiChunkedBitmapCtrl.enabled', 'bool') +bl.type('GuiChunkedBitmapCtrl.tile', 'bool') +bl.type('GuiChunkedBitmapCtrl.useVariable', 'bool') +bl.type('GuiChunkedBitmapCtrl.visible', 'bool') +bl.type('GuiChunkedBitmapCtrl::setBitmap:1', 'object') +bl.type('GuiClockHud.clipToParent', 'bool') +bl.type('GuiClockHud.enabled', 'bool') +bl.type('GuiClockHud.showFill', 'bool') +bl.type('GuiClockHud.showFrame', 'bool') +bl.type('GuiClockHud.visible', 'bool') +bl.type('GuiClockHud::getTime:1', 'object') +bl.type('GuiClockHud::setTime:1', 'object') +bl.type('GuiConsole.clipToParent', 'bool') +bl.type('GuiConsole.enabled', 'bool') +bl.type('GuiConsole.visible', 'bool') +bl.type('GuiConsoleEditCtrl.clipToParent', 'bool') +bl.type('GuiConsoleEditCtrl.enabled', 'bool') +bl.type('GuiConsoleEditCtrl.password', 'bool') +bl.type('GuiConsoleEditCtrl.sinkAllKeyEvents', 'bool') +bl.type('GuiConsoleEditCtrl.tabComplete', 'bool') +bl.type('GuiConsoleEditCtrl.useSiblingScroller', 'bool') +bl.type('GuiConsoleEditCtrl.visible', 'bool') +bl.type('GuiConsoleTextCtrl.clipToParent', 'bool') +bl.type('GuiConsoleTextCtrl.enabled', 'bool') +bl.type('GuiConsoleTextCtrl.visible', 'bool') +bl.type('GuiControl.clipToParent', 'bool') +bl.type('GuiControl.enabled', 'bool') +bl.type('GuiControl.visible', 'bool') +bl.type('GuiControl::ScaleText:1', 'object') +bl.type('GuiControl::getExtent:1', 'object') +bl.type('GuiControl::getHelpPage:1', 'object') +bl.type('GuiControl::getLowestChildPoint:1', 'object') +bl.type('GuiControl::getMinExtent:1', 'object') +bl.type('GuiControl::getPosition:1', 'object') +bl.type('GuiControl::getScreenPosition:1', 'object') +bl.type('GuiControl::getValue:1', 'object') +bl.type('GuiControl::isActive', 'bool') +bl.type('GuiControl::isActive:1', 'object') +bl.type('GuiControl::isAwake', 'bool') +bl.type('GuiControl::isAwake:1', 'object') +bl.type('GuiControl::isVisible', 'bool') +bl.type('GuiControl::isVisible:1', 'object') +bl.type('GuiControl::makeFirstResponder:1', 'object') +bl.type('GuiControl::makeFirstResponder:2', 'bool') +bl.type('GuiControl::resize:1', 'object') +bl.type('GuiControl::setActive:1', 'object') +bl.type('GuiControl::setActive:2', 'bool') +bl.type('GuiControl::setCentered:1', 'object') +bl.type('GuiControl::setCenteredX:1', 'object') +bl.type('GuiControl::setCenteredY:1', 'object') +bl.type('GuiControl::setHasRendered:1', 'object') +bl.type('GuiControl::setHasRendered:2', 'bool') +bl.type('GuiControl::setProfile:1', 'object') +bl.type('GuiControl::setProfile:2', 'object') +bl.type('GuiControl::setValue:1', 'object') +bl.type('GuiControl::setVisible:1', 'object') +bl.type('GuiControl::setVisible:2', 'bool') +bl.type('GuiControlListPopUp.clipToParent', 'bool') +bl.type('GuiControlListPopUp.enabled', 'bool') +bl.type('GuiControlListPopUp.visible', 'bool') +bl.type('GuiControlProfile.autoSizeHeight', 'bool') +bl.type('GuiControlProfile.autoSizeWidth', 'bool') +bl.type('GuiControlProfile.canKeyFocus', 'bool') +bl.type('GuiControlProfile.doFontOutline', 'bool') +bl.type('GuiControlProfile.modal', 'bool') +bl.type('GuiControlProfile.mouseOverSelected', 'bool') +bl.type('GuiControlProfile.numbersOnly', 'bool') +bl.type('GuiControlProfile.opaque', 'bool') +bl.type('GuiControlProfile.returnTab', 'bool') +bl.type('GuiControlProfile.tab', 'bool') +bl.type('GuiControlProfile::updateFont:1', 'object') +bl.type('GuiCrossHairHud.alignLeft', 'bool') +bl.type('GuiCrossHairHud.alignTop', 'bool') +bl.type('GuiCrossHairHud.clipToParent', 'bool') +bl.type('GuiCrossHairHud.enabled', 'bool') +bl.type('GuiCrossHairHud.keepCached', 'bool') +bl.type('GuiCrossHairHud.lockAspectRatio', 'bool') +bl.type('GuiCrossHairHud.mMultiply', 'bool') +bl.type('GuiCrossHairHud.overflowImage', 'bool') +bl.type('GuiCrossHairHud.visible', 'bool') +bl.type('GuiCrossHairHud.wrap', 'bool') +bl.type('GuiEditCtrl.clipToParent', 'bool') +bl.type('GuiEditCtrl.enabled', 'bool') +bl.type('GuiEditCtrl.visible', 'bool') +bl.type('GuiEditCtrl::addNewCtrl:1', 'object') +bl.type('GuiEditCtrl::addNewCtrl:2', 'object') +bl.type('GuiEditCtrl::bringToFront:1', 'object') +bl.type('GuiEditCtrl::deleteSelection:1', 'object') +bl.type('GuiEditCtrl::justify:1', 'object') +bl.type('GuiEditCtrl::loadSelection:1', 'object') +bl.type('GuiEditCtrl::moveSelection:1', 'object') +bl.type('GuiEditCtrl::pushToBack:1', 'object') +bl.type('GuiEditCtrl::saveSelection:1', 'object') +bl.type('GuiEditCtrl::select:1', 'object') +bl.type('GuiEditCtrl::select:2', 'object') +bl.type('GuiEditCtrl::selectAll:1', 'object') +bl.type('GuiEditCtrl::setCurrentAddSet:1', 'object') +bl.type('GuiEditCtrl::setCurrentAddSet:2', 'object') +bl.type('GuiEditCtrl::setRoot:1', 'object') +bl.type('GuiEditCtrl::setRoot:2', 'object') +bl.type('GuiEditCtrl::toggle:1', 'object') +bl.type('GuiEditor::onSelect:1', 'object') +bl.type('GuiEditorClassPopup::onSelect:1', 'object') +bl.type('GuiEditorContentList::onSelect:1', 'object') +bl.type('GuiEditorMenuBar::onMenuItemSelect:1', 'object') +bl.type('GuiEditorResList::onSelect:1', 'object') +bl.type('GuiEditorRuler.clipToParent', 'bool') +bl.type('GuiEditorRuler.enabled', 'bool') +bl.type('GuiEditorRuler.visible', 'bool') +bl.type('GuiEditorTreeView::onSelect:1', 'object') +bl.type('GuiFadeinBitmapCtrl.alignLeft', 'bool') +bl.type('GuiFadeinBitmapCtrl.alignTop', 'bool') +bl.type('GuiFadeinBitmapCtrl.clipToParent', 'bool') +bl.type('GuiFadeinBitmapCtrl.enabled', 'bool') +bl.type('GuiFadeinBitmapCtrl.keepCached', 'bool') +bl.type('GuiFadeinBitmapCtrl.lockAspectRatio', 'bool') +bl.type('GuiFadeinBitmapCtrl.mMultiply', 'bool') +bl.type('GuiFadeinBitmapCtrl.overflowImage', 'bool') +bl.type('GuiFadeinBitmapCtrl.visible', 'bool') +bl.type('GuiFadeinBitmapCtrl.wrap', 'bool') +bl.type('GuiFadeinBitmapCtrl::reset:1', 'object') +bl.type('GuiFilterCtrl.clipToParent', 'bool') +bl.type('GuiFilterCtrl.enabled', 'bool') +bl.type('GuiFilterCtrl.visible', 'bool') +bl.type('GuiFilterCtrl::getValue:1', 'object') +bl.type('GuiFilterCtrl::identity:1', 'object') +bl.type('GuiFilterCtrl::setValue:1', 'object') +bl.type('GuiFrameSetCtrl.autoBalance', 'bool') +bl.type('GuiFrameSetCtrl.clipToParent', 'bool') +bl.type('GuiFrameSetCtrl.enabled', 'bool') +bl.type('GuiFrameSetCtrl.visible', 'bool') +bl.type('GuiFrameSetCtrl::addColumn:1', 'object') +bl.type('GuiFrameSetCtrl::addRow:1', 'object') +bl.type('GuiFrameSetCtrl::frameBorder:1', 'object') +bl.type('GuiFrameSetCtrl::frameBorder:3', 'bool') +bl.type('GuiFrameSetCtrl::frameMinExtent:1', 'object') +bl.type('GuiFrameSetCtrl::frameMovable:1', 'object') +bl.type('GuiFrameSetCtrl::frameMovable:3', 'bool') +bl.type('GuiFrameSetCtrl::getColumnCount:1', 'object') +bl.type('GuiFrameSetCtrl::getColumnOffset:1', 'object') +bl.type('GuiFrameSetCtrl::getRowCount:1', 'object') +bl.type('GuiFrameSetCtrl::getRowOffset:1', 'object') +bl.type('GuiFrameSetCtrl::removeColumn:1', 'object') +bl.type('GuiFrameSetCtrl::removeRow:1', 'object') +bl.type('GuiFrameSetCtrl::setColumnOffset:1', 'object') +bl.type('GuiFrameSetCtrl::setRowOffset:1', 'object') +bl.type('GuiGraphCtrl.clipToParent', 'bool') +bl.type('GuiGraphCtrl.enabled', 'bool') +bl.type('GuiGraphCtrl.visible', 'bool') +bl.type('GuiGraphCtrl::addAutoPlot:1', 'object') +bl.type('GuiGraphCtrl::addDatum:1', 'object') +bl.type('GuiGraphCtrl::getDatum:1', 'object') +bl.type('GuiGraphCtrl::matchScale:1', 'object') +bl.type('GuiGraphCtrl::removeAutoPlot:1', 'object') +bl.type('GuiGraphCtrl::setGraphType:1', 'object') +bl.type('GuiHealthBarHud.clipToParent', 'bool') +bl.type('GuiHealthBarHud.displayEnergy', 'bool') +bl.type('GuiHealthBarHud.enabled', 'bool') +bl.type('GuiHealthBarHud.flipped', 'bool') +bl.type('GuiHealthBarHud.showFill', 'bool') +bl.type('GuiHealthBarHud.showFrame', 'bool') +bl.type('GuiHealthBarHud.visible', 'bool') +bl.type('GuiInputCtrl.clipToParent', 'bool') +bl.type('GuiInputCtrl.enabled', 'bool') +bl.type('GuiInputCtrl.visible', 'bool') +bl.type('GuiInspector.clipToParent', 'bool') +bl.type('GuiInspector.enabled', 'bool') +bl.type('GuiInspector.useFieldGrouping', 'bool') +bl.type('GuiInspector.visible', 'bool') +bl.type('GuiInspector::addDynamicField:1', 'object') +bl.type('GuiInspector::apply:1', 'object') +bl.type('GuiInspector::inspect:1', 'object') +bl.type('GuiInspector::inspect:2', 'object') +bl.type('GuiInspector::setAllGroupState:1', 'object') +bl.type('GuiInspector::setAllGroupState:2', 'bool') +bl.type('GuiInspector::setAllGroupStateScript:1', 'object') +bl.type('GuiInspector::toggleDynamicGroupExpand:1', 'object') +bl.type('GuiInspector::toggleDynamicGroupScript:1', 'object') +bl.type('GuiInspector::toggleGroupExpand:1', 'object') +bl.type('GuiInspector::toggleGroupExpand:2', 'object') +bl.type('GuiInspector::toggleGroupScript:1', 'object') +bl.type('GuiMLTextCtrl.allowColorChars', 'bool') +bl.type('GuiMLTextCtrl.autoResize', 'bool') +bl.type('GuiMLTextCtrl.clipToParent', 'bool') +bl.type('GuiMLTextCtrl.enabled', 'bool') +bl.type('GuiMLTextCtrl.selectable', 'bool') +bl.type('GuiMLTextCtrl.visible', 'bool') +bl.type('GuiMLTextCtrl::addText:1', 'object') +bl.type('GuiMLTextCtrl::addText:3', 'bool') +bl.type('GuiMLTextCtrl::forceReflow:1', 'object') +bl.type('GuiMLTextCtrl::getText:1', 'object') +bl.type('GuiMLTextCtrl::onAdd:1', 'object') +bl.type('GuiMLTextCtrl::onURL:1', 'object') +bl.type('GuiMLTextCtrl::scrollToTag:1', 'object') +bl.type('GuiMLTextCtrl::scrollToTop:1', 'object') +bl.type('GuiMLTextCtrl::setAlpha:1', 'object') +bl.type('GuiMLTextCtrl::setCursorPosition', 'bool') +bl.type('GuiMLTextCtrl::setCursorPosition:1', 'object') +bl.type('GuiMLTextCtrl::setText:1', 'object') +bl.type('GuiMLTextEditCtrl.allowColorChars', 'bool') +bl.type('GuiMLTextEditCtrl.autoResize', 'bool') +bl.type('GuiMLTextEditCtrl.clipToParent', 'bool') +bl.type('GuiMLTextEditCtrl.enabled', 'bool') +bl.type('GuiMLTextEditCtrl.selectable', 'bool') +bl.type('GuiMLTextEditCtrl.visible', 'bool') +bl.type('GuiMenuBar.clipToParent', 'bool') +bl.type('GuiMenuBar.enabled', 'bool') +bl.type('GuiMenuBar.visible', 'bool') +bl.type('GuiMenuBar::addMenu:1', 'object') +bl.type('GuiMenuBar::addMenuItem:1', 'object') +bl.type('GuiMenuBar::clearMenuItems:1', 'object') +bl.type('GuiMenuBar::clearMenus:1', 'object') +bl.type('GuiMenuBar::removeMenu:1', 'object') +bl.type('GuiMenuBar::removeMenuItem:1', 'object') +bl.type('GuiMenuBar::setMenuItemBitmap:1', 'object') +bl.type('GuiMenuBar::setMenuItemChecked:1', 'object') +bl.type('GuiMenuBar::setMenuItemChecked:4', 'bool') +bl.type('GuiMenuBar::setMenuItemEnable:1', 'object') +bl.type('GuiMenuBar::setMenuItemEnable:4', 'bool') +bl.type('GuiMenuBar::setMenuItemText:1', 'object') +bl.type('GuiMenuBar::setMenuItemVisible:1', 'object') +bl.type('GuiMenuBar::setMenuItemVisible:4', 'bool') +bl.type('GuiMenuBar::setMenuText:1', 'object') +bl.type('GuiMenuBar::setMenuVisible:1', 'object') +bl.type('GuiMenuBar::setMenuVisible:3', 'bool') +bl.type('GuiMessageVectorCtrl.clipToParent', 'bool') +bl.type('GuiMessageVectorCtrl.enabled', 'bool') +bl.type('GuiMessageVectorCtrl.visible', 'bool') +bl.type('GuiMessageVectorCtrl::attach', 'bool') +bl.type('GuiMessageVectorCtrl::attach:1', 'object') +bl.type('GuiMessageVectorCtrl::attach:2', 'object') +bl.type('GuiMessageVectorCtrl::detach:1', 'object') +bl.type('GuiMouseEventCtrl.clipToParent', 'bool') +bl.type('GuiMouseEventCtrl.enabled', 'bool') +bl.type('GuiMouseEventCtrl.lockMouse', 'bool') +bl.type('GuiMouseEventCtrl.visible', 'bool') +bl.type('GuiNoMouseCtrl.clipToParent', 'bool') +bl.type('GuiNoMouseCtrl.enabled', 'bool') +bl.type('GuiNoMouseCtrl.visible', 'bool') +bl.type('GuiObjectView.clipToParent', 'bool') +bl.type('GuiObjectView.enabled', 'bool') +bl.type('GuiObjectView.visible', 'bool') +bl.type('GuiObjectView::dumpView:1', 'object') +bl.type('GuiObjectView::hideNode:1', 'object') +bl.type('GuiObjectView::loadDSQ:1', 'object') +bl.type('GuiObjectView::mountObject:1', 'object') +bl.type('GuiObjectView::setCamera:1', 'object') +bl.type('GuiObjectView::setCameraRot:1', 'object') +bl.type('GuiObjectView::setEmpty:1', 'object') +bl.type('GuiObjectView::setIflFrame:1', 'object') +bl.type('GuiObjectView::setMouse:1', 'object') +bl.type('GuiObjectView::setNodeColor:1', 'object') +bl.type('GuiObjectView::setObject:1', 'object') +bl.type('GuiObjectView::setOrbitDist:1', 'object') +bl.type('GuiObjectView::setScale:1', 'object') +bl.type('GuiObjectView::setSequence:1', 'object') +bl.type('GuiObjectView::setThreadPos:1', 'object') +bl.type('GuiObjectView::unHideNode:1', 'object') +bl.type('GuiObjectView::unMountObject:1', 'object') +bl.type('GuiPlayerView.clipToParent', 'bool') +bl.type('GuiPlayerView.enabled', 'bool') +bl.type('GuiPlayerView.visible', 'bool') +bl.type('GuiPlayerView::setModel:1', 'object') +bl.type('GuiPlayerView::setSeq:1', 'object') +bl.type('GuiPopUpMenuCtrl.clipToParent', 'bool') +bl.type('GuiPopUpMenuCtrl.enabled', 'bool') +bl.type('GuiPopUpMenuCtrl.visible', 'bool') +bl.type('GuiPopUpMenuCtrl::add:1', 'object') +bl.type('GuiPopUpMenuCtrl::addFront:1', 'object') +bl.type('GuiPopUpMenuCtrl::addScheme:1', 'object') +bl.type('GuiPopUpMenuCtrl::clear:1', 'object') +bl.type('GuiPopUpMenuCtrl::findText:1', 'object') +bl.type('GuiPopUpMenuCtrl::forceClose:1', 'object') +bl.type('GuiPopUpMenuCtrl::forceOnAction:1', 'object') +bl.type('GuiPopUpMenuCtrl::getSelected:1', 'object') +bl.type('GuiPopUpMenuCtrl::getText:1', 'object') +bl.type('GuiPopUpMenuCtrl::getTextById:1', 'object') +bl.type('GuiPopUpMenuCtrl::onRemove:1', 'object') +bl.type('GuiPopUpMenuCtrl::replaceText:1', 'object') +bl.type('GuiPopUpMenuCtrl::replaceText:2', 'bool') +bl.type('GuiPopUpMenuCtrl::setEnumContent:1', 'object') +bl.type('GuiPopUpMenuCtrl::setSelected:1', 'object') +bl.type('GuiPopUpMenuCtrl::setText:1', 'object') +bl.type('GuiPopUpMenuCtrl::size:1', 'object') +bl.type('GuiPopUpMenuCtrl::sort:1', 'object') +bl.type('GuiProgressCtrl.clipToParent', 'bool') +bl.type('GuiProgressCtrl.enabled', 'bool') +bl.type('GuiProgressCtrl.visible', 'bool') +bl.type('GuiRadioCtrl.clipToParent', 'bool') +bl.type('GuiRadioCtrl.enabled', 'bool') +bl.type('GuiRadioCtrl.visible', 'bool') +bl.type('GuiScrollCtrl.clipToParent', 'bool') +bl.type('GuiScrollCtrl.constantThumbHeight', 'bool') +bl.type('GuiScrollCtrl.enabled', 'bool') +bl.type('GuiScrollCtrl.visible', 'bool') +bl.type('GuiScrollCtrl.willFirstRespond', 'bool') +bl.type('GuiScrollCtrl::scrollToBottom:1', 'object') +bl.type('GuiScrollCtrl::scrollToTop:1', 'object') +bl.type('GuiShapeNameHud.clipToParent', 'bool') +bl.type('GuiShapeNameHud.enabled', 'bool') +bl.type('GuiShapeNameHud.showFill', 'bool') +bl.type('GuiShapeNameHud.showFrame', 'bool') +bl.type('GuiShapeNameHud.visible', 'bool') +bl.type('GuiSliderCtrl.clipToParent', 'bool') +bl.type('GuiSliderCtrl.enabled', 'bool') +bl.type('GuiSliderCtrl.snap', 'bool') +bl.type('GuiSliderCtrl.visible', 'bool') +bl.type('GuiSliderCtrl::getValue:1', 'object') +bl.type('GuiSpeedometerHud.alignLeft', 'bool') +bl.type('GuiSpeedometerHud.alignTop', 'bool') +bl.type('GuiSpeedometerHud.clipToParent', 'bool') +bl.type('GuiSpeedometerHud.enabled', 'bool') +bl.type('GuiSpeedometerHud.keepCached', 'bool') +bl.type('GuiSpeedometerHud.lockAspectRatio', 'bool') +bl.type('GuiSpeedometerHud.mMultiply', 'bool') +bl.type('GuiSpeedometerHud.overflowImage', 'bool') +bl.type('GuiSpeedometerHud.visible', 'bool') +bl.type('GuiSpeedometerHud.wrap', 'bool') +bl.type('GuiSwatchCtrl.clipToParent', 'bool') +bl.type('GuiSwatchCtrl.enabled', 'bool') +bl.type('GuiSwatchCtrl.visible', 'bool') +bl.type('GuiSwatchCtrl::getColor:1', 'object') +bl.type('GuiSwatchCtrl::setColor:1', 'object') +bl.type('GuiTSCtrl.clipToParent', 'bool') +bl.type('GuiTSCtrl.enabled', 'bool') +bl.type('GuiTSCtrl.visible', 'bool') +bl.type('GuiTextCtrl.clipToParent', 'bool') +bl.type('GuiTextCtrl.enabled', 'bool') +bl.type('GuiTextCtrl.visible', 'bool') +bl.type('GuiTextCtrl::getPixelWidth:1', 'object') +bl.type('GuiTextCtrl::setText:1', 'object') +bl.type('GuiTextEditCtrl.clipToParent', 'bool') +bl.type('GuiTextEditCtrl.enabled', 'bool') +bl.type('GuiTextEditCtrl.password', 'bool') +bl.type('GuiTextEditCtrl.sinkAllKeyEvents', 'bool') +bl.type('GuiTextEditCtrl.tabComplete', 'bool') +bl.type('GuiTextEditCtrl.visible', 'bool') +bl.type('GuiTextEditCtrl::getCursorPos:1', 'object') +bl.type('GuiTextEditCtrl::restrictNumberInput:1', 'object') +bl.type('GuiTextEditCtrl::setCursorPos:1', 'object') +bl.type('GuiTextEditCtrl::updateHistorySize:1', 'object') +bl.type('GuiTextEditSliderCtrl.clipToParent', 'bool') +bl.type('GuiTextEditSliderCtrl.enabled', 'bool') +bl.type('GuiTextEditSliderCtrl.password', 'bool') +bl.type('GuiTextEditSliderCtrl.sinkAllKeyEvents', 'bool') +bl.type('GuiTextEditSliderCtrl.tabComplete', 'bool') +bl.type('GuiTextEditSliderCtrl.visible', 'bool') +bl.type('GuiTextListCtrl.clipColumnText', 'bool') +bl.type('GuiTextListCtrl.clipToParent', 'bool') +bl.type('GuiTextListCtrl.enabled', 'bool') +bl.type('GuiTextListCtrl.enumerate', 'bool') +bl.type('GuiTextListCtrl.fitParentWidth', 'bool') +bl.type('GuiTextListCtrl.resizeCell', 'bool') +bl.type('GuiTextListCtrl.visible', 'bool') +bl.type('GuiTextListCtrl::addRow:1', 'object') +bl.type('GuiTextListCtrl::clear:1', 'object') +bl.type('GuiTextListCtrl::clearSelection:1', 'object') +bl.type('GuiTextListCtrl::findTextIndex:1', 'object') +bl.type('GuiTextListCtrl::getRowId:1', 'object') +bl.type('GuiTextListCtrl::getRowNumById:1', 'object') +bl.type('GuiTextListCtrl::getRowText:1', 'object') +bl.type('GuiTextListCtrl::getRowTextById:1', 'object') +bl.type('GuiTextListCtrl::getSelectedId:1', 'object') +bl.type('GuiTextListCtrl::isRowActive', 'bool') +bl.type('GuiTextListCtrl::isRowActive:1', 'object') +bl.type('GuiTextListCtrl::removeRow:1', 'object') +bl.type('GuiTextListCtrl::removeRowById:1', 'object') +bl.type('GuiTextListCtrl::rowCount:1', 'object') +bl.type('GuiTextListCtrl::scrollVisible:1', 'object') +bl.type('GuiTextListCtrl::setRowActive:1', 'object') +bl.type('GuiTextListCtrl::setRowActive:3', 'bool') +bl.type('GuiTextListCtrl::setRowById:1', 'object') +bl.type('GuiTextListCtrl::setSelectedById:1', 'object') +bl.type('GuiTextListCtrl::setSelectedRow:1', 'object') +bl.type('GuiTextListCtrl::sort:1', 'object') +bl.type('GuiTextListCtrl::sort:3', 'bool') +bl.type('GuiTextListCtrl::sortNumerical:1', 'object') +bl.type('GuiTextListCtrl::sortNumerical:3', 'bool') +bl.type('GuiTreeViewCtrl.allowMultipleSelections', 'bool') +bl.type('GuiTreeViewCtrl.clipToParent', 'bool') +bl.type('GuiTreeViewCtrl.enabled', 'bool') +bl.type('GuiTreeViewCtrl.recurseSets', 'bool') +bl.type('GuiTreeViewCtrl.visible', 'bool') +bl.type('GuiTreeViewCtrl::open:1', 'object') +bl.type('GuiTreeViewCtrl::open:2', 'object') +bl.type('GuiWindowCtrl.canClose', 'bool') +bl.type('GuiWindowCtrl.canMaximize', 'bool') +bl.type('GuiWindowCtrl.canMinimize', 'bool') +bl.type('GuiWindowCtrl.canMove', 'bool') +bl.type('GuiWindowCtrl.clipToParent', 'bool') +bl.type('GuiWindowCtrl.enabled', 'bool') +bl.type('GuiWindowCtrl.resizeHeight', 'bool') +bl.type('GuiWindowCtrl.resizeWidth', 'bool') +bl.type('GuiWindowCtrl.visible', 'bool') +bl.type('HTTPObject::get:1', 'object') +bl.type('HTTPObject::post:1', 'object') +bl.type('HateImage::onDone:1', 'object') +bl.type('HeapQueue::_demote:1', 'object') +bl.type('HeapQueue::_promote:1', 'object') +bl.type('HeapQueue::compare:1', 'object') +bl.type('HeapQueue::onAdd:1', 'object') +bl.type('HeapQueue::pop:1', 'object') +bl.type('HeapQueue::push:1', 'object') +bl.type('HeapQueue::update:1', 'object') +bl.type('HelpDlg::onWake:1', 'object') +bl.type('HelpFileList::onSelect:1', 'object') +bl.type('HelpText::setText:1', 'object') +bl.type('HorseArmor::onAdd:1', 'object') +bl.type('HorseArmor::onDriverLeave:1', 'object') +bl.type('HorseHoleBot::onAdd:1', 'object') +bl.type('HorseHoleBot::onBotCollision:1', 'object') +bl.type('HorseHoleBot::onBotDamage:1', 'object') +bl.type('HorseHoleBot::onBotFollow:1', 'object') +bl.type('HorseHoleBot::onBotLoop:1', 'object') +bl.type('InspectAddFieldDlg::doAction:1', 'object') +bl.type('InspectTreeView::onSelect:1', 'object') +bl.type('Item.canSetIFLs', 'bool') +bl.type('Item.collideable', 'bool') +bl.type('Item.rotate', 'bool') +bl.type('Item.static', 'bool') +bl.type('Item::Respawn:1', 'object') +bl.type('Item::fadeIn:1', 'object') +bl.type('Item::fadeOut:1', 'object') +bl.type('Item::getLastStickyNormal:1', 'object') +bl.type('Item::getLastStickyPos:1', 'object') +bl.type('Item::getRespawnTime:1', 'object') +bl.type('Item::isRotating', 'bool') +bl.type('Item::isRotating:1', 'object') +bl.type('Item::isStatic', 'bool') +bl.type('Item::isStatic:1', 'object') +bl.type('Item::schedulePop:1', 'object') +bl.type('Item::setCollisionTimeout', 'bool') +bl.type('Item::setCollisionTimeout:1', 'object') +bl.type('Item::setCollisionTimeout:2', 'object') +bl.type('Item::setRespawnTime:1', 'object') +bl.type('Item::setThrower:1', 'object') +bl.type('ItemData.doColorShift', 'bool') +bl.type('ItemData.emap', 'bool') +bl.type('ItemData.firstPersonOnly', 'bool') +bl.type('ItemData.inheritEnergyFromMount', 'bool') +bl.type('ItemData.isInvincible', 'bool') +bl.type('ItemData.lightOnlyStatic', 'bool') +bl.type('ItemData.observeThroughObject', 'bool') +bl.type('ItemData.renderWhenDestroyed', 'bool') +bl.type('ItemData.sticky', 'bool') +bl.type('ItemData.thirdPersonOnly', 'bool') +bl.type('ItemData.useEyePoint', 'bool') +bl.type('ItemData::create:1', 'object') +bl.type('ItemData::onAdd:1', 'object') +bl.type('ItemData::onBallCollision:1', 'object') +bl.type('ItemData::onCollision:1', 'object') +bl.type('ItemData::onPickup:1', 'object') +bl.type('ItemData::onThrow:1', 'object') +bl.type('ItemData::onUse:1', 'object') +bl.type('ItemImage::onMount:1', 'object') +bl.type('ItemImage::onUnMount:1', 'object') +bl.type('JMG_List::onSelect:1', 'object') +bl.type('JMG_Slayer::createMinigame:1', 'object') +bl.type('JMG_Slayer::editMinigame:1', 'object') +bl.type('JMG_Slayer::onWake:1', 'object') +bl.type('JoinServerGuiBS::ClickBack:1', 'object') +bl.type('JoinServerGuiBS::cancel:1', 'object') +bl.type('JoinServerGuiBS::exit:1', 'object') +bl.type('JoinServerGuiBS::join:1', 'object') +bl.type('JoinServerGuiBS::onWake:1', 'object') +bl.type('JoinServerGuiBS::queryLan:1', 'object') +bl.type('JoinServerGuiBS::queryWebMaster:1', 'object') +bl.type('JoinServerGuiBS::update:1', 'object') +bl.type('JoinServerPassGui::cancel:1', 'object') +bl.type('JoinServerPassGui::enterPass:1', 'object') +bl.type('LeftHandedGunImage::onFire:1', 'object') +bl.type('LeftHandedGunImage::onMount:1', 'object') +bl.type('LeftHandedGunImage::onUnMount:1', 'object') +bl.type('Lightning.useFog', 'bool') +bl.type('Lightning::strikeObject:1', 'object') +bl.type('Lightning::strikeObject:2', 'object') +bl.type('Lightning::strikeRandomPoint:1', 'object') +bl.type('Lightning::warningFlashes:1', 'object') +bl.type('LoadBricksGui::ClickOwnership:1', 'object') +bl.type('LoadBricksGui::onSleep:1', 'object') +bl.type('LoadBricksGui::onWake:1', 'object') +bl.type('LoadingGui::onAdd:1', 'object') +bl.type('LoadingGui::onSleep:1', 'object') +bl.type('LoadingGui::onWake:1', 'object') +bl.type('LoveImage::onDone:1', 'object') +bl.type('MM_AuthBar::blinkFail:1', 'object') +bl.type('MM_AuthBar::blinkSuccess:1', 'object') +bl.type('MainMenuGui::PlayMusic:1', 'object') +bl.type('MainMenuGui::buildScreenshotList:1', 'object') +bl.type('MainMenuGui::clickJoinBS:1', 'object') +bl.type('MainMenuGui::clickNameButton:1', 'object') +bl.type('MainMenuGui::clickOptions:1', 'object') +bl.type('MainMenuGui::clickPlayer:1', 'object') +bl.type('MainMenuGui::clickStart:1', 'object') +bl.type('MainMenuGui::clickSteam:1', 'object') +bl.type('MainMenuGui::clickUnlock:1', 'object') +bl.type('MainMenuGui::hideButtons:1', 'object') +bl.type('MainMenuGui::onRender:1', 'object') +bl.type('MainMenuGui::onSleep:1', 'object') +bl.type('MainMenuGui::onWake:1', 'object') +bl.type('MainMenuGui::retryAuth:1', 'object') +bl.type('MainMenuGui::showButtons:1', 'object') +bl.type('ManualJoin::onWake:1', 'object') +bl.type('MessageBoxOKCancelDlg::onSleep:1', 'object') +bl.type('MessageBoxOKDlg::onSleep:1', 'object') +bl.type('MessageBoxYesNoDlg::onSleep:1', 'object') +bl.type('MessageVector::clear:1', 'object') +bl.type('MessageVector::deleteLine', 'bool') +bl.type('MessageVector::deleteLine:1', 'object') +bl.type('MessageVector::dump:1', 'object') +bl.type('MessageVector::getLineIndexByTag:1', 'object') +bl.type('MessageVector::getLineTag:1', 'object') +bl.type('MessageVector::getLineText:1', 'object') +bl.type('MessageVector::getLineTextByTag:1', 'object') +bl.type('MessageVector::getNumLines:1', 'object') +bl.type('MessageVector::insertLine', 'bool') +bl.type('MessageVector::insertLine:1', 'object') +bl.type('MessageVector::popBackLine', 'bool') +bl.type('MessageVector::popBackLine:1', 'object') +bl.type('MessageVector::popFrontLine', 'bool') +bl.type('MessageVector::popFrontLine:1', 'object') +bl.type('MessageVector::pushBackLine:1', 'object') +bl.type('MessageVector::pushFrontLine:1', 'object') +bl.type('MiniGameInviteGui::ClickAccept:1', 'object') +bl.type('MiniGameInviteGui::ClickIgnore:1', 'object') +bl.type('MiniGameInviteGui::ClickReject:1', 'object') +bl.type('MiniGameInviteGui::Ignore:1', 'object') +bl.type('MiniGameInviteGui::onSleep:1', 'object') +bl.type('MiniGameInviteGui::onWake:1', 'object') +bl.type('MiniGameSO::reset:1', 'object') +bl.type('MissionMarker.canSetIFLs', 'bool') +bl.type('MissionMarkerData.emap', 'bool') +bl.type('MissionMarkerData.firstPersonOnly', 'bool') +bl.type('MissionMarkerData.inheritEnergyFromMount', 'bool') +bl.type('MissionMarkerData.isInvincible', 'bool') +bl.type('MissionMarkerData.observeThroughObject', 'bool') +bl.type('MissionMarkerData.renderWhenDestroyed', 'bool') +bl.type('MissionMarkerData.thirdPersonOnly', 'bool') +bl.type('MissionMarkerData.useEyePoint', 'bool') +bl.type('MissionMarkerData::create:1', 'object') +bl.type('NMH_Type::send:1', 'object') +bl.type('NMH_Type::type:1', 'object') +bl.type('NetConnection::cancelConnect:1', 'object') +bl.type('NetConnection::checkMaxRate:1', 'object') +bl.type('NetConnection::clearPaths:1', 'object') +bl.type('NetConnection::connect:1', 'object') +bl.type('NetConnection::connectArranged:1', 'object') +bl.type('NetConnection::connectLocal:1', 'object') +bl.type('NetConnection::getAddress:1', 'object') +bl.type('NetConnection::getFinishedInitialGhost', 'bool') +bl.type('NetConnection::getFinishedInitialGhost:1', 'object') +bl.type('NetConnection::getGhostID:1', 'object') +bl.type('NetConnection::getGhostsActive:1', 'object') +bl.type('NetConnection::getPacketLoss:1', 'object') +bl.type('NetConnection::getPing:1', 'object') +bl.type('NetConnection::getPort:1', 'object') +bl.type('NetConnection::getProtocolVersion:1', 'object') +bl.type('NetConnection::getRawIP:1', 'object') +bl.type('NetConnection::isLan', 'bool') +bl.type('NetConnection::isLan:1', 'object') +bl.type('NetConnection::isLocal', 'bool') +bl.type('NetConnection::isLocal:1', 'object') +bl.type('NetConnection::isLocalConnection', 'bool') +bl.type('NetConnection::isLocalConnection:1', 'object') +bl.type('NetConnection::resolveGhostID:1', 'object') +bl.type('NetConnection::resolveObjectFromGhostIndex', 'object') +bl.type('NetConnection::resolveObjectFromGhostIndex:1', 'object') +bl.type('NetConnection::sendDisconnectPacket:1', 'object') +bl.type('NetConnection::setFinishedInitialGhost:1', 'object') +bl.type('NetConnection::setFinishedInitialGhost:2', 'bool') +bl.type('NetConnection::transmitPaths:1', 'object') +bl.type('NetGraph::cancel:1', 'object') +bl.type('NetGraph::toggleKey:1', 'object') +bl.type('NetGraph::toggleNetGraph:1', 'object') +bl.type('NetGraph::updateStats:1', 'object') +bl.type('NetObject::clearScopeToClient:1', 'object') +bl.type('NetObject::getGhostID:1', 'object') +bl.type('NetObject::scopeToClient:1', 'object') +bl.type('NetObject::scopeToClient:2', 'object') +bl.type('NetObject::setScopeAlways:1', 'object') +bl.type('NewChatSO::addLine:1', 'object') +bl.type('NewPlayerListGui::clickList:1', 'object') +bl.type('NewPlayerListGui::onWake:1', 'object') +bl.type('Observer::onTrigger:1', 'object') +bl.type('OpenALInitDriver', 'bool') +bl.type('OptAudioDriverList::onSelect:1', 'object') +bl.type('OptGraphicsBPPMenu::init:1', 'object') +bl.type('OptGraphicsBorderlessToggle::onAction:1', 'object') +bl.type('OptGraphicsDriverMenu::onSelect:1', 'object') +bl.type('OptGraphicsFullscreenToggle::onAction:1', 'object') +bl.type('OptGraphicsResolutionMenu::init:1', 'object') +bl.type('OptGraphicsResolutionMenu::onSelect:1', 'object') +bl.type('OptRemapInputCtrl::onInputEvent:1', 'object') +bl.type('OptRemapList::doRemap:1', 'object') +bl.type('OptRemapList::fillList:1', 'object') +bl.type('OptScreenshotMenu::init:1', 'object') +bl.type('PE_EmitterEditor::onNewEmitter:1', 'object') +bl.type('PE_EmitterEditor::save:1', 'object') +bl.type('PE_EmitterEditor::updateControls:1', 'object') +bl.type('PE_EmitterEditor::updateEmitter:1', 'object') +bl.type('PE_ParticleEditor::onNewParticle:1', 'object') +bl.type('PE_ParticleEditor::save:1', 'object') +bl.type('PE_ParticleEditor::updateControls:1', 'object') +bl.type('PE_ParticleEditor::updateParticle:1', 'object') +bl.type('PSD_Window::SetAllPrintRatiosGui:1', 'object') +bl.type('PSD_Window::ShowAllPrintRatiosTab:1', 'object') +bl.type('PainHighImage::onDone:1', 'object') +bl.type('PainLowImage::onDone:1', 'object') +bl.type('PainMidImage::onDone:1', 'object') +bl.type('ParticleData.animateTexture', 'bool') +bl.type('ParticleData.useInvAlpha', 'bool') +bl.type('ParticleData::reload:1', 'object') +bl.type('ParticleEditor::initEditor:1', 'object') +bl.type('ParticleEditor::openEmitterPane:1', 'object') +bl.type('ParticleEditor::openParticlePane:1', 'object') +bl.type('ParticleEditor::resetEmitterNode:1', 'object') +bl.type('ParticleEditor::startup:1', 'object') +bl.type('ParticleEditor::updateEmitterNode:1', 'object') +bl.type('ParticleEmitterData.doDetail', 'bool') +bl.type('ParticleEmitterData.doFalloff', 'bool') +bl.type('ParticleEmitterData.orientOnVelocity', 'bool') +bl.type('ParticleEmitterData.orientParticles', 'bool') +bl.type('ParticleEmitterData.overrideAdvance', 'bool') +bl.type('ParticleEmitterData.useEmitterColors', 'bool') +bl.type('ParticleEmitterData.useEmitterSizes', 'bool') +bl.type('ParticleEmitterData::reload:1', 'object') +bl.type('ParticleEmitterNode.pointPlacement', 'bool') +bl.type('ParticleEmitterNode.spherePlacement', 'bool') +bl.type('ParticleEmitterNode::getEmitterDataBlock:1', 'object') +bl.type('ParticleEmitterNode::onRemove:1', 'object') +bl.type('ParticleEmitterNode::setColor:1', 'object') +bl.type('ParticleEmitterNode::setEmitterDataBlock:1', 'object') +bl.type('Path.isLooping', 'bool') +bl.type('Path::getPathId:1', 'object') +bl.type('PathCamera.canSetIFLs', 'bool') +bl.type('PathCamera::popFront:1', 'object') +bl.type('PathCamera::pushBack:1', 'object') +bl.type('PathCamera::pushFront:1', 'object') +bl.type('PathCamera::reset:1', 'object') +bl.type('PathCamera::setPosition:1', 'object') +bl.type('PathCamera::setState:1', 'object') +bl.type('PathCamera::setTarget:1', 'object') +bl.type('PathCameraData.emap', 'bool') +bl.type('PathCameraData.firstPersonOnly', 'bool') +bl.type('PathCameraData.inheritEnergyFromMount', 'bool') +bl.type('PathCameraData.isInvincible', 'bool') +bl.type('PathCameraData.observeThroughObject', 'bool') +bl.type('PathCameraData.renderWhenDestroyed', 'bool') +bl.type('PathCameraData.thirdPersonOnly', 'bool') +bl.type('PathCameraData.useEyePoint', 'bool') +bl.type('PhysicalZone.isWater', 'bool') +bl.type('PhysicalZone::activate:1', 'object') +bl.type('PhysicalZone::deactivate:1', 'object') +bl.type('PhysicalZone::sendUpdate:1', 'object') +bl.type('PhysicalZone::setAppliedForce:1', 'object') +bl.type('PhysicalZone::setWaterColor:1', 'object') +bl.type('PlayGui::createInvHUD:1', 'object') +bl.type('Player.canSetIFLs', 'bool') +bl.type('Player::ActivateStuff:1', 'object') +bl.type('Player::checkDismountPoint', 'bool') +bl.type('Player::checkDismountPoint:1', 'object') +bl.type('Player::clearControlObject:1', 'object') +bl.type('Player::emote:1', 'object') +bl.type('Player::getControlObject:1', 'object') +bl.type('Player::getHackPosition:1', 'object') +bl.type('Player::getMaxBackwardSpeed:1', 'object') +bl.type('Player::getMaxCrouchBackwardSpeed:1', 'object') +bl.type('Player::getMaxCrouchForwardSpeed:1', 'object') +bl.type('Player::getMaxCrouchSideSpeed:1', 'object') +bl.type('Player::getMaxForwardSpeed:1', 'object') +bl.type('Player::getMaxSideSpeed:1', 'object') +bl.type('Player::getMaxUnderwaterBackwardSpeed:1', 'object') +bl.type('Player::getMaxUnderwaterForwardSpeed:1', 'object') +bl.type('Player::getMaxUnderwaterSideSpeed:1', 'object') +bl.type('Player::getState:1', 'object') +bl.type('Player::getWorldSpaceMovement', 'bool') +bl.type('Player::getWorldSpaceMovement:1', 'object') +bl.type('Player::isCrouched', 'bool') +bl.type('Player::isCrouched:1', 'object') +bl.type('Player::isFirstPerson', 'bool') +bl.type('Player::isFirstPerson:1', 'object') +bl.type('Player::setActionThread', 'bool') +bl.type('Player::setActionThread:1', 'object') +bl.type('Player::setActionThread:3', 'bool') +bl.type('Player::setActionThread:4', 'bool') +bl.type('Player::setArmThread', 'bool') +bl.type('Player::setArmThread:1', 'object') +bl.type('Player::setControlObject', 'bool') +bl.type('Player::setControlObject:1', 'object') +bl.type('Player::setControlObject:2', 'object') +bl.type('Player::setDecalName:1', 'object') +bl.type('Player::setFaceName:1', 'object') +bl.type('Player::setHeadUp', 'bool') +bl.type('Player::setHeadUp:1', 'object') +bl.type('Player::setHeadUp:2', 'bool') +bl.type('Player::setLookLimits:1', 'object') +bl.type('Player::setMaxBackwardSpeed:1', 'object') +bl.type('Player::setMaxCrouchBackwardSpeed:1', 'object') +bl.type('Player::setMaxCrouchForwardSpeed:1', 'object') +bl.type('Player::setMaxCrouchSideSpeed:1', 'object') +bl.type('Player::setMaxForwardSpeed:1', 'object') +bl.type('Player::setMaxSideSpeed:1', 'object') +bl.type('Player::setMaxUnderwaterBackwardSpeed:1', 'object') +bl.type('Player::setMaxUnderwaterForwardSpeed:1', 'object') +bl.type('Player::setMaxUnderwaterSideSpeed:1', 'object') +bl.type('Player::setWorldSpaceMovement:1', 'object') +bl.type('Player::setWorldSpaceMovement:2', 'bool') +bl.type('PlayerData.canJet', 'bool') +bl.type('PlayerData.canRide', 'bool') +bl.type('PlayerData.emap', 'bool') +bl.type('PlayerData.firstPersonOnly', 'bool') +bl.type('PlayerData.inheritEnergyFromMount', 'bool') +bl.type('PlayerData.isInvincible', 'bool') +bl.type('PlayerData.observeThroughObject', 'bool') +bl.type('PlayerData.renderFirstPerson', 'bool') +bl.type('PlayerData.renderWhenDestroyed', 'bool') +bl.type('PlayerData.rideAble', 'bool') +bl.type('PlayerData.thirdPersonOnly', 'bool') +bl.type('PlayerData.useEyePoint', 'bool') +bl.type('PlayerData::onDriverLeave:1', 'object') +bl.type('PlayerSportArmor::onTrigger:1', 'object') +bl.type('PlayerSportTurboArmor::onTrigger:1', 'object') +bl.type('PlayerTeleportImage::onDone:1', 'object') +bl.type('Precipitation.doCollision', 'bool') +bl.type('Precipitation.rotateWithCamVel', 'bool') +bl.type('Precipitation.useTrueBillboards', 'bool') +bl.type('Precipitation.useTurbulence', 'bool') +bl.type('Precipitation::setPercentange:1', 'object') +bl.type('PrintGunImage::onFire:1', 'object') +bl.type('PrintGunImage::onHitObject:1', 'object') +bl.type('PrintSelectorDlg::onSleep:1', 'object') +bl.type('PrintSelectorDlg::onWake:1', 'object') +bl.type('Projectile.sourceObject', 'object') +bl.type('Projectile::Bounce:1', 'object') +bl.type('Projectile::Redirect:1', 'object') +bl.type('Projectile::explode:1', 'object') +bl.type('Projectile::getLastImpactNormal:1', 'object') +bl.type('Projectile::getLastImpactPosition:1', 'object') +bl.type('Projectile::getLastImpactVelocity:1', 'object') +bl.type('Projectile::getVelocity:1', 'object') +bl.type('Projectile::onAdd:1', 'object') +bl.type('Projectile::playSportBallSound:1', 'object') +bl.type('ProjectileData.collideWithPlayers', 'bool') +bl.type('ProjectileData.explodeOnDeath', 'bool') +bl.type('ProjectileData.explodeOnPlayerImpact', 'bool') +bl.type('ProjectileData.hasLight', 'bool') +bl.type('ProjectileData.hasWaterLight', 'bool') +bl.type('ProjectileData.isBallistic', 'bool') +bl.type('ProjectileData::Damage:1', 'object') +bl.type('ProjectileData::impactImpulse:1', 'object') +bl.type('ProjectileData::onCollision:1', 'object') +bl.type('ProjectileData::onExplode:1', 'object') +bl.type('ProjectileData::radiusDamage:1', 'object') +bl.type('ProjectileData::radiusImpulse:1', 'object') +bl.type('QueueSO::dumpVals:1', 'object') +bl.type('QueueSO::pop:1', 'object') +bl.type('QueueSO::push:1', 'object') +bl.type('QuotaObject.AutoDelete', 'bool') +bl.type('QuotaObject::dumpAllocs:1', 'object') +bl.type('QuotaObject::getAllocs_Schedules:1', 'object') +bl.type('QuotaObject::killObjects:1', 'object') +bl.type('QuotaObject::setAllocs_Environment:1', 'object') +bl.type('QuotaObject::setAllocs_Item:1', 'object') +bl.type('QuotaObject::setAllocs_Misc:1', 'object') +bl.type('QuotaObject::setAllocs_Player:1', 'object') +bl.type('QuotaObject::setAllocs_Projectile:1', 'object') +bl.type('QuotaObject::setAllocs_Schedules:1', 'object') +bl.type('QuotaObject::setAllocs_Vehicle:1', 'object') +bl.type('SA_directoryList::onSelect:1', 'object') +bl.type('SA_fileList::onSelect:1', 'object') +bl.type('SO_ClientTeam::addMember:1', 'object') +bl.type('SO_ClientTeam::removeMember:1', 'object') +bl.type('SO_ClientTeam::setCaptain:1', 'object') +bl.type('SO_ClientTeamManager::addTeam:1', 'object') +bl.type('SO_ClientTeamManager::dumpTeams:1', 'object') +bl.type('SO_ClientTeamManager::findTeamByID:1', 'object') +bl.type('SO_ClientTeamManager::removeTeam:1', 'object') +bl.type('SO_ClientTeamManager::setTeamName:1', 'object') +bl.type('SavingGui::onRender:1', 'object') +bl.type('SavingGui::onWake:1', 'object') +bl.type('SavingGui::save:1', 'object') +bl.type('SceneObject::getForwardVector:1', 'object') +bl.type('SceneObject::getObjectBox:1', 'object') +bl.type('SceneObject::getPosition:1', 'object') +bl.type('SceneObject::getScale:1', 'object') +bl.type('SceneObject::getTransform:1', 'object') +bl.type('SceneObject::getUpVector:1', 'object') +bl.type('SceneObject::getWorldBox:1', 'object') +bl.type('SceneObject::getWorldBoxCenter:1', 'object') +bl.type('SceneObject::setScale:1', 'object') +bl.type('SceneObject::setTransform:1', 'object') +bl.type('ScopeAlwaysShape.canSetIFLs', 'bool') +bl.type('ScriptObject::getVariable:1', 'object') +bl.type('ScriptObject::setVariable:1', 'object') +bl.type('SelectNetworkGui::onSleep:1', 'object') +bl.type('SelectNetworkGui::onWake:1', 'object') +bl.type('ServerSO::Display:1', 'object') +bl.type('ServerSO::serialize:1', 'object') +bl.type('ServerSettingsGui::ApplyVariablesToGui:1', 'object') +bl.type('ServerSettingsGui::ClickBack:1', 'object') +bl.type('ServerSettingsGui::clickInternet:1', 'object') +bl.type('ServerSettingsGui::clickLAN:1', 'object') +bl.type('ServerSettingsGui::clickLaunchGame:1', 'object') +bl.type('ServerSettingsGui::clickSinglePlayer:1', 'object') +bl.type('ServerSettingsGui::copyVariablesToPrefs:1', 'object') +bl.type('ServerSettingsGui::getVariablesFromFile:1', 'object') +bl.type('ServerSettingsGui::getVariablesFromGui:1', 'object') +bl.type('ServerSettingsGui::onRender:1', 'object') +bl.type('ServerSettingsGui::onWake:1', 'object') +bl.type('ShapeBase.canSetIFLs', 'bool') +bl.type('ShapeBase::applyDamage:1', 'object') +bl.type('ShapeBase::applyImpulse', 'bool') +bl.type('ShapeBase::applyImpulse:1', 'object') +bl.type('ShapeBase::applyRepair:1', 'object') +bl.type('ShapeBase::canCloak', 'bool') +bl.type('ShapeBase::canCloak:1', 'object') +bl.type('ShapeBase::disableNodeColor:1', 'object') +bl.type('ShapeBase::getCameraFov:1', 'object') +bl.type('ShapeBase::getControllingClient:1', 'object') +bl.type('ShapeBase::getControllingObject', 'object') +bl.type('ShapeBase::getControllingObject:1', 'object') +bl.type('ShapeBase::getDamageFlash:1', 'object') +bl.type('ShapeBase::getDamageLevel:1', 'object') +bl.type('ShapeBase::getDamagePercent:1', 'object') +bl.type('ShapeBase::getDamageState:1', 'object') +bl.type('ShapeBase::getEnergyLevel:1', 'object') +bl.type('ShapeBase::getEnergyPercent:1', 'object') +bl.type('ShapeBase::getEyePoint:1', 'object') +bl.type('ShapeBase::getEyeTransform:1', 'object') +bl.type('ShapeBase::getEyeVector:1', 'object') +bl.type('ShapeBase::getImageAmmo', 'bool') +bl.type('ShapeBase::getImageAmmo:1', 'object') +bl.type('ShapeBase::getImageLoaded', 'bool') +bl.type('ShapeBase::getImageLoaded:1', 'object') +bl.type('ShapeBase::getImageSkinTag:1', 'object') +bl.type('ShapeBase::getImageState:1', 'object') +bl.type('ShapeBase::getImageTrigger', 'bool') +bl.type('ShapeBase::getImageTrigger:1', 'object') +bl.type('ShapeBase::getMountNode:1', 'object') +bl.type('ShapeBase::getMountNodeObject', 'object') +bl.type('ShapeBase::getMountNodeObject:1', 'object') +bl.type('ShapeBase::getMountSlot:1', 'object') +bl.type('ShapeBase::getMountSlot:2', 'object') +bl.type('ShapeBase::getMountedImage:1', 'object') +bl.type('ShapeBase::getMountedObject', 'object') +bl.type('ShapeBase::getMountedObject:1', 'object') +bl.type('ShapeBase::getMountedObjectCount:1', 'object') +bl.type('ShapeBase::getMountedObjectNode', 'object') +bl.type('ShapeBase::getMountedObjectNode:1', 'object') +bl.type('ShapeBase::getMuzzlePoint:1', 'object') +bl.type('ShapeBase::getMuzzleVector:1', 'object') +bl.type('ShapeBase::getObjectMount', 'object') +bl.type('ShapeBase::getObjectMount:1', 'object') +bl.type('ShapeBase::getPendingImage:1', 'object') +bl.type('ShapeBase::getRechargeRate:1', 'object') +bl.type('ShapeBase::getRepairRate:1', 'object') +bl.type('ShapeBase::getShapeName:1', 'object') +bl.type('ShapeBase::getSkinName:1', 'object') +bl.type('ShapeBase::getSlotTransform:1', 'object') +bl.type('ShapeBase::getVelocity:1', 'object') +bl.type('ShapeBase::getWaterCoverage:1', 'object') +bl.type('ShapeBase::getWhiteOut:1', 'object') +bl.type('ShapeBase::hideNode:1', 'object') +bl.type('ShapeBase::isCloaked', 'bool') +bl.type('ShapeBase::isCloaked:1', 'object') +bl.type('ShapeBase::isDestroyed', 'bool') +bl.type('ShapeBase::isDestroyed:1', 'object') +bl.type('ShapeBase::isDisabled', 'bool') +bl.type('ShapeBase::isDisabled:1', 'object') +bl.type('ShapeBase::isEnabled', 'bool') +bl.type('ShapeBase::isEnabled:1', 'object') +bl.type('ShapeBase::isHidden', 'bool') +bl.type('ShapeBase::isHidden:1', 'object') +bl.type('ShapeBase::isImageFiring', 'bool') +bl.type('ShapeBase::isImageFiring:1', 'object') +bl.type('ShapeBase::isImageMounted', 'bool') +bl.type('ShapeBase::isImageMounted:1', 'object') +bl.type('ShapeBase::isImageMounted:2', 'object') +bl.type('ShapeBase::isMounted', 'bool') +bl.type('ShapeBase::isMounted:1', 'object') +bl.type('ShapeBase::isNodeVisible', 'bool') +bl.type('ShapeBase::isNodeVisible:1', 'object') +bl.type('ShapeBase::mountImage', 'bool') +bl.type('ShapeBase::mountImage:1', 'object') +bl.type('ShapeBase::mountImage:2', 'object') +bl.type('ShapeBase::mountImage:4', 'bool') +bl.type('ShapeBase::mountObject', 'bool') +bl.type('ShapeBase::mountObject:1', 'object') +bl.type('ShapeBase::mountObject:2', 'object') +bl.type('ShapeBase::mountObject:3', 'object') +bl.type('ShapeBase::pauseThread', 'bool') +bl.type('ShapeBase::pauseThread:1', 'object') +bl.type('ShapeBase::playAudio', 'bool') +bl.type('ShapeBase::playAudio:1', 'object') +bl.type('ShapeBase::playAudio:3', 'object') +bl.type('ShapeBase::playThread', 'bool') +bl.type('ShapeBase::playThread:1', 'object') +bl.type('ShapeBase::setCameraFov:1', 'object') +bl.type('ShapeBase::setCloaked:1', 'object') +bl.type('ShapeBase::setCloaked:2', 'bool') +bl.type('ShapeBase::setDamageFlash:1', 'object') +bl.type('ShapeBase::setDamageLevel:1', 'object') +bl.type('ShapeBase::setDamageState', 'bool') +bl.type('ShapeBase::setDamageState:1', 'object') +bl.type('ShapeBase::setDamageVector:1', 'object') +bl.type('ShapeBase::setEnergyLevel:1', 'object') +bl.type('ShapeBase::setHidden:1', 'object') +bl.type('ShapeBase::setHidden:2', 'bool') +bl.type('ShapeBase::setIflFrame:1', 'object') +bl.type('ShapeBase::setImageAmmo', 'bool') +bl.type('ShapeBase::setImageAmmo:1', 'object') +bl.type('ShapeBase::setImageAmmo:3', 'bool') +bl.type('ShapeBase::setImageLoaded', 'bool') +bl.type('ShapeBase::setImageLoaded:1', 'object') +bl.type('ShapeBase::setImageLoaded:3', 'bool') +bl.type('ShapeBase::setImageTrigger', 'bool') +bl.type('ShapeBase::setImageTrigger:1', 'object') +bl.type('ShapeBase::setImageTrigger:3', 'bool') +bl.type('ShapeBase::setNodeColor:1', 'object') +bl.type('ShapeBase::setRepairRate:1', 'object') +bl.type('ShapeBase::setShapeName:1', 'object') +bl.type('ShapeBase::setShapeNameColor:1', 'object') +bl.type('ShapeBase::setShapeNameDistance:1', 'object') +bl.type('ShapeBase::setSkinName:1', 'object') +bl.type('ShapeBase::setThreadDir', 'bool') +bl.type('ShapeBase::setThreadDir:1', 'object') +bl.type('ShapeBase::setThreadDir:3', 'bool') +bl.type('ShapeBase::setVelocity', 'bool') +bl.type('ShapeBase::setVelocity:1', 'object') +bl.type('ShapeBase::setWhiteOut:1', 'object') +bl.type('ShapeBase::startFade:1', 'object') +bl.type('ShapeBase::startFade:4', 'bool') +bl.type('ShapeBase::stopAudio', 'bool') +bl.type('ShapeBase::stopAudio:1', 'object') +bl.type('ShapeBase::stopThread', 'bool') +bl.type('ShapeBase::stopThread:1', 'object') +bl.type('ShapeBase::unHideNode:1', 'object') +bl.type('ShapeBase::unMountObject', 'bool') +bl.type('ShapeBase::unMountObject:1', 'object') +bl.type('ShapeBase::unMountObject:2', 'object') +bl.type('ShapeBase::unmount:1', 'object') +bl.type('ShapeBase::unmountImage', 'bool') +bl.type('ShapeBase::unmountImage:1', 'object') +bl.type('ShapeBaseData.emap', 'bool') +bl.type('ShapeBaseData.firstPersonOnly', 'bool') +bl.type('ShapeBaseData.inheritEnergyFromMount', 'bool') +bl.type('ShapeBaseData.isInvincible', 'bool') +bl.type('ShapeBaseData.observeThroughObject', 'bool') +bl.type('ShapeBaseData.renderWhenDestroyed', 'bool') +bl.type('ShapeBaseData.thirdPersonOnly', 'bool') +bl.type('ShapeBaseData.useEyePoint', 'bool') +bl.type('ShapeBaseData::Damage:1', 'object') +bl.type('ShapeBaseData::checkDeployPos', 'bool') +bl.type('ShapeBaseData::checkDeployPos:1', 'object') +bl.type('ShapeBaseData::getDeployTransform:1', 'object') +bl.type('ShapeBaseData::onInventory:1', 'object') +bl.type('ShapeBaseData::onPickup:1', 'object') +bl.type('ShapeBaseData::onThrow:1', 'object') +bl.type('ShapeBaseData::onUse:1', 'object') +bl.type('ShapeBaseImageData.accuFire', 'bool') +bl.type('ShapeBaseImageData.cloakable', 'bool') +bl.type('ShapeBaseImageData.correctMuzzleVector', 'bool') +bl.type('ShapeBaseImageData.doColorShift', 'bool') +bl.type('ShapeBaseImageData.emap', 'bool') +bl.type('ShapeBaseImageData.firstPerson', 'bool') +bl.type('ShapeBaseImageData.firstPersonParticles', 'bool') +bl.type('ShapeBaseImageData.stateAllowImageChange', 'bool') +bl.type('ShapeBaseImageData.stateDirection', 'bool') +bl.type('ShapeBaseImageData.stateEjectShell', 'bool') +bl.type('ShapeBaseImageData.stateFire', 'bool') +bl.type('ShapeBaseImageData.stateIgnoreLoadedForReady', 'bool') +bl.type('ShapeBaseImageData.stateSequenceRandomFlash', 'bool') +bl.type('ShapeBaseImageData.stateWaitForTimeout', 'bool') +bl.type('ShapeBaseImageData.usesEnergy', 'bool') +bl.type('ShapeBaseImageData::onBallTrigger:1', 'object') +bl.type('SharkHoleBot::onAdd:1', 'object') +bl.type('SharkHoleBot::onBotCollision:1', 'object') +bl.type('SharkHoleBot::onBotDamage:1', 'object') +bl.type('SharkHoleBot::onBotFollow:1', 'object') +bl.type('SharkHoleBot::onBotLoop:1', 'object') +bl.type('SharkHoleBot::onDisabled:1', 'object') +bl.type('SharkHoleBot::onEnterLiquid:1', 'object') +bl.type('SharkHoleBot::onNewDataBlock:1', 'object') +bl.type('SharkHoleBot::onRemove:1', 'object') +bl.type('SharkHoleBotBottom::onAdd:1', 'object') +bl.type('SharkHoleBotBottom::onBotCollision:1', 'object') +bl.type('SharkHoleBotBottom::onBotDamage:1', 'object') +bl.type('SharkHoleBotBottom::onBotLoop:1', 'object') +bl.type('SharkHoleBotBottom::onDisabled:1', 'object') +bl.type('SharkHoleBotBottom::onEnterLiquid:1', 'object') +bl.type('SharkHoleBotBottom::onNewDataBlock:1', 'object') +bl.type('SharkHoleBotBottom::onRemove:1', 'object') +bl.type('SharkHoleBotTop::onAdd:1', 'object') +bl.type('SharkHoleBotTop::onBotCollision:1', 'object') +bl.type('SharkHoleBotTop::onBotDamage:1', 'object') +bl.type('SharkHoleBotTop::onBotLoop:1', 'object') +bl.type('SharkHoleBotTop::onDisabled:1', 'object') +bl.type('SharkHoleBotTop::onEnterLiquid:1', 'object') +bl.type('SharkHoleBotTop::onNewDataBlock:1', 'object') +bl.type('SharkHoleBotTop::onRemove:1', 'object') +bl.type('SimGroup::CLIENTDumpNTNames:1', 'object') +bl.type('SimGroup::CLIENTaddNTName:1', 'object') +bl.type('SimGroup::CLIENTremoveNTName:1', 'object') +bl.type('SimGroup::ChainDeleteAll:1', 'object') +bl.type('SimGroup::ClearAllNTNames:1', 'object') +bl.type('SimGroup::DumpNTNames:1', 'object') +bl.type('SimGroup::addNTName:1', 'object') +bl.type('SimGroup::addPotentialTrust:1', 'object') +bl.type('SimGroup::addSpawnBrick:1', 'object') +bl.type('SimGroup::chainBlink:1', 'object') +bl.type('SimGroup::chainMethodCall:1', 'object') +bl.type('SimGroup::dumpSpawnPoints:1', 'object') +bl.type('SimGroup::getBrickSpawnPoint:1', 'object') +bl.type('SimGroup::getClient:1', 'object') +bl.type('SimGroup::getTrustFailureMessage:1', 'object') +bl.type('SimGroup::hasUser:1', 'object') +bl.type('SimGroup::indexOf:1', 'object') +bl.type('SimGroup::removeNTName:1', 'object') +bl.type('SimGroup::removeSpawnBrick:1', 'object') +bl.type('SimObject::SetEventEnabled:1', 'object') +bl.type('SimObject::ToggleEventEnabled:1', 'object') +bl.type('SimObject::addScheduledEvent:1', 'object') +bl.type('SimObject::call:1', 'object') +bl.type('SimObject::cancelEvents:1', 'object') +bl.type('SimObject::clearAttributes:1', 'object') +bl.type('SimObject::clearEvents:1', 'object') +bl.type('SimObject::clearNTObjectName:1', 'object') +bl.type('SimObject::copyAttributes:1', 'object') +bl.type('SimObject::delete:1', 'object') +bl.type('SimObject::dump:1', 'object') +bl.type('SimObject::dumpEvents:1', 'object') +bl.type('SimObject::getAttribute:1', 'object') +bl.type('SimObject::getClassName:1', 'object') +bl.type('SimObject::getGroup:1', 'object') +bl.type('SimObject::getId:1', 'object') +bl.type('SimObject::getName:1', 'object') +bl.type('SimObject::getTaggedField:1', 'object') +bl.type('SimObject::getType:1', 'object') +bl.type('SimObject::getVariable:1', 'object') +bl.type('SimObject::onCameraEnterOrbit:1', 'object') +bl.type('SimObject::onCameraLeaveOrbit:1', 'object') +bl.type('SimObject::processInputEvent:1', 'object') +bl.type('SimObject::save', 'bool') +bl.type('SimObject::save:1', 'object') +bl.type('SimObject::schedule:1', 'object') +bl.type('SimObject::scheduleNoQuota:1', 'object') +bl.type('SimObject::serializeEvent:1', 'object') +bl.type('SimObject::serializeEventToString:1', 'object') +bl.type('SimObject::setAttribute:1', 'object') +bl.type('SimObject::setNTObjectName:1', 'object') +bl.type('SimObject::setName:1', 'object') +bl.type('SimObject::setVariable:1', 'object') +bl.type('SimSet::add:1', 'object') +bl.type('SimSet::bringToFront:1', 'object') +bl.type('SimSet::clear:1', 'object') +bl.type('SimSet::clientDeleteAll:1', 'object') +bl.type('SimSet::deleteAll:1', 'object') +bl.type('SimSet::getCount:1', 'object') +bl.type('SimSet::getObject', 'object') +bl.type('SimSet::getObject:1', 'object') +bl.type('SimSet::isMember', 'bool') +bl.type('SimSet::isMember:1', 'object') +bl.type('SimSet::listObjects:1', 'object') +bl.type('SimSet::pushToBack:1', 'object') +bl.type('SimSet::remove:1', 'object') +bl.type('SkiItem::onUse:1', 'object') +bl.type('SkiWeaponImage::onFire:1', 'object') +bl.type('Sky.noRenderBans', 'bool') +bl.type('Sky.renderBottomTexture', 'bool') +bl.type('Sky.windEffectPrecipitation', 'bool') +bl.type('Sky::getWindVelocity:1', 'object') +bl.type('Sky::sendUpdate:1', 'object') +bl.type('Sky::setWindVelocity:1', 'object') +bl.type('SlayerClient::SendData:1', 'object') +bl.type('SlayerClient::clearAllData:1', 'object') +bl.type('SlayerClient::editMinigame:1', 'object') +bl.type('SlayerClient::onAdd:1', 'object') +bl.type('SlayerClient::onDisconnect:1', 'object') +bl.type('SlayerClient::onRemove:1', 'object') +bl.type('SlayerClient_GameModeHandlerSG::updateGameMode:1', 'object') +bl.type('SlayerClient_GameModeTemplateSG::applyDefaultPreferences:1', 'object') +bl.type('SlayerClient_GameModeTemplateSG::applyDefaultTeamPreferences:1', 'object') +bl.type('SlayerClient_GameModeTemplateSG::createDefaultTeams:1', 'object') +bl.type('SlayerClient_PrefHandlerSG::getPrefSO:1', 'object') +bl.type('SlayerClient_PrefSO::getDisplayValue:1', 'object') +bl.type('SlayerClient_PrefSO::getValue:1', 'object') +bl.type('SlayerClient_PrefSO::idiotProof:1', 'object') +bl.type('SlayerClient_PrefSO::onAdd:1', 'object') +bl.type('SlayerClient_PrefSO::onAdded:1', 'object') +bl.type('SlayerClient_PrefSO::setValue:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::addPref:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::clearPrefs:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::clearRules:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::displayRule:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::exportMinigamePreferences:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::exportPrefs:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::getPrefSO:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::importMinigamePreferences:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::sendPreferenceValues:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::updateDynamicRules:1', 'object') +bl.type('SlayerClient_ServerPrefHandlerSG::updateGUIValue:1', 'object') +bl.type('SlayerClient_ServerPrefSO::getDisplayValue:1', 'object') +bl.type('SlayerClient_ServerPrefSO::getValue:1', 'object') +bl.type('SlayerClient_ServerPrefSO::idiotProof:1', 'object') +bl.type('SlayerClient_ServerPrefSO::setValue:1', 'object') +bl.type('SlayerClient_Support::Debug:1', 'object') +bl.type('SlayerClient_Support::error:1', 'object') +bl.type('SlayerClient_Support::getIDFromUiName:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::addTeam:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::clearTeams:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::createTeam:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::getTeamFromID:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::getTeamFromName:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::onAdd:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::onRemove:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::removeTeam:1', 'object') +bl.type('SlayerClient_TeamHandlerSG::sendTeams:1', 'object') +bl.type('SlayerClient_TeamPrefHandlerSG::addPref:1', 'object') +bl.type('SlayerClient_TeamPrefHandlerSG::clearPrefs:1', 'object') +bl.type('SlayerClient_TeamPrefHandlerSG::exportTeamPreferences:1', 'object') +bl.type('SlayerClient_TeamPrefHandlerSG::getPrefSO:1', 'object') +bl.type('SlayerClient_TeamPrefHandlerSG::importTeamPreferences:1', 'object') +bl.type('SlayerClient_TeamPrefHandlerSG::resetPreferences:1', 'object') +bl.type('SlayerClient_TeamPrefHandlerSG::updateGUIValue:1', 'object') +bl.type('SlayerClient_TeamPrefSO::getDisplayValue:1', 'object') +bl.type('SlayerClient_TeamPrefSO::getValue:1', 'object') +bl.type('SlayerClient_TeamPrefSO::idiotProof:1', 'object') +bl.type('SlayerClient_TeamPrefSO::setValue:1', 'object') +bl.type('SlayerClient_helpTCP::handleText:1', 'object') +bl.type('SlayerClient_helpTCP::onDone:1', 'object') +bl.type('Slayer_Advanced::Refresh:1', 'object') +bl.type('Slayer_Advanced::apply:1', 'object') +bl.type('Slayer_Advanced::onWake:1', 'object') +bl.type('Slayer_Advanced_CategoryFilter::onSelect:1', 'object') +bl.type('Slayer_Advanced_Selector::onSelect:1', 'object') +bl.type('Slayer_CtrDisplay::addText:1', 'object') +bl.type('Slayer_CtrDisplay::onWake:1', 'object') +bl.type('Slayer_General::onWake:1', 'object') +bl.type('Slayer_General_Basic_Color::CreateColorMenu:1', 'object') +bl.type('Slayer_General_Basic_Color::clickColor:1', 'object') +bl.type('Slayer_General_Mode_Selector::onCancel:1', 'object') +bl.type('Slayer_General_Mode_Selector::onSelect:1', 'object') +bl.type('Slayer_General_Player::onPopUpMenuSelect:1', 'object') +bl.type('Slayer_Help::getHelpFile:1', 'object') +bl.type('Slayer_Help::loadOfflineHelpFile:1', 'object') +bl.type('Slayer_Help::onWake:1', 'object') +bl.type('Slayer_Main::Refresh:1', 'object') +bl.type('Slayer_Main::apply:1', 'object') +bl.type('Slayer_Main::onSleep:1', 'object') +bl.type('Slayer_Main::onWake:1', 'object') +bl.type('Slayer_Main::refreshFromServer:1', 'object') +bl.type('Slayer_Main_Announcements::addMessage:1', 'object') +bl.type('Slayer_Main_Announcements::clearMessages:1', 'object') +bl.type('Slayer_Main_Announcements::onSleep:1', 'object') +bl.type('Slayer_Main_Announcements::onWake:1', 'object') +bl.type('Slayer_Main_Announcements::removeMessage:1', 'object') +bl.type('Slayer_Main_Announcements::scrollText:1', 'object') +bl.type('Slayer_Main_Announcements::startScrolling:1', 'object') +bl.type('Slayer_Main_Favs::ClickFav:1', 'object') +bl.type('Slayer_Main_Favs::onWake:1', 'object') +bl.type('Slayer_Main_Favs::setFavs:1', 'object') +bl.type('Slayer_Main_Favs::updateFavs:1', 'object') +bl.type('Slayer_Main_TabList::onSelect:1', 'object') +bl.type('Slayer_Main_TabList::setSelectedByTab:1', 'object') +bl.type('Slayer_Main_Tabs::addTab:1', 'object') +bl.type('Slayer_Main_Tabs::lockTab:1', 'object') +bl.type('Slayer_Main_Tabs::removeTab:1', 'object') +bl.type('Slayer_Main_Tabs::setTab:1', 'object') +bl.type('Slayer_Options::Refresh:1', 'object') +bl.type('Slayer_Options::apply:1', 'object') +bl.type('Slayer_Options::onWake:1', 'object') +bl.type('Slayer_Options_Selector::onSelect:1', 'object') +bl.type('Slayer_PrefSO::getDisplayValue:1', 'object') +bl.type('Slayer_PrefSO::idiotProof:1', 'object') +bl.type('Slayer_Support::Benchmark:1', 'object') +bl.type('Slayer_Support::RgbToHex:1', 'object') +bl.type('Slayer_Support::getAverageColor:1', 'object') +bl.type('Slayer_Support::getClosestPaintColor:1', 'object') +bl.type('Slayer_Support::getDynamicVariable:1', 'object') +bl.type('Slayer_Support::isFloat:1', 'object') +bl.type('Slayer_Support::isItemInList:1', 'object') +bl.type('Slayer_Support::loadFiles:1', 'object') +bl.type('Slayer_Support::setDynamicVariable:1', 'object') +bl.type('Slayer_Support::stripTrailingZeros:1', 'object') +bl.type('Slayer_Support::swapItemsInList:1', 'object') +bl.type('Slayer_Teams::CreateColorMenu:1', 'object') +bl.type('Slayer_Teams::Refresh:1', 'object') +bl.type('Slayer_Teams::clickAddMember:1', 'object') +bl.type('Slayer_Teams::clickAdvanced:1', 'object') +bl.type('Slayer_Teams::clickApply:1', 'object') +bl.type('Slayer_Teams::clickCancel:1', 'object') +bl.type('Slayer_Teams::clickCreateTeam:1', 'object') +bl.type('Slayer_Teams::clickDeleteTeam:1', 'object') +bl.type('Slayer_Teams::clickEditUniform:1', 'object') +bl.type('Slayer_Teams::clickRemoveMember:1', 'object') +bl.type('Slayer_Teams::loadUniform:1', 'object') +bl.type('Slayer_Teams::onWake:1', 'object') +bl.type('Slayer_Teams::pickColor:1', 'object') +bl.type('Slayer_Teams::resetDatablockLists:1', 'object') +bl.type('Slayer_Teams::resetUniform:1', 'object') +bl.type('Slayer_Teams::saveUniform:1', 'object') +bl.type('Slayer_Teams::setLoadoutSync:1', 'object') +bl.type('Slayer_Teams_Advanced::apply:1', 'object') +bl.type('Slayer_Teams_Advanced::onWake:1', 'object') +bl.type('Slayer_Teams_Advanced_Selector::onSelect:1', 'object') +bl.type('Slayer_Teams_MovePlayerName::refreshList:1', 'object') +bl.type('Slayer_Teams_Selector::onDeleteKey:1', 'object') +bl.type('Slayer_Teams_Selector::onSelect:1', 'object') +bl.type('SpawnSphere.canSetIFLs', 'bool') +bl.type('StaticShape.canSetIFLs', 'bool') +bl.type('StaticShape::explode:1', 'object') +bl.type('StaticShapeData.emap', 'bool') +bl.type('StaticShapeData.firstPersonOnly', 'bool') +bl.type('StaticShapeData.inheritEnergyFromMount', 'bool') +bl.type('StaticShapeData.isInvincible', 'bool') +bl.type('StaticShapeData.noIndividualDamage', 'bool') +bl.type('StaticShapeData.observeThroughObject', 'bool') +bl.type('StaticShapeData.renderWhenDestroyed', 'bool') +bl.type('StaticShapeData.thirdPersonOnly', 'bool') +bl.type('StaticShapeData.useEyePoint', 'bool') +bl.type('StaticShapeData::Damage:1', 'object') +bl.type('StaticShapeData::create:1', 'object') +bl.type('StaticShapeData::onAdd:1', 'object') +bl.type('SteamAPI_Init', 'bool') +bl.type('SteamEnabled', 'bool') +bl.type('SteamGreenLightGui::ClickBack:1', 'object') +bl.type('SteamGreenLightGui::clickForward:1', 'object') +bl.type('SteamGreenLightGui::onRender:1', 'object') +bl.type('SteamGreenLightGui::onWake:1', 'object') +bl.type('SteamSetLobbyIP', 'bool') +bl.type('SteamSetLobbyPort', 'bool') +bl.type('Sun::sendUpdate:1', 'object') +bl.type('TCPObject::connect:1', 'object') +bl.type('TCPObject::delete:1', 'object') +bl.type('TCPObject::disconnect:1', 'object') +bl.type('TCPObject::listen:1', 'object') +bl.type('TCPObject::saveBufferToFile:1', 'object') +bl.type('TCPObject::send:1', 'object') +bl.type('TCPObject::setBinary:1', 'object') +bl.type('TCPObject::setBinary:2', 'bool') +bl.type('TCPObject::setBinarySize:1', 'object') +bl.type('TankShellProjectile::onCollision:1', 'object') +bl.type('TankSmokeImage::onDone:1', 'object') +bl.type('TankTurretPlayer::Damage:1', 'object') +bl.type('TankVehicle::Damage:1', 'object') +bl.type('Trigger::getNumObjects:1', 'object') +bl.type('Trigger::getObject:1', 'object') +bl.type('Trigger::onAdd:1', 'object') +bl.type('Trigger::removeObjectById', 'bool') +bl.type('Trigger::removeObjectById:1', 'object') +bl.type('TriggerData::onAdd:1', 'object') +bl.type('TriggerData::onEnterTrigger:1', 'object') +bl.type('TriggerData::onLeaveTrigger:1', 'object') +bl.type('TriggerData::onTickTrigger:1', 'object') +bl.type('TrustInviteGui::ClickAccept:1', 'object') +bl.type('TrustInviteGui::ClickIgnore:1', 'object') +bl.type('TrustInviteGui::ClickReject:1', 'object') +bl.type('TrustInviteGui::Ignore:1', 'object') +bl.type('VBOSupport', 'bool') +bl.type('Vehicle.canSetIFLs', 'bool') +bl.type('Vehicle.disableMove', 'bool') +bl.type('Vehicle::finalExplosion:1', 'object') +bl.type('Vehicle::lavaDamage:1', 'object') +bl.type('Vehicle::onActivate:1', 'object') +bl.type('Vehicle::onCollision:1', 'object') +bl.type('Vehicle::onDriverLeave:1', 'object') +bl.type('Vehicle::onRemove:1', 'object') +bl.type('Vehicle::setAngularVelocity:1', 'object') +bl.type('Vehicle::teleportEffect:1', 'object') +bl.type('Vehicle::tumbleCheck:1', 'object') +bl.type('VehicleData.cameraRoll', 'bool') +bl.type('VehicleData.emap', 'bool') +bl.type('VehicleData.firstPersonOnly', 'bool') +bl.type('VehicleData.inheritEnergyFromMount', 'bool') +bl.type('VehicleData.isInvincible', 'bool') +bl.type('VehicleData.observeThroughObject', 'bool') +bl.type('VehicleData.renderWhenDestroyed', 'bool') +bl.type('VehicleData.rideAble', 'bool') +bl.type('VehicleData.thirdPersonOnly', 'bool') +bl.type('VehicleData.useEyePoint', 'bool') +bl.type('VehicleData::onCollision:1', 'object') +bl.type('VehicleData::onDriverLeave:1', 'object') +bl.type('VehicleData::onEnterLiquid:1', 'object') +bl.type('VehicleData::onLeaveLiquid:1', 'object') +bl.type('VehicleSpawnMarker.canSetIFLs', 'bool') +bl.type('VehicleSpawnMarker.reColorVehicle', 'bool') +bl.type('VehicleSpawnMarker::getReColorVehicle', 'bool') +bl.type('VehicleSpawnMarker::getReColorVehicle:1', 'object') +bl.type('VehicleSpawnMarker::getUiName:1', 'object') +bl.type('VehicleSpawnMarker::onAdd:1', 'object') +bl.type('VehicleSpawnMarker::onRemove:1', 'object') +bl.type('VehicleSpawnMarker::setData:1', 'object') +bl.type('VehicleSpawnMarker::setData:3', 'bool') +bl.type('WandImage::onFire:1', 'object') +bl.type('WandImage::onHitObject:1', 'object') +bl.type('WandImage::onPreFire:1', 'object') +bl.type('WandImage::onStopFire:1', 'object') +bl.type('WandItem::onUse:1', 'object') +bl.type('WayPoint.canSetIFLs', 'bool') +bl.type('Weapon::onInventory:1', 'object') +bl.type('Weapon::onPickup:1', 'object') +bl.type('Weapon::onUse:1', 'object') +bl.type('WeaponImage::onFire:1', 'object') +bl.type('WeaponImage::onMount:1', 'object') +bl.type('WeaponImage::onUnMount:1', 'object') +bl.type('WheeledVehicle.canSetIFLs', 'bool') +bl.type('WheeledVehicle.disableMove', 'bool') +bl.type('WheeledVehicle::getWheelCount:1', 'object') +bl.type('WheeledVehicle::getWheelPowered', 'bool') +bl.type('WheeledVehicle::getWheelPowered:1', 'object') +bl.type('WheeledVehicle::setWheelPowered', 'bool') +bl.type('WheeledVehicle::setWheelPowered:1', 'object') +bl.type('WheeledVehicle::setWheelPowered:3', 'bool') +bl.type('WheeledVehicle::setWheelSpring', 'bool') +bl.type('WheeledVehicle::setWheelSpring:1', 'object') +bl.type('WheeledVehicle::setWheelSteering', 'bool') +bl.type('WheeledVehicle::setWheelSteering:1', 'object') +bl.type('WheeledVehicle::setWheelTire', 'bool') +bl.type('WheeledVehicle::setWheelTire:1', 'object') +bl.type('WheeledVehicleData.cameraRoll', 'bool') +bl.type('WheeledVehicleData.emap', 'bool') +bl.type('WheeledVehicleData.firstPersonOnly', 'bool') +bl.type('WheeledVehicleData.inheritEnergyFromMount', 'bool') +bl.type('WheeledVehicleData.isInvincible', 'bool') +bl.type('WheeledVehicleData.isSled', 'bool') +bl.type('WheeledVehicleData.observeThroughObject', 'bool') +bl.type('WheeledVehicleData.renderWhenDestroyed', 'bool') +bl.type('WheeledVehicleData.rideAble', 'bool') +bl.type('WheeledVehicleData.steeringUseAutoReturn', 'bool') +bl.type('WheeledVehicleData.steeringUseStrafeSteering', 'bool') +bl.type('WheeledVehicleData.thirdPersonOnly', 'bool') +bl.type('WheeledVehicleData.useEyePoint', 'bool') +bl.type('WheeledVehicleData::Damage:1', 'object') +bl.type('WheeledVehicleData::create:1', 'object') +bl.type('WheeledVehicleData::onAdd:1', 'object') +bl.type('WheeledVehicleData::onCollision:1', 'object') +bl.type('WheeledVehicleData::onDamage:1', 'object') +bl.type('WheeledVehicleData::onDriverLeave:1', 'object') +bl.type('WhoTalkSO::Display:1', 'object') +bl.type('WhoTalkSO::HasID:1', 'object') +bl.type('WhoTalkSO::addID:1', 'object') +bl.type('WhoTalkSO::removeID:1', 'object') +bl.type('WorldEditor.axisGizmoActive', 'bool') +bl.type('WorldEditor.boundingBoxCollision', 'bool') +bl.type('WorldEditor.clipToParent', 'bool') +bl.type('WorldEditor.enabled', 'bool') +bl.type('WorldEditor.isDirty', 'bool') +bl.type('WorldEditor.objectsUseBoxCenter', 'bool') +bl.type('WorldEditor.planarMovement', 'bool') +bl.type('WorldEditor.renderMissionArea', 'bool') +bl.type('WorldEditor.renderNav', 'bool') +bl.type('WorldEditor.renderObjHandle', 'bool') +bl.type('WorldEditor.renderObjText', 'bool') +bl.type('WorldEditor.renderPlane', 'bool') +bl.type('WorldEditor.renderPlaneHashes', 'bool') +bl.type('WorldEditor.renderPopupBackground', 'bool') +bl.type('WorldEditor.renderSelectionBox', 'bool') +bl.type('WorldEditor.selectionLocked', 'bool') +bl.type('WorldEditor.showMousePopupInfo', 'bool') +bl.type('WorldEditor.snapRotations', 'bool') +bl.type('WorldEditor.snapToGrid', 'bool') +bl.type('WorldEditor.toggleIgnoreList', 'bool') +bl.type('WorldEditor.visible', 'bool') +bl.type('WorldEditor::addUndoState:1', 'object') +bl.type('WorldEditor::canPasteSelection', 'bool') +bl.type('WorldEditor::canPasteSelection:1', 'object') +bl.type('WorldEditor::clearIgnoreList:1', 'object') +bl.type('WorldEditor::clearSelection:1', 'object') +bl.type('WorldEditor::copySelection:1', 'object') +bl.type('WorldEditor::deleteSelection:1', 'object') +bl.type('WorldEditor::dropSelection:1', 'object') +bl.type('WorldEditor::getMode:1', 'object') +bl.type('WorldEditor::getSelectedObject', 'object') +bl.type('WorldEditor::getSelectedObject:1', 'object') +bl.type('WorldEditor::getSelectionCentroid:1', 'object') +bl.type('WorldEditor::getSelectionSize:1', 'object') +bl.type('WorldEditor::hideSelection:1', 'object') +bl.type('WorldEditor::hideSelection:2', 'bool') +bl.type('WorldEditor::ignoreObjClass:1', 'object') +bl.type('WorldEditor::lockSelection:1', 'object') +bl.type('WorldEditor::lockSelection:2', 'bool') +bl.type('WorldEditor::pasteSelection:1', 'object') +bl.type('WorldEditor::redirectConsole:1', 'object') +bl.type('WorldEditor::redo:1', 'object') +bl.type('WorldEditor::selectObject:1', 'object') +bl.type('WorldEditor::selectObject:2', 'object') +bl.type('WorldEditor::setMode:1', 'object') +bl.type('WorldEditor::undo:1', 'object') +bl.type('WorldEditor::unselectObject:1', 'object') +bl.type('WorldEditor::unselectObject:2', 'object') +bl.type('WrenchImage::onFire:1', 'object') +bl.type('WrenchImage::onHitObject:1', 'object') +bl.type('WrenchImage::onPreFire:1', 'object') +bl.type('WrenchImage::onStopFire:1', 'object') +bl.type('WtfImage::onDone:1', 'object') +bl.type('ZombieHoleBot::onAdd:1', 'object') +bl.type('ZombieHoleBot::onBotCollision:1', 'object') +bl.type('ZombieHoleBot::onBotFollow:1', 'object') +bl.type('ZombieHoleBot::onBotLoop:1', 'object') +bl.type('aboutDlg::onWake:1', 'object') +bl.type('aboutText::onURL:1', 'object') +bl.type('activateKeyboard', 'bool') +bl.type('addBanGui::ban:1', 'object') +bl.type('addBanGui::clickForever:1', 'object') +bl.type('addBanGui::onSleep:1', 'object') +bl.type('addBanGui::onWake:1', 'object') +bl.type('addBanGui::setVictim:1', 'object') +bl.type('addCardProfile:11', 'bool') +bl.type('addCardProfile:12', 'bool') +bl.type('addCardProfile:13', 'bool') +bl.type('addCardProfile:3', 'bool') +bl.type('addCardProfile:4', 'bool') +bl.type('addCardProfile:5', 'bool') +bl.type('addCardProfile:6', 'bool') +bl.type('addCardProfile:7', 'bool') +bl.type('addCardProfile:8', 'bool') +bl.type('addCardProfile:9', 'bool') +bl.type('addMaterialMapping', 'bool') +bl.type('addOSCardProfile:3', 'bool') +bl.type('addOSCardProfile:4', 'bool') +bl.type('addOSCardProfile:5', 'bool') +bl.type('adminGui::ClickClearBricks:1', 'object') +bl.type('adminGui::ClickGameMode:1', 'object') +bl.type('adminGui::ClickServerSettings:1', 'object') +bl.type('adminGui::ban:1', 'object') +bl.type('adminGui::kick:1', 'object') +bl.type('adminGui::onWake:1', 'object') +bl.type('adminGui::openEnvGui:1', 'object') +bl.type('adminGui::sortList:1', 'object') +bl.type('adminGui::sortNumList:1', 'object') +bl.type('adminGui::spy:1', 'object') +bl.type('alxIsPlaying', 'bool') +bl.type('alxSetChannelVolume', 'bool') +bl.type('amIDrivingAVehicle', 'bool') +bl.type('amIStrafeSteering', 'bool') +bl.type('ammo::onInventory:1', 'object') +bl.type('authTCPobj_Client::onConnectFailed:1', 'object') +bl.type('authTCPobj_Client::onConnected:1', 'object') +bl.type('authTCPobj_Client::onDNSFailed:1', 'object') +bl.type('authTCPobj_Client::onDisconnect:1', 'object') +bl.type('authTCPobj_Client::onLine:1', 'object') +bl.type('authTCPobj_Server::onConnectFailed:1', 'object') +bl.type('authTCPobj_Server::onConnected:1', 'object') +bl.type('authTCPobj_Server::onDNSFailed:1', 'object') +bl.type('authTCPobj_Server::onDisconnect:1', 'object') +bl.type('authTCPobj_Server::onLine:1', 'object') +bl.type('basketballImage::onBallTrigger:1', 'object') +bl.type('basketballImage::onFire:1', 'object') +bl.type('basketballImage::onMount:1', 'object') +bl.type('basketballImage::onUnMount:1', 'object') +bl.type('basketballItem::onBallCollision:1', 'object') +bl.type('basketballItem::onUse:1', 'object') +bl.type('basketballProjectile::onCollision:1', 'object') +bl.type('basketballShootImage::onBallTrigger:1', 'object') +bl.type('basketballShootImage::onCharge:1', 'object') +bl.type('basketballShootImage::onFire:1', 'object') +bl.type('basketballShootImage::onMount:1', 'object') +bl.type('basketballShootImage::onUnMount:1', 'object') +bl.type('blankaBallImage::onAbortCharge:1', 'object') +bl.type('blankaBallImage::onCharge:1', 'object') +bl.type('blankaBallImage::onFire:1', 'object') +bl.type('blankaBallImage::onMount:1', 'object') +bl.type('blankaBallImage::onUnMount:1', 'object') +bl.type('blankaBallProjectile::onCollision:1', 'object') +bl.type('blinkPaintProjectile::onCollision:1', 'object') +bl.type('blueKeyImage::onFire:1', 'object') +bl.type('blueKeyImage::onHitObject:1', 'object') +bl.type('blueKeyImage::onPreFire:1', 'object') +bl.type('blueKeyImage::onStopFire:1', 'object') +bl.type('brick32xWaterData::disappear:1', 'object') +bl.type('brick32xWaterData::onClearFakeDeath:1', 'object') +bl.type('brick32xWaterData::onColorChange:1', 'object') +bl.type('brick32xWaterData::onDeath:1', 'object') +bl.type('brick32xWaterData::onFakeDeath:1', 'object') +bl.type('brick32xWaterData::onLoadPlant:1', 'object') +bl.type('brick32xWaterData::onPlant:1', 'object') +bl.type('brick32xWaterData::onRemove:1', 'object') +bl.type('brick32xWaterData::onTrustCheckFinished:1', 'object') +bl.type('brick32xWaterData::reappear:1', 'object') +bl.type('brick8xWaterData::disappear:1', 'object') +bl.type('brick8xWaterData::onClearFakeDeath:1', 'object') +bl.type('brick8xWaterData::onColorChange:1', 'object') +bl.type('brick8xWaterData::onDeath:1', 'object') +bl.type('brick8xWaterData::onFakeDeath:1', 'object') +bl.type('brick8xWaterData::onLoadPlant:1', 'object') +bl.type('brick8xWaterData::onPlant:1', 'object') +bl.type('brick8xWaterData::onRemove:1', 'object') +bl.type('brick8xWaterData::onTrustCheckFinished:1', 'object') +bl.type('brick8xWaterData::reappear:1', 'object') +bl.type('brick8xWaterRapidsData::disappear:1', 'object') +bl.type('brick8xWaterRapidsData::onClearFakeDeath:1', 'object') +bl.type('brick8xWaterRapidsData::onColorChange:1', 'object') +bl.type('brick8xWaterRapidsData::onDeath:1', 'object') +bl.type('brick8xWaterRapidsData::onFakeDeath:1', 'object') +bl.type('brick8xWaterRapidsData::onLoadPlant:1', 'object') +bl.type('brick8xWaterRapidsData::onPlant:1', 'object') +bl.type('brick8xWaterRapidsData::onRemove:1', 'object') +bl.type('brick8xWaterRapidsData::onTrustCheckFinished:1', 'object') +bl.type('brick8xWaterRapidsData::reappear:1', 'object') +bl.type('brick8xWaterRiverData::disappear:1', 'object') +bl.type('brick8xWaterRiverData::onClearFakeDeath:1', 'object') +bl.type('brick8xWaterRiverData::onColorChange:1', 'object') +bl.type('brick8xWaterRiverData::onDeath:1', 'object') +bl.type('brick8xWaterRiverData::onFakeDeath:1', 'object') +bl.type('brick8xWaterRiverData::onLoadPlant:1', 'object') +bl.type('brick8xWaterRiverData::onPlant:1', 'object') +bl.type('brick8xWaterRiverData::onRemove:1', 'object') +bl.type('brick8xWaterRiverData::onTrustCheckFinished:1', 'object') +bl.type('brick8xWaterRiverData::reappear:1', 'object') +bl.type('brickCheckpointData::onLoadPlant:1', 'object') +bl.type('brickCheckpointData::onPlant:1', 'object') +bl.type('brickCheckpointData::onPlayerTouch:1', 'object') +bl.type('brickDeployProjectile::onCollision:1', 'object') +bl.type('brickImage::onDeploy:1', 'object') +bl.type('brickSkullData::onPlant:1', 'object') +bl.type('brickSpawnPointData::onLoadPlant:1', 'object') +bl.type('brickSpawnPointData::onPlant:1', 'object') +bl.type('brickSpawnPointData::onRemove:1', 'object') +bl.type('brickTeledoorData::onLoadPlant:1', 'object') +bl.type('brickTeledoorData::onPlant:1', 'object') +bl.type('brickTeledoorData::onPlayerTouch:1', 'object') +bl.type('brickTeledoorData::onTrustCheckFinished:1', 'object') +bl.type('brickTreasureChestData::onDeath:1', 'object') +bl.type('brickTreasureChestData::onLoadPlant:1', 'object') +bl.type('brickTreasureChestData::onPlant:1', 'object') +bl.type('brickTreasureChestData::onRemove:1', 'object') +bl.type('brickTreasureChestData::openTreasureChest:1', 'object') +bl.type('brickVehicleSpawnData::onColorChange:1', 'object') +bl.type('calcExplosionCoverage:2', 'object') +bl.type('chromePaintProjectile::onCollision:1', 'object') +bl.type('colorGui::clickCancel:1', 'object') +bl.type('colorGui::doCallbacks:1', 'object') +bl.type('colorGui::done:1', 'object') +bl.type('colorGui::onSleep:1', 'object') +bl.type('colorGui::onWake:1', 'object') +bl.type('colorGui::popUp:1', 'object') +bl.type('colorGui::setMode:1', 'object') +bl.type('colorGui::update:1', 'object') +bl.type('commandToClient:1', 'object') +bl.type('compile', 'bool') +bl.type('connectingGui::cancel:1', 'object') +bl.type('connectingGui::onWake:1', 'object') +bl.type('containerBoxClear', 'bool') +bl.type('containerBoxEmpty', 'bool') +bl.type('containerRayCast:4', 'object') +bl.type('createCanvas', 'bool') +bl.type('createPath', 'bool') +bl.type('customAvatarGui::ClickX:1', 'object') +bl.type('customAvatarGui::onWake:1', 'object') +bl.type('customAvatar_modelSelect::onSelect:1', 'object') +bl.type('deathVehicle::onAdd:1', 'object') +bl.type('deathVehicle::onDriverLeave:1', 'object') +bl.type('deathVehicle::onImpact:1', 'object') +bl.type('deathVehicle::onRemove:1', 'object') +bl.type('deathVehicle::tumbleCheck:1', 'object') +bl.type('defaultControlsGui::apply:1', 'object') +bl.type('defaultControlsGui::clickClose:1', 'object') +bl.type('defaultControlsGui::onSleep:1', 'object') +bl.type('defaultControlsGui::onWake:1', 'object') +bl.type('discoverFile', 'bool') +bl.type('dodgeballImage::onBallTrigger:1', 'object') +bl.type('dodgeballImage::onCharge:1', 'object') +bl.type('dodgeballImage::onFire:1', 'object') +bl.type('dodgeballImage::onMount:1', 'object') +bl.type('dodgeballImage::onUnMount:1', 'object') +bl.type('dodgeballItem::onUse:1', 'object') +bl.type('dodgeballProjectile::onCollision:1', 'object') +bl.type('doesAllowConnections', 'bool') +bl.type('dofScreenShot', 'bool') +bl.type('enableJoystick', 'bool') +bl.type('enableMouse', 'bool') +bl.type('enableWinConsole:1', 'bool') +bl.type('escapeMenu::clickAdmin:1', 'object') +bl.type('escapeMenu::clickLoadBricks:1', 'object') +bl.type('escapeMenu::clickMinigames:1', 'object') +bl.type('escapeMenu::clickSaveBricks:1', 'object') +bl.type('escapeMenu::onWake:1', 'object') +bl.type('escapeMenu::toggle:1', 'object') +bl.type('exec', 'bool') +bl.type('fileCopy', 'bool') +bl.type('fileDelete', 'bool') +bl.type('filtersGui::onSleep:1', 'object') +bl.type('filtersGui::onWake:1', 'object') +bl.type('flatPaintProjectile::onCollision:1', 'object') +bl.type('footballImage::onAbortCharge:1', 'object') +bl.type('footballImage::onBallTrigger:1', 'object') +bl.type('footballImage::onCharge:1', 'object') +bl.type('footballImage::onFire:1', 'object') +bl.type('footballImage::onMount:1', 'object') +bl.type('footballImage::onUnMount:1', 'object') +bl.type('footballProjectile::onCollision:1', 'object') +bl.type('footballProjectile::onRest:1', 'object') +bl.type('fxDTSBrick.isBasePlate', 'bool') +bl.type('fxDTSBrick.isPlanted', 'bool') +bl.type('fxDTSBrick::canExplode', 'bool') +bl.type('fxDTSBrick::canExplode:1', 'object') +bl.type('fxDTSBrick::colorVehicle:1', 'object') +bl.type('fxDTSBrick::delete:1', 'object') +bl.type('fxDTSBrick::dumpDownList:1', 'object') +bl.type('fxDTSBrick::dumpUpList:1', 'object') +bl.type('fxDTSBrick::getAngleID:1', 'object') +bl.type('fxDTSBrick::getColorFxID:1', 'object') +bl.type('fxDTSBrick::getColorID:1', 'object') +bl.type('fxDTSBrick::getDataBlock:1', 'object') +bl.type('fxDTSBrick::getDestructionVolume:1', 'object') +bl.type('fxDTSBrick::getDistanceFromGround:1', 'object') +bl.type('fxDTSBrick::getDownBrick', 'object') +bl.type('fxDTSBrick::getDownBrick:1', 'object') +bl.type('fxDTSBrick::getExposedAreaBottom:1', 'object') +bl.type('fxDTSBrick::getExposedAreaEast:1', 'object') +bl.type('fxDTSBrick::getExposedAreaNorth:1', 'object') +bl.type('fxDTSBrick::getExposedAreaSouth:1', 'object') +bl.type('fxDTSBrick::getExposedAreaTop:1', 'object') +bl.type('fxDTSBrick::getExposedAreaWest:1', 'object') +bl.type('fxDTSBrick::getFakeDeadTime:1', 'object') +bl.type('fxDTSBrick::getLightId:1', 'object') +bl.type('fxDTSBrick::getNumDownBricks:1', 'object') +bl.type('fxDTSBrick::getNumUpBricks:1', 'object') +bl.type('fxDTSBrick::getPrintID:1', 'object') +bl.type('fxDTSBrick::getShapeFxID:1', 'object') +bl.type('fxDTSBrick::getUpBrick', 'object') +bl.type('fxDTSBrick::getUpBrick:1', 'object') +bl.type('fxDTSBrick::hasFakePathToGround', 'bool') +bl.type('fxDTSBrick::hasFakePathToGround:1', 'object') +bl.type('fxDTSBrick::hasPathToGround', 'bool') +bl.type('fxDTSBrick::hasPathToGround:1', 'object') +bl.type('fxDTSBrick::isBasePlate', 'bool') +bl.type('fxDTSBrick::isBasePlate:1', 'object') +bl.type('fxDTSBrick::isColliding', 'bool') +bl.type('fxDTSBrick::isColliding:1', 'object') +bl.type('fxDTSBrick::isDead', 'bool') +bl.type('fxDTSBrick::isDead:1', 'object') +bl.type('fxDTSBrick::isExposed', 'bool') +bl.type('fxDTSBrick::isExposed:1', 'object') +bl.type('fxDTSBrick::isFakeDead', 'bool') +bl.type('fxDTSBrick::isFakeDead:1', 'object') +bl.type('fxDTSBrick::isInSceneGraph', 'bool') +bl.type('fxDTSBrick::isInSceneGraph:1', 'object') +bl.type('fxDTSBrick::isInTree', 'bool') +bl.type('fxDTSBrick::isInTree:1', 'object') +bl.type('fxDTSBrick::isPlanted', 'bool') +bl.type('fxDTSBrick::isPlanted:1', 'object') +bl.type('fxDTSBrick::isRayCasting', 'bool') +bl.type('fxDTSBrick::isRayCasting:1', 'object') +bl.type('fxDTSBrick::isRendering', 'bool') +bl.type('fxDTSBrick::isRendering:1', 'object') +bl.type('fxDTSBrick::isTreeRendering', 'bool') +bl.type('fxDTSBrick::isTreeRendering:1', 'object') +bl.type('fxDTSBrick::killBrick:1', 'object') +bl.type('fxDTSBrick::onDeath:1', 'object') +bl.type('fxDTSBrick::onLoadPlant:1', 'object') +bl.type('fxDTSBrick::onRemove:1', 'object') +bl.type('fxDTSBrick::plant:1', 'object') +bl.type('fxDTSBrick::sendWrenchData:1', 'object') +bl.type('fxDTSBrick::setColliding:1', 'object') +bl.type('fxDTSBrick::setColliding:2', 'bool') +bl.type('fxDTSBrick::setColor:1', 'object') +bl.type('fxDTSBrick::setColorFX:1', 'object') +bl.type('fxDTSBrick::setDataBlock', 'bool') +bl.type('fxDTSBrick::setDataBlock:1', 'object') +bl.type('fxDTSBrick::setItem:1', 'object') +bl.type('fxDTSBrick::setItemPosition:1', 'object') +bl.type('fxDTSBrick::setItemRespawntime:1', 'object') +bl.type('fxDTSBrick::setPrint:1', 'object') +bl.type('fxDTSBrick::setRayCasting:1', 'object') +bl.type('fxDTSBrick::setRayCasting:2', 'bool') +bl.type('fxDTSBrick::setRendering:1', 'object') +bl.type('fxDTSBrick::setRendering:2', 'bool') +bl.type('fxDTSBrick::setShapeFX:1', 'object') +bl.type('fxDTSBrick::setTrusted:1', 'object') +bl.type('fxDTSBrick::setTrusted:2', 'bool') +bl.type('fxDTSBrick::trustCheckFinished:1', 'object') +bl.type('fxDTSBrick::willCauseChainKill', 'bool') +bl.type('fxDTSBrick::willCauseChainKill:1', 'object') +bl.type('fxDTSBrickData.alwaysShowWireFrame', 'bool') +bl.type('fxDTSBrickData.brickSizeX', 'object') +bl.type('fxDTSBrickData.brickSizeY', 'object') +bl.type('fxDTSBrickData.brickSizeZ', 'object') +bl.type('fxDTSBrickData.canCoverBottom', 'bool') +bl.type('fxDTSBrickData.canCoverEast', 'bool') +bl.type('fxDTSBrickData.canCoverNorth', 'bool') +bl.type('fxDTSBrickData.canCoverSouth', 'bool') +bl.type('fxDTSBrickData.canCoverTop', 'bool') +bl.type('fxDTSBrickData.canCoverWest', 'bool') +bl.type('fxDTSBrickData.hasPrint', 'bool') +bl.type('fxDTSBrickData.indestructable', 'bool') +bl.type('fxDTSBrickData.isWaterBrick', 'bool') +bl.type('fxDTSBrickData::disappear:1', 'object') +bl.type('fxDTSBrickData::getBlockArrayBit', 'bool') +bl.type('fxDTSBrickData::getBlockArrayBit:1', 'object') +bl.type('fxDTSBrickData::getMaxSide:1', 'object') +bl.type('fxDTSBrickData::getVolume:1', 'object') +bl.type('fxDTSBrickData::onAdd:1', 'object') +bl.type('fxDTSBrickData::onClearFakeDeath:1', 'object') +bl.type('fxDTSBrickData::onColorChange:1', 'object') +bl.type('fxDTSBrickData::onDeath:1', 'object') +bl.type('fxDTSBrickData::onFakeDeath:1', 'object') +bl.type('fxDTSBrickData::onLoadPlant:1', 'object') +bl.type('fxDTSBrickData::onPlant:1', 'object') +bl.type('fxDTSBrickData::onPlayerTouch:1', 'object') +bl.type('fxDTSBrickData::onRemove:1', 'object') +bl.type('fxDTSBrickData::onTeledoorEnter:1', 'object') +bl.type('fxDTSBrickData::onTeledoorExit:1', 'object') +bl.type('fxDTSBrickData::onTrustCheckFailed:1', 'object') +bl.type('fxDTSBrickData::onTrustCheckFinished:1', 'object') +bl.type('fxDTSBrickData::onUse:1', 'object') +bl.type('fxDTSBrickData::openTreasureChest:1', 'object') +bl.type('fxDTSBrickData::reappear:1', 'object') +bl.type('fxDayCycle.targetUseDefaultVector', 'bool') +bl.type('fxDayCycle::sendUpdate:1', 'object') +bl.type('fxDayCycle::setDayLength:1', 'object') +bl.type('fxDayCycle::setDayOffset:1', 'object') +bl.type('fxDayCycle::setEnabled:1', 'object') +bl.type('fxDayCycle::setEnabled:2', 'bool') +bl.type('fxLight.Enable', 'bool') +bl.type('fxLight::attachToBrick:1', 'object') +bl.type('fxLight::attachToBrick:2', 'object') +bl.type('fxLight::attachToObject:1', 'object') +bl.type('fxLight::attachToObject:2', 'object') +bl.type('fxLight::detachFromObject:1', 'object') +bl.type('fxLight::getPosition:1', 'object') +bl.type('fxLight::getTransform:1', 'object') +bl.type('fxLight::onRemove:1', 'object') +bl.type('fxLight::reset:1', 'object') +bl.type('fxLight::setEnable:1', 'object') +bl.type('fxLight::setEnable:2', 'bool') +bl.type('fxLightData.AnimBrightness', 'bool') +bl.type('fxLightData.AnimColor', 'bool') +bl.type('fxLightData.AnimOffsets', 'bool') +bl.type('fxLightData.AnimRadius', 'bool') +bl.type('fxLightData.AnimRotation', 'bool') +bl.type('fxLightData.ConstantSizeOn', 'bool') +bl.type('fxLightData.FlareOn', 'bool') +bl.type('fxLightData.FlareTP', 'bool') +bl.type('fxLightData.LerpBrightness', 'bool') +bl.type('fxLightData.LerpColor', 'bool') +bl.type('fxLightData.LerpOffset', 'bool') +bl.type('fxLightData.LerpRadius', 'bool') +bl.type('fxLightData.LerpRotation', 'bool') +bl.type('fxLightData.LightOn', 'bool') +bl.type('fxLightData.LinkFlare', 'bool') +bl.type('fxLightData.LinkFlareSize', 'bool') +bl.type('fxLightData.SingleColorKeys', 'bool') +bl.type('fxPlane.additiveBlend', 'bool') +bl.type('fxPlane.blend', 'bool') +bl.type('fxPlane.colorMultiply', 'bool') +bl.type('fxPlane.isSolid', 'bool') +bl.type('fxPlane::sendUpdate:1', 'object') +bl.type('fxSunLight.AnimAzimuth', 'bool') +bl.type('fxSunLight.AnimBrightness', 'bool') +bl.type('fxSunLight.AnimColor', 'bool') +bl.type('fxSunLight.AnimElevation', 'bool') +bl.type('fxSunLight.AnimRotation', 'bool') +bl.type('fxSunLight.AnimSize', 'bool') +bl.type('fxSunLight.Enable', 'bool') +bl.type('fxSunLight.FlareTP', 'bool') +bl.type('fxSunLight.LerpAzimuth', 'bool') +bl.type('fxSunLight.LerpBrightness', 'bool') +bl.type('fxSunLight.LerpColor', 'bool') +bl.type('fxSunLight.LerpElevation', 'bool') +bl.type('fxSunLight.LerpRotation', 'bool') +bl.type('fxSunLight.LerpSize', 'bool') +bl.type('fxSunLight.LinkFlareSize', 'bool') +bl.type('fxSunLight.LockToRealSun', 'bool') +bl.type('fxSunLight.SingleColorKeys', 'bool') +bl.type('fxSunLight::reset:1', 'object') +bl.type('fxSunLight::sendUpdate:1', 'object') +bl.type('fxSunLight::setAzimuthKeys:1', 'object') +bl.type('fxSunLight::setAzimuthTime:1', 'object') +bl.type('fxSunLight::setBlendMode:1', 'object') +bl.type('fxSunLight::setBlueKeys:1', 'object') +bl.type('fxSunLight::setBrightnessKeys:1', 'object') +bl.type('fxSunLight::setBrightnessTime:1', 'object') +bl.type('fxSunLight::setColorTime:1', 'object') +bl.type('fxSunLight::setElevationKeys:1', 'object') +bl.type('fxSunLight::setElevationTime:1', 'object') +bl.type('fxSunLight::setEnable:1', 'object') +bl.type('fxSunLight::setFadeTime:1', 'object') +bl.type('fxSunLight::setFlareBitmaps:1', 'object') +bl.type('fxSunLight::setFlareBrightness:1', 'object') +bl.type('fxSunLight::setFlareColor:1', 'object') +bl.type('fxSunLight::setFlareSize:1', 'object') +bl.type('fxSunLight::setFlareTP:1', 'object') +bl.type('fxSunLight::setGreenKeys:1', 'object') +bl.type('fxSunLight::setLerpAzimuth:1', 'object') +bl.type('fxSunLight::setLerpBrightness:1', 'object') +bl.type('fxSunLight::setLerpColor:1', 'object') +bl.type('fxSunLight::setLerpElevation:1', 'object') +bl.type('fxSunLight::setLerpRotation:1', 'object') +bl.type('fxSunLight::setLerpSize:1', 'object') +bl.type('fxSunLight::setLinkFlareSize:1', 'object') +bl.type('fxSunLight::setMaxAzimuth:1', 'object') +bl.type('fxSunLight::setMaxBrightness:1', 'object') +bl.type('fxSunLight::setMaxColor:1', 'object') +bl.type('fxSunLight::setMaxElevation:1', 'object') +bl.type('fxSunLight::setMaxRotation:1', 'object') +bl.type('fxSunLight::setMaxSize:1', 'object') +bl.type('fxSunLight::setMinAzimuth:1', 'object') +bl.type('fxSunLight::setMinBrightness:1', 'object') +bl.type('fxSunLight::setMinColor:1', 'object') +bl.type('fxSunLight::setMinElevation:1', 'object') +bl.type('fxSunLight::setMinRotation:1', 'object') +bl.type('fxSunLight::setMinSize:1', 'object') +bl.type('fxSunLight::setRedKeys:1', 'object') +bl.type('fxSunLight::setRotationKeys:1', 'object') +bl.type('fxSunLight::setRotationTime:1', 'object') +bl.type('fxSunLight::setSingleColorKeys:1', 'object') +bl.type('fxSunLight::setSizeKeys:1', 'object') +bl.type('fxSunLight::setSizeTime:1', 'object') +bl.type('fxSunLight::setSunAzimuth:1', 'object') +bl.type('fxSunLight::setSunElevation:1', 'object') +bl.type('fxSunLight::setUseAzimuth:1', 'object') +bl.type('fxSunLight::setUseBrightness:1', 'object') +bl.type('fxSunLight::setUseColor:1', 'object') +bl.type('fxSunLight::setUseElevation:1', 'object') +bl.type('fxSunLight::setUseRotation:1', 'object') +bl.type('fxSunLight::setUseSize:1', 'object') +bl.type('getBrickLimit', 'object') +bl.type('getCurrentQuotaObject', 'object') +bl.type('getParticleDisconnectMode', 'bool') +bl.type('glTexImage3D', 'bool') +bl.type('glowPaintProjectile::onCollision:1', 'object') +bl.type('greenKeyImage::onFire:1', 'object') +bl.type('greenKeyImage::onHitObject:1', 'object') +bl.type('greenKeyImage::onPreFire:1', 'object') +bl.type('greenKeyImage::onStopFire:1', 'object') +bl.type('gunImage::onFire:1', 'object') +bl.type('hammerImage::onFire:1', 'object') +bl.type('hammerImage::onHitObject:1', 'object') +bl.type('hammerImage::onPreFire:1', 'object') +bl.type('hammerImage::onStopFire:1', 'object') +bl.type('hatTCPObj::onConnectFailed:1', 'object') +bl.type('hatTCPObj::onConnected:1', 'object') +bl.type('hatTCPObj::onDNSFailed:1', 'object') +bl.type('hatTCPObj::onDisconnect:1', 'object') +bl.type('hatTCPObj::onLine:1', 'object') +bl.type('horseBasketballImage::onBallTrigger:1', 'object') +bl.type('horseBasketballImage::onFire:1', 'object') +bl.type('horseBasketballImage::onMount:1', 'object') +bl.type('horseBasketballImage::onUnMount:1', 'object') +bl.type('horseDodgeballImage::onBallTrigger:1', 'object') +bl.type('horseDodgeballImage::onFire:1', 'object') +bl.type('horseDodgeballImage::onMount:1', 'object') +bl.type('horseDodgeballImage::onUnMount:1', 'object') +bl.type('horseFootballImage::onBallTrigger:1', 'object') +bl.type('horseFootballImage::onCharge:1', 'object') +bl.type('horseFootballImage::onFire:1', 'object') +bl.type('horseFootballImage::onMount:1', 'object') +bl.type('horseFootballImage::onUnMount:1', 'object') +bl.type('horseRayImage::onFire:1', 'object') +bl.type('horseRayProjectile::Damage:1', 'object') +bl.type('horseSoccerBallImage::onBallTrigger:1', 'object') +bl.type('horseSoccerBallImage::onFire:1', 'object') +bl.type('horseSoccerBallImage::onMount:1', 'object') +bl.type('horseSoccerBallImage::onUnMount:1', 'object') +bl.type('horseSoccerBallStandImage::onBallTrigger:1', 'object') +bl.type('horseSoccerBallStandImage::onFire:1', 'object') +bl.type('horseSoccerBallStandImage::onMount:1', 'object') +bl.type('horseSoccerBallStandImage::onUnMount:1', 'object') +bl.type('isDeviceFullScreenOnly', 'bool') +bl.type('isEventPending', 'bool') +bl.type('isFile', 'bool') +bl.type('isFullScreen', 'bool') +bl.type('isFunction', 'bool') +bl.type('isJoystickDetected', 'bool') +bl.type('isKoreanBuild', 'bool') +bl.type('isLANAddress', 'bool') +bl.type('isMacintosh', 'bool') +bl.type('isObject', 'bool') +bl.type('isPackage', 'bool') +bl.type('isUnlocked', 'bool') +bl.type('isWindows', 'bool') +bl.type('isWriteableFileName', 'bool') +bl.type('jelloPaintProjectile::onCollision:1', 'object') +bl.type('joinMiniGameGui::ClickLeave:1', 'object') +bl.type('joinMiniGameGui::onWake:1', 'object') +bl.type('lockMouse:1', 'bool') +bl.type('mm_Fade::OnWait:1', 'object') +bl.type('mm_Fade::onDone:1', 'object') +bl.type('newMessageHud::onSleep:1', 'object') +bl.type('newMessageHud::onWake:1', 'object') +bl.type('newMessageHud::open:1', 'object') +bl.type('newMessageHud::updatePosition:1', 'object') +bl.type('newMessageHud::updateTypePosition:1', 'object') +bl.type('nextResolution', 'bool') +bl.type('noHudGui::onRender:1', 'object') +bl.type('noHudGui::onSleep:1', 'object') +bl.type('noHudGui::onWake:1', 'object') +bl.type('optionsDlg::RemapAll:1', 'object') +bl.type('optionsDlg::RemapNext:1', 'object') +bl.type('optionsDlg::UpdateAvailableShaders:1', 'object') +bl.type('optionsDlg::applyGraphics:1', 'object') +bl.type('optionsDlg::clearAllBinds:1', 'object') +bl.type('optionsDlg::clickLatencyOption:1', 'object') +bl.type('optionsDlg::onSleep:1', 'object') +bl.type('optionsDlg::onWake:1', 'object') +bl.type('optionsDlg::setBrickFXQuality:1', 'object') +bl.type('optionsDlg::setDefaultBinds:1', 'object') +bl.type('optionsDlg::setLightingQuality:1', 'object') +bl.type('optionsDlg::setPane:1', 'object') +bl.type('optionsDlg::setParticleQuality:1', 'object') +bl.type('optionsDlg::setPhysicsQuality:1', 'object') +bl.type('optionsDlg::setShaderQuality:1', 'object') +bl.type('optionsDlg::setTextureQuality:1', 'object') +bl.type('optionsDlg::updateDrawDistanceBlocker:1', 'object') +bl.type('optionsDlg::updateFOV:1', 'object') +bl.type('optionsDlg::updateMaxViewDistance:1', 'object') +bl.type('optionsDlg::updateTempBrickBlockers:1', 'object') +bl.type('paintProjectile::onCollision:1', 'object') +bl.type('pearlPaintProjectile::onCollision:1', 'object') +bl.type('playJournal:2', 'bool') +bl.type('postServerTCPObj::onConnectFailed:1', 'object') +bl.type('postServerTCPObj::onConnected:1', 'object') +bl.type('postServerTCPObj::onDNSFailed:1', 'object') +bl.type('postServerTCPObj::onDisconnect:1', 'object') +bl.type('postServerTCPObj::onLine:1', 'object') +bl.type('prevResolution', 'bool') +bl.type('protocolRegistryCheck', 'bool') +bl.type('pushBroomImage::onFire:1', 'object') +bl.type('pushBroomImage::onStopFire:1', 'object') +bl.type('queryMasterTCPObj::onConnectFailed:1', 'object') +bl.type('queryMasterTCPObj::onConnected:1', 'object') +bl.type('queryMasterTCPObj::onDNSFailed:1', 'object') +bl.type('queryMasterTCPObj::onDisconnect:1', 'object') +bl.type('queryMasterTCPObj::onLine:1', 'object') +bl.type('rainbowPaintProjectile::onCollision:1', 'object') +bl.type('recordingsDlg::onWake:1', 'object') +bl.type('redKeyImage::onFire:1', 'object') +bl.type('redKeyImage::onHitObject:1', 'object') +bl.type('redKeyImage::onPreFire:1', 'object') +bl.type('redKeyImage::onStopFire:1', 'object') +bl.type('redbookClose', 'bool') +bl.type('redbookOpen', 'bool') +bl.type('redbookPlay', 'bool') +bl.type('redbookSetVolume', 'bool') +bl.type('redbookStop', 'bool') +bl.type('regNameGui::onClose:1', 'object') +bl.type('regNameGui::onSleep:1', 'object') +bl.type('regNameGui::onType:1', 'object') +bl.type('regNameGui::onWake:1', 'object') +bl.type('regNameGui::register:1', 'object') +bl.type('regName_tcpObj::onConnectFailed:1', 'object') +bl.type('regName_tcpObj::onConnected:1', 'object') +bl.type('regName_tcpObj::onDNSFailed:1', 'object') +bl.type('regName_tcpObj::onDisconnect:1', 'object') +bl.type('regName_tcpObj::onLine:1', 'object') +bl.type('saveBricksGui::onSleep:1', 'object') +bl.type('saveBricksGui::onWake:1', 'object') +bl.type('screenShot', 'bool') +bl.type('selectBLIDGui::onSleep:1', 'object') +bl.type('selectBLIDGui::onWake:1', 'object') +bl.type('selectBLIDGui::select:1', 'object') +bl.type('sendTimeScaleToClient:1', 'object') +bl.type('servAuthTCPobj::onConnectFailed:1', 'object') +bl.type('servAuthTCPobj::onConnected:1', 'object') +bl.type('servAuthTCPobj::onDNSFailed:1', 'object') +bl.type('servAuthTCPobj::onLine:1', 'object') +bl.type('serverCmdSymbolHandeler', 'bool') +bl.type('setClipboard', 'bool') +bl.type('setCurrentQuotaObject:1', 'object') +bl.type('setDisplayDevice', 'bool') +bl.type('setDisplayDevice:5', 'bool') +bl.type('setEchoFileLoads:1', 'bool') +bl.type('setJoinIP_tcpObj::onLine:1', 'object') +bl.type('setNetPort', 'bool') +bl.type('setRes', 'bool') +bl.type('setScreenMode', 'bool') +bl.type('setScreenMode:4', 'bool') +bl.type('setServerInfo', 'bool') +bl.type('setVerticalSync', 'bool') +bl.type('setVerticalSync:1', 'bool') +bl.type('skiVehicle::onAdd:1', 'object') +bl.type('skiVehicle::onDriverLeave:1', 'object') +bl.type('skiVehicle::onImpact:1', 'object') +bl.type('skiVehicle::onUnMount:1', 'object') +bl.type('skiVehicle::onWreck:1', 'object') +bl.type('soccerBallImage::onBallTrigger:1', 'object') +bl.type('soccerBallImage::onCharge:1', 'object') +bl.type('soccerBallImage::onFire:1', 'object') +bl.type('soccerBallImage::onMount:1', 'object') +bl.type('soccerBallImage::onUnMount:1', 'object') +bl.type('soccerBallItem::onBallCollision:1', 'object') +bl.type('soccerBallItem::onUse:1', 'object') +bl.type('soccerBallProjectile::onCollision:1', 'object') +bl.type('soccerBallProjectile::onRest:1', 'object') +bl.type('soccerBallStandImage::onBallTrigger:1', 'object') +bl.type('soccerBallStandImage::onFire:1', 'object') +bl.type('soccerBallStandImage::onMount:1', 'object') +bl.type('soccerBallStandImage::onUnMount:1', 'object') +bl.type('spearImage::onAbortCharge:1', 'object') +bl.type('spearImage::onCharge:1', 'object') +bl.type('spearImage::onFire:1', 'object') +bl.type('stablePaintProjectile::onCollision:1', 'object') +bl.type('swirlPaintProjectile::onCollision:1', 'object') +bl.type('switchBitDepth', 'bool') +bl.type('swordImage::onPreFire:1', 'object') +bl.type('swordImage::onStopFire:1', 'object') +bl.type('ti_tcp::onConnectFailed:1', 'object') +bl.type('ti_tcp::onConnected:1', 'object') +bl.type('ti_tcp::onDisconnect:1', 'object') +bl.type('ti_tcp::onLine:1', 'object') +bl.type('toggleFullScreen', 'bool') +bl.type('trace:1', 'bool') +bl.type('unBanGui::clickUnBan:1', 'object') +bl.type('unBanGui::onSleep:1', 'object') +bl.type('unBanGui::onWake:1', 'object') +bl.type('unBanGui::sortList:1', 'object') +bl.type('unBanGui::sortNumList:1', 'object') +bl.type('unBanGui::unBan:1', 'object') +bl.type('upnpAdd', 'bool') +bl.type('wrenchBotDlg::LoadDataBlocks:1', 'object') +bl.type('wrenchBotDlg::Respawn:1', 'object') +bl.type('wrenchBotDlg::botOff:1', 'object') +bl.type('wrenchBotDlg::botOn:1', 'object') +bl.type('wrenchBotDlg::onSleep:1', 'object') +bl.type('wrenchBotDlg::onWake:1', 'object') +bl.type('wrenchBotDlg::send:1', 'object') +bl.type('wrenchDlg::onWake:1', 'object') +bl.type('wrenchEventsDlg::createTargetList:1', 'object') +bl.type('wrenchSoundDlg::onWake:1', 'object') +bl.type('wrenchVehicleSpawnDlg::onWake:1', 'object') +bl.type('yellowKeyImage::onFire:1', 'object') +bl.type('yellowKeyImage::onHitObject:1', 'object') +bl.type('yellowKeyImage::onPreFire:1', 'object') +bl.type('yellowKeyImage::onStopFire:1', 'object') + +-- Parsed from dumpConsoleClasses() and dumpConsoleFunctions() and manually verified +bl.type('GuiCanvas::getContent', 'object') +bl.type('ParticleEmitterNode::getEmitterDataBlock', 'object') +bl.type('ShapeBase::getControllingClient', 'object') +bl.type('ShapeBase::getMountedImage', 'object') +bl.type('ShapeBase::getPendingImage', 'object') +bl.type('SimObject::getGroup', 'object') +bl.type('containerSearchNext', 'object') +bl.type('fxDTSBrick.client', 'object') +bl.type('getDataBlock', 'object') +bl.type('alxPlay:1', 'object') + +-- Manually entered +bl.type('ShapeBase::getControlObject', 'object') +bl.type('GameConnection::getControlObject', 'object') +bl.type('GameBase::setDataBlock:2', 'object') +bl.type('NetObject::clearScopeToClient:2', 'object') + +print(' Executed libbl-types.lua') diff --git a/src/util/libbl.lua b/src/util/libbl.lua new file mode 100644 index 0000000..a5a60a8 --- /dev/null +++ b/src/util/libbl.lua @@ -0,0 +1,840 @@ +-- bl library +-- Main lua-side functionality of bllua, +-- provided through the global table 'bl.' + +-- todo: set + +local _bllua_ts = ts + +bl = bl or {} + +-- Misc +-- Apply a function to each element in a list, building a new list from the returns +local function map(t,f) + local u = {} + for i,v in ipairs(t) do + u[i] = f(v) + end + return u +end +local function isValidFuncName(name) + return type(name)=='string' and name:find('^[a-zA-Z0-9_]+$') +end +local function isValidFuncNameNs(name) + return type(name)=='string' and ( + name:find('^[a-zA-Z0-9_]+$') or + name:find('^[a-zA-Z0-9_]+::[a-zA-Z0-9_]+$') ) +end +local function isValidFuncNameNsArgn(name) + return type(name)=='string' and ( + name:find('^[a-zA-Z0-9_]+$') or + name:find('^[a-zA-Z0-9_]+%.[a-zA-Z0-9_]+$') or + name:find('^[a-zA-Z0-9_]+::[a-zA-Z0-9_]+$') or + name:find('^[a-zA-Z0-9_]+:[0-9]+$') or + name:find('^[a-zA-Z0-9_]+::[a-zA-Z0-9_]+:[0-9]+$') ) +end +-- Whether a var can be converted into a TS vector +local function isTsVector(val) + if type(val)~='table' then return false end + if #val~=3 and #val~=2 then return false end + if val.__is_vector then return true end + for _,v in ipairs(val) do + if type(v)~='number' then return false end + end + return true +end +-- Use strings for object types instead of integer bitmasks like in TS +local tsTypesByName = { + ['all'] = -1, + ['static'] = 1, + ['environment'] = 2, + ['terrain'] = 4, + ['water'] = 16, + ['trigger'] = 32, + ['marker'] = 64, + ['gamebase'] = 1024, + ['shapebase'] = 2048, + ['camera'] = 4096, + ['staticshape'] = 8192, + ['player'] = 16384, + ['item'] = 32768, + ['vehicle'] = 65536, + ['vehicleblocker'] = 131072, + ['projectile'] = 262144, + ['explosion'] = 524288, + ['corpse'] = 1048576, + ['debris'] = 4194304, + ['physicalzone'] = 8388608, + ['staticts'] = 16777216, + ['brick'] = 33554432, + ['brickalways'] = 67108864, + ['staticrendered'] = 134217728, + ['damagableitem'] = 268435456, +} +local tsTypesByNum = {} +for k,v in pairs(tsTypesByName) do + tsTypesByNum[v] = k +end + +-- Type conversion +local toTsObject +-- Convert a string from TS into a boolean +-- Note: Nonempty nonnumeric strings evaluate to 1, unlike in TS +local function tsBool(v) return v~='' and v~='0' end +-- Convert a Lua var into a TS string, or error if not possible +local function valToTs(val) + if val==nil then -- nil -> '' + return '' + elseif type(val)=='boolean' then -- bool -> 0 or 1 + return val and '1' or '0' + elseif type(val)=='number' then -- number + return tostring(val) + elseif type(val)=='string' then -- string + return val + elseif type(val)=='table' then + if val._tsObjectId then -- object -> object id + return tostring(val._tsObjectId) + elseif isTsVector(val) then -- vector - > 3 numbers + return table.concat(val, ' ') + elseif #val==2 and isTsVector(val[1]) and isTsVector(val[2]) then + -- box - > 6 numbers + return table.concat(val[1], ' ')..' '..table.concat(val[2], ' ') + else + error('valToTs: could not convert table', 3) + end + else + error('valToTs: could not convert '..type(val), 3) + end +end +bl._forceType = bl._forceType or {} +local function valFromTs(val, name) + if type(val)~='string' then + error('valFromTs: expected string, got '..type(val), 3) end + if name then + local nameL = name:lower() + if bl._forceType[nameL] then + local typ = bl._forceType[nameL] + if typ=='boolean' then + return tsBool(val) + elseif typ=='object' then + return toTsObject(val) + else + error('valFromTs: invalid force type '..typ, 3) + end + end + end + -- '' -> nil + if val=='' then return nil end + -- number + local num = tonumber(val) + if num then return num end + -- vector + 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)} end + 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]+)$') + -- box (2 vectors) + if x1S then return { + vector{tonumber(x1S),tonumber(y1S),tonumber(z1S)}, + vector{tonumber(x2S),tonumber(y2S),tonumber(z2S)} } end + -- string + return val +end +local function arglistFromTs(name, argsS) + local args = {} + for i,arg in ipairs(argsS) do + args[i] = valFromTs(arg, name..':'..i) + end + return args +end +local function arglistToTs(args) + return map(args, valToTs) +end +function bl.type(name,typ) + if typ~='bool' and typ~='boolean' and typ~='object' and typ~=nil then + error('bl.type: can only set type to \'bool\' or \'object\' or nil', 2) end + if not isValidFuncNameNsArgn(name) then + error('bl.type: invalid function or variable name \''..name..'\'', 2) end + if typ=='bool' then typ='boolean' end + bl._forceType[name:lower()] = typ +end + + +-- Value detection + +local function isTsObject(t) + return type(t)=='table' and t._tsObjectId~=nil +end + +local function tsIsObject(name) return tsBool(_bllua_ts.call('isObject', name)) end +local function tsIsFunction(name) return tsBool(_bllua_ts.call('isFunction', name)) end +local function tsIsFunctionNs(ns, name) return tsBool(_bllua_ts.call('isFunction', ns, name)) end +local function tsIsFunctionNsname(nsname) + local ns, name = nsname:match('^([^:]+)::([^:]+)$') + if ns then return tsIsFunctionNs(ns, name) + else return tsIsFunction(nsname) end +end + +function bl.isObject(obj) + if isTsObject(obj) then + obj = obj._tsObjectId + elseif type(obj)=='number' then + obj = tostring(obj) + elseif type(obj)~='string' then + error('bl.isObject: argument #1: expected torque object, number, or string', 2) + end + return tsIsObject(obj) +end +function bl.isFunction(a1, a2) + if type(a1)~='string' then + error('bl.isFunction: argument #1: expected string', 2) end + if a2 then + if type(a2)~='string' then + error('bl.isFunction: argument #2: expected string', 2) end + return tsIsFunctionNs(a1, a2) + else + return tsIsFunction(a1) + end +end + +-- Torque object pseudo-class +bl._objectUserMetas = bl._objectUserMetas or {} +function bl.class(name, inherit) + if not ( type(name)=='string' and isValidFuncName(name) ) then + error('bl.class: argument #1: invalid class name', 2) end + if not ( inherit==nil or (type(inherit)=='string' and isValidFuncName(inherit)) ) then + error('bl.class: argument #2: inherit name must be a string or nil', 2) end + name = name:lower() + + local met = bl._objectUserMetas[name] or {} + bl._objectUserMetas[name] = met + met._name = name + + if inherit then + inherit = inherit:lower() + + local inh = bl._objectUserMetas[inherit] + if not inh then error('bl.class: argument #2: \''..inherit..'\' is not the '.. + 'name of an existing class', 2) end + + local inhI = bl._objectUserMetas[name]._inherit + if inhI and inhI~=inh then + error('bl.class: argument #2: class already exists and '.. + 'inherits a different parent.', 2) end + + bl._objectUserMetas[name]._inherit = inh + end +end +local function objectInheritedMetas(name) + local inh = bl._objectUserMetas[name:lower()] + return function() + local inhP = inh + if inhP==nil then return nil end + inh = inh._inherit + return inhP + end +end +local tsObjectMeta = { + -- __index: Called when accessing fields that don't exist in the object itself + -- Return torque member function or value + __index = function(t, name) + if rawget(t,'_deleted') then + error('ts object index: object no longer exists', 2) end + if type(name)~='string' and type(name)~='number' then + error('ts object index: index must be a string or number', 2) end + if getmetatable(t)[name] then + return getmetatable(t)[name] + elseif type(name)=='number' then + if not tsIsFunctionNs(rawget(t,'_tsNamespace'), 'getObject') then + error('ts object __index: index is number, but object does not have '.. + 'getObject method', 2) end + return toTsObject(_bllua_ts.callobj(t._tsObjectId, 'getObject', + tostring(name))) + else + for inh in objectInheritedMetas(rawget(t,'_tsClassName')) do + if inh[name] then return inh[name] end + end + if tsIsFunctionNs(rawget(t,'_tsNamespace'), name) then + return function(t, ...) + local args = {...} + local argsS = arglistToTs(args) + return valFromTs(_bllua_ts.callobj(rawget(t,'_tsObjectId'), name, unpack(argsS)), + rawget(t,'_tsNamespace')..'::'..name) + end + else + return valFromTs(_bllua_ts.getfield(rawget(t,'_tsObjectId'), name), + rawget(t,'_tsNamespace')..'.'..name) + end + end + end, + -- __newindex: Called when setting fields on the object + -- Set lua data + -- Use :set() to set Torque data + __newindex = function(t, name, val) + if rawget(t,'_deleted') then + error('ts object newindex: object no longer exists', 2) end + if type(name)~='string' then + error('ts object newindex: index must be a string', 2) end + rawset(t, name, val) + -- create strong reference since it's now storing lua data + bl._objectsStrong[rawget(t,'_tsObjectId')] = t + end, + -- object:set(fieldName, value) + -- Use to set torque data + set = function(t, name, val) + 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 + if t._deleted then + error('ts object method: object no longer exists', 2) end + if type(name)~='string' then + error('ts object :set(): index must be a string', 2) end + _bllua_ts.setfield(t._tsObjectId, name, valToTs(val)) + end, + -- __tostring: Called when printing + -- Display a nice info string + __tostring = function(t) + return 'torque:'..t._tsNamespace..':'..t._tsObjectId.. + (t._tsName~='' and ('('..t._tsName..')') or '') + end, + -- #object + -- If the object has a getCount method, return its count + __len = function(t) + if t._deleted then + error('ts object __len: object no longer exists', 2) end + if not tsIsFunctionNs(t._tsNamespace, 'getCount') then + error('ts object __len: object has no getCount method', 2) end + return tonumber(_bllua_ts.callobj(t._tsObjectId, 'getCount')) + end, + -- object:iterate() + -- Return an iterator for Torque objects with the getCount and getObject methods + -- for index, object in group:iterate() do ... end + iterate = function(t) + if t==nil then + error('ts object method: be sure to use :func() not .func()', 2) end + if t._deleted then + error('ts object method: object no longer exists', 2) end + if not ( + tsIsFunctionNs(t._tsNamespace, 'getCount' ) and + tsIsFunctionNs(t._tsNamespace, 'getObject')) then + error('ts object :iterate() - '.. + 'Object does not have getCount and getObject methods', 2) end + local count = tonumber(_bllua_ts.callobj(t._tsObjectId, 'getCount')) + local idx = 0 + return function() + if idx < count then + local obj = toTsObject(_bllua_ts.callobj(t._tsObjectId, + 'getObject', tostring(idx))) + idx = idx+1 + return idx-1, obj + else + return nil + end + end + end, + -- Wrap some Torque functions for performance and error checking + getName = function(t) + if t==nil then + error('ts object method: be sure to use :func() not .func()', 2) end + if t._deleted then + error('ts object method: object no longer exists', 2) end + return t._tsName + end, + getId = function(t) + if t==nil then + error('ts object method: be sure to use :func() not .func()', 2) end + if t._deleted then + error('ts object method: object no longer exists', 2) end + return tonumber(t._tsObjectId) + end, + getType = function(t) + if t==nil then + error('ts object method: be sure to use :func() not .func()', 2) end + if t._deleted then + error('ts object method: object no longer exists', 2) end + return tsTypesByNum[_bllua_ts.callobj(t._tsObjectId, 'getType')] + end, + ---- Schedule method for objects + --schedule = function(t, time, cb, ...) + -- if type(t)~='table' or not t._tsObjectId then + -- error('ts object method: be sure to use :func() not .func()', 2) end + -- if t._deleted then + -- error('ts object method: object no longer exists', 2) end + -- if type(time)~='number' then + -- error('ts object schedule: argument #2: time must be a number', 2) end + -- if type(cb)~='function' then + -- error('ts object schedule: argument #3: callback must be a function', 2) end + -- local args = {...} + -- bl.schedule(time, function() + -- if tsBool(__bllua_ts.call('isObject', t._tsObjectId)) then + -- pcall(cb, unpack(args)) + -- end + -- end) + --end, + exists = function(t) + if t==nil then + error('ts object method: be sure to use :func() not .func()', 2) end + if t._deleted then + return false end + return tsIsObject(t._tsObjectId) + end, +} +-- Weak-values table for caching Torque object references +-- Objects in this table can be garbage collected if there are no other refs to them +if not bl._objectsWeak then + bl._objectsWeak = {} + setmetatable(bl._objectsWeak, { __mode='v' }) +end +-- Strong table for preserving Torque object references containing lua data +-- If an object in this table, it will remain here and in the Weak table until deleted +if not bl._objectsStrong then + bl._objectsStrong = {} +end +-- Hook object deletion to clean up its lua data +-- idS is expected to be the object ID number, NOT the object name +function _bllua_objectDeleted(idS) + local obj = bl._objectsWeak[idS] + if obj then + obj._deleted = true + bl._objectsStrong[idS] = nil + bl._objectsWeak[idS] = nil + bl._objectsWeak[obj._tsName:lower()] = nil + end +end + +-- Return a Torque object for the object ID string, or create one if none exists +toTsObject = function(idiS) + if type(idiS)~='string' then + error('toTsObject: input must be a string', 2) end + idiS = idiS:lower() + if bl._objectsWeak[idiS] then return bl._objectsWeak[idiS] end + + if not tsBool(_bllua_ts.call('isObject', idiS)) then + --error('toTsObject: object \''..idiS..'\' does not exist', 2) end + return nil end + + local className = _bllua_ts.callobj(idiS, 'getClassName') + local obj = { + _tsObjectId = _bllua_ts.callobj(idiS, 'getId' ), + _tsName = _bllua_ts.callobj(idiS, 'getName' ), + _tsNamespace = className, + _tsClassName = className:lower() + } + setmetatable(obj, tsObjectMeta) + + bl._objectsWeak[obj._tsObjectId ] = obj + bl._objectsWeak[obj._tsName:lower()] = obj + return obj +end + +-- Metatable for the global bl library +-- Allows accessing Torque objects, variables, and functions by indexing it +local tsMeta = { + -- __index: Called when accessing fields that don't exist in the table itself + -- Allow indexing by object id: bl[1234] + -- by object name: bl.mainMenuGui + -- by function name: bl.quit() + -- by variable name: bl.iAmAdmin + __index = function(t, name) + if getmetatable(t)[name] then + return getmetatable(t)[name] + elseif bl._objectUserMetas[name:lower()] then + return bl._objectUserMetas[name:lower()] + else + if type(name)=='number' then + return toTsObject(tostring(name)) + elseif name:find('::') then + local ns, rest = name:match('^([^:]+)::(.+)$') + if not ns then error('ts index: invalid name \''..name..'\'', 2) end + if not rest:find('::') and tsIsFunction(ns, rest) then + error('ts index: can\'t call a namespaced function from lua', 2) + else + return valFromTs(_bllua_ts.getvar(name), name) + end + elseif tsIsFunction(name) then + return function(...) + local args = {...} + local argsS = arglistToTs(args) + return valFromTs(_bllua_ts.call(name, unpack(argsS)), name) + end + elseif tsIsObject(name) then + return toTsObject(name) + else + return valFromTs(_bllua_ts.getvar(name), name) + end + end + end, +} + +-- bl.set(name, value) +-- Used to set global variables +function bl.set(t, name, val) + _bllua_ts.call('_bllua_set_var', name, valToTs(val)) +end + +-- Utility functions +function bl.call(func, ...) + local args = {...} + local argsS = arglistToTs(args) + return _bllua_ts.call(func, unpack(argsS)) +end +function bl.eval(code) + return valFromTs(_bllua_ts.call('eval', code)) +end +function bl.exec(file) + return valFromTs(_bllua_ts.call('exec', file)) +end +function bl.tobool(val) + return val~=nil and + val~=false and + --val~='' and + --val~='0' and + val~=0 +end +function bl.toobject(id) + if type(id)=='table' and id._tsObjectId then + return id + elseif type(id)=='string' or type(id)=='number' then + return toTsObject(tostring(id)) + else + error('bl.toobject: id must be a ts object, number, or string', 2) + end +end +function bl.array(name, ...) + local rest = {...} + return name..table.concat(rest, '_') +end +function _bllua_call(name, ...) + -- todo: call ts->lua using this instead of directly +end + +-- bl.schedule: Use TS's schedule function to schedule lua calls +-- bl.schedule(time, function, args...) +bl._scheduleTable = bl._scheduleTable or {} +bl._scheduleNextId = bl._scheduleNextId or 1 +local function cancelTsSched(sched) + if not (sched and sched.handle) then + error('schedule:cancel() - invalid object', 2) + end + _bllua_ts.call('cancel', sched.handle) + bl._scheduleTable[id] = nil +end +function bl.schedule(time, cb, ...) + local id = bl._scheduleNextId + bl._scheduleNextId = bl._scheduleNextId+1 + local args = {...} + local handle = tonumber(_bllua_ts.call('schedule', + time, 0, 'luacall', '_bllua_schedule_callback', id)) + local sch = { + callback = cb, + args = args, + handle = handle, + cancel = cancelTsSched, + } + bl._scheduleTable[id] = sch + return sch +end +function _bllua_schedule_callback(id) + id = tonumber(id) + local sch = bl._scheduleTable[id] + if not sch then error('_ts_schedule_callback: no schedule with id '..id) end + bl._scheduleTable[sched_id] = nil + sch.callback(unpack(sch.args)) +end + +-- serverCmd and clientCmd +-- bl.serverCmd('suicide', function(client) client.player:kill() end) +bl._cmds = bl._cmds or {} +function _bllua_process_cmd(cmdS, clientS, ...) + local client = toTsObject(clientS) + local argsS = {...} + local args = arglistFromTs(cmdS, argsS) + local func = bl._cmds[cmdS] + if not func then error('_bllua_process_cmd: no cmd named \''..cmd..'\'') end + pcall(func, client, unpack(args)) +end +local function addCmd(cmd, func) + if not isValidFuncName(cmd) then + error('addCmd: invalid function name \''..tostring(cmd)..'\'') end + bl._servercmds[cmd] = func + local arglist = '%a,%b,%c,%d,%e,%f,%g,%h' + _bllua_ts.eval('function '..cmd..'(%cl,'..arglist..'){'.. + 'luacall(_bllua_process_cmd,"'..cmd..'",%cl,'..arglist..');}') +end +function bl.serverCmd(name, func) addCmd('serverCmd'..name, func) end +function bl.clientCmd(name, func) addCmd('clientCmd'..name, func) end + +-- Hooks (using TS packages) +local function isPackageActive(pkg) + local numpkgs = tonumber(_bllua_ts.call('getNumActivePackages')) + for i = 0, numpkgs-1 do + local apkg = _bllua_ts.call('getActivePackage', tostring(i)) + if apkg==pkg then return true end + end + return false +end +local function activatePackage(pkg) + if not isPackageActive(pkg) then + _bllua_ts.call('activatePackage', pkg) + end +end +local function deactivatePackage(pkg) + if isPackageActive(pkg) then + _bllua_ts.call('deactivatePackage', pkg) + end +end +bl._hooks = bl._hooks or {} +function _bllua_process_hook(pkgS, nameS, timeS, ...) + local argsS = {...} + local args = arglistFromTs(nameS, argsS) + + local func = bl._hooks[pkgS] and bl._hooks[pkgS][nameS] and + bl._hooks[pkgS][nameS][timeS] + if not func then + error('_bllua_process_hook: no hook for '..pkgS..':'..nameS..':'..timeS) end + + pcall(func, args) +end +local function updateHook(pkg, name, hk) + local arglist = '%a,%b,%c,%d,%e,%f,%g,%h' + local beforeCode = hk.before and + ('luacall("_bllua_process_hook", "'..pkg..'", "'..name.. + '", "before", '..arglist..');') or '' + local parentCode = hk.override and + ('luacall("_bllua_process_hook", "'..pkg..'", "'..name.. + '", "override", '..arglist..');') or + (tsIsFunctionNsname(name) and + ('parent::'..name:match('[^:]+$')..'('..arglist..');') or '') + local afterCode = hk.after and + ('luacall("_bllua_process_hook", "'..pkg..'", "'..name.. + '", "after", '..arglist..');') or '' + bl.eval('package '..pkg..'{function '..name..'('..arglist..'){'.. + beforeCode..parentCode..afterCode..'}};') +end +function bl.hook(pkg, name, time, func) + if not isValidFuncName(pkg) then + error('bl.hook: argument #1: invalid package name \''..tostring(pkg)..'\'', 2) end + if not isValidFuncNameNs(name) then + error('bl.hook: argument #2: invalid function name \''..tostring(name)..'\'', 2) end + if time~='before' and time~='after' and time~='override' then + error('bl.hook: argument #3: time must be one of '.. + '\'before\' \'after\' \'override\'', 2) end + if type(func)~='function' then + error('bl.hook: argument #4: expected a function', 2) end + + bl._hooks[pkg] = bl._hooks[pkg] or {} + bl._hooks[pkg][name] = bl._hooks[pkg][name] or {} + bl._hooks[pkg][name][time] = func + + updateHook(pkg, name, bl._hooks[pkg][name]) + activatePackage(pkg) +end +function bl.unhook(pkg, name, time) + if not isValidFuncName(pkg) then + error('bl.unhook: argument #1: invalid package name \''..tostring(pkg)..'\'', 2) end + if not isValidFuncNameNs(name) then + error('bl.unhook: argument #2: invalid function name \''..tostring(name)..'\'', 2) end + if time~='before' and time~='after' and time~='override' then + error('bl.unhook: argument #3: time must be one of '.. + '\'before\' \'after\' \'override\'', 2) end + + if not name then + if bl._hooks[pkg] then + for name,hk in pairs(bl._hooks[pkg]) do + updateHook(pkg, name, {}) + end + bl._hooks[pkg] = nil + else + --error('bl.unhook: no hooks registered under package name \''.. + -- pkg..'\'', 2) + end + deactivatePackage(pkg) + else + if bl._hooks[pkg][name] then + if not time then + bl._hooks[pkg][name] = nil + if table.isempty(bl._hooks[pkg]) then + bl._hooks[pkg] = nil + deactivatePackage(pkg) + end + updateHook(pkg, name, {}) + else + if time~='before' and time~='after' and time~='override' then + error('bl.unhook: argument #3: time must be nil or one of '.. + '\'before\' \'after\' \'override\'', 2) end + bl._hooks[pkg][name][time] = nil + if table.isempty(bl._hooks[pkg][name]) and table.empty(bl._hooks[pkg]) then + bl._hooks[pkg] = nil + deactivatePackage(pkg) + end + updateHook(pkg, name, bl._hooks[pkg][name]) + end + else + --error('bl.unhook: no hooks registered for function \''..name.. + -- '\' under package name \''..pkg..'\'', 2) + end + end +end + +-- Container search/raycast +local function vecToTs(v) + if not isTsVector(v) then + error('vecToTs: argument is not a vector', 3) end + return table.concat(v, ' ') +end +local function maskToTs(mask) + if type(mask)=='string' then + local val = tsTypesByName[mask:lower()] + if not val then + error('maskToTs: invalid mask \''..mask..'\'', 3) end + return tostring(val) + elseif type(mask)=='table' then + local tval = 0 + local seen = {} + for i,v in ipairs(mask) do + if not seen[v] then + local val = tsTypesByName[v:lower()] + if not val then + error('maskToTs: invalid mask \''..v.. + '\' at index '..i..' in mask list', 3) end + tval = tval + val + seen[v] = true + end + end + return tostring(tval) + else + error('maskToTs: mask must be a string or table', 3) + end +end +local function objToTs(obj) + if type(obj)=='number' or type(obj)=='string' then + return tostring(obj) + elseif type(obj)=='table' and obj._tsObjectId then + return tostring(obj._tsObjectId) + else + error('objToTs: invalid object \''..tostring(obj)..'\'', 3) + end +end +function bl.raycast(start, stop, mask, ignores) + local startS = vecToTs(start) + local stopS = vecToTs(start) + local maskS = maskToTs(mask) + local ignoresS = {} + for _,v in ipairs(ignores) do + table.insert(ignoresS, objToTs(v)) + end + + local retS = _bllua_ts.call('containerRaycast', startS, stopS, maskS, unpack(ignoresS)) + + if retS=='0' then + return nil + else + local hitS, pxS,pyS,pzS, nxS,nyS,nzS = retS:match('^([0-9]+) '.. + '(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+) '.. + '(%-?[0-9%.e]+) (%-?[0-9%.e]+) (%-?[0-9%.e]+)$') + local hit = toTsObject(hitS) + local pos = vector{tonumber(pxS),tonumber(pyS),tonumber(pzS)} + local norm = vector{tonumber(nxS),tonumber(nyS),tonumber(nzS)} + return hit, pos, norm + end +end +local function tsContainerSearchIterator() + local retS = _bllua_ts.call('containerSearchNext') + if retS=='0' then + return nil + else + return toTsObject(retS) + end +end +function bl.boxSearch(pos, size, mask) + local posS = vecToTs(pos) + local sizeS = vecToTs(size) + local maskS = maskToTs(mask) + + _bllua_ts.call('initContainerBoxSearch', posS, sizeS, maskS) + return tsContainerSearchIterator +end +function bl.radiusSearch(pos, radius, mask) + local posS = vecToTs(pos) + if type(radius)~='number' then + error('bl.radiusSearch: argument #2: radius must be a number', 2) end + local radiusS = tostring(radius) + local maskS = maskToTs(mask) + + _bllua_ts.call('initContainerRadiusSearch', posS, radiusS, maskS) + return tsContainerSearchIterator +end + +-- Print/Talk/Echo +local function valsToString(vals) + local strs = {} + for i,v in ipairs(vals) do + strs[i] = table.tostring(v) + end + return table.concat(strs, ' ') +end +bl.echo = function(...) + local str = valsToString({...}) + _bllua_ts.call('echo', str) +end +print = bl.echo +bl.talk = function(...) + local str = valsToString({...}) + _bllua_ts.call('echo', str) + _bllua_ts.call('talk', str) +end + +local function createTsObj(keyword, class, name, inherit, props) + local propsT = {} + for k,v in pairs(props) do + if not isValidFuncName(k) then + error('bl.new/datablock: invalid property name \''..k..'\'') end + table.insert(propsT, k..'="'..valToTs(v)..'";') + end + + local objS = _bllua_ts.eval( + 'return '..keyword..' '..class..'('.. + (name or '')..(inherit and (':'..inherit) or '')..'){'.. + table.concat(propsT)..'};') + local obj = toTsObject(objS) + if not obj then + error('bl.new/datablock: failed to create object', 3) end + + return obj +end +local function parseTsDecl(decl) + local class, name, inherit + if decl:find(' ') then -- class ... + local cl, rest = decl:match('^([^ ]+) ([^ ]+)$') + class = cl + if rest:find(':') then -- class name:inherit + name, inherit = rest:match('^([^:]*):([^:]+)$') + if not name then class = nil end -- error + if name=='' then name = nil end -- class :inherit + else + name = rest + end + else -- class + class = decl + end + if not ( + isValidFuncName(class) and + (name==nil or isValidFuncName(name)) and + (inherit==nil or isValidFuncName(inherit)) ) then + error('bl.new/datablock: invalid decl \''..decl..'\'\n'.. + 'must be of the format: \'className\', \'className name\', '.. + '\'className :inherit\', or \'className name:inherit\'', 3) end + return class, name, inherit +end +function bl.new(decl, props) + local class, name, inherit = parseTsDecl(decl) + return createTsObj('new', class, name, inherit, props) +end +function bl.datablock(decl, props) + local class, name, inherit = parseTsDecl(decl) + return createTsObj('datablock', class, name, inherit, props) +end + +setmetatable(bl, tsMeta) + +print(' Executed libbl.lua') diff --git a/src/util/libts-support.cs b/src/util/libts-support.cs new file mode 100644 index 0000000..c928408 --- /dev/null +++ b/src/util/libts-support.cs @@ -0,0 +1,52 @@ + +// Read an entire file as text and return its contents as a string +// Used for reading files from zips +function _bllua_ReadEntireFile(%fn) { + %text = ""; + %file = new FileObject(); + %file.openForRead(%fn); + while (!%file.isEOF()) { %text = %text @ %file.readLine() @ "\r\n"; } + %file.close(); + %file.delete(); + return %text; +} + +// Hack to create/set global variables +// since there's no easy way to do this from the DLL directly +function _bllua_set_var(%name, %val) { + %first = strLwr(getSubStr(%name, 0, 1)); + %rest = getSubStr(%name, 1, strLen(%name)); + switch$(%first) { + case "a": $a[%rest] = %val; return; + case "b": $b[%rest] = %val; return; + case "c": $c[%rest] = %val; return; + case "d": $d[%rest] = %val; return; + case "e": $e[%rest] = %val; return; + case "f": $f[%rest] = %val; return; + case "g": $g[%rest] = %val; return; + case "h": $h[%rest] = %val; return; + case "i": $i[%rest] = %val; return; + case "j": $j[%rest] = %val; return; + case "k": $k[%rest] = %val; return; + case "l": $l[%rest] = %val; return; + case "m": $m[%rest] = %val; return; + case "n": $n[%rest] = %val; return; + case "o": $o[%rest] = %val; return; + case "p": $p[%rest] = %val; return; + case "q": $q[%rest] = %val; return; + case "r": $r[%rest] = %val; return; + case "s": $s[%rest] = %val; return; + case "t": $t[%rest] = %val; return; + case "u": $u[%rest] = %val; return; + case "v": $v[%rest] = %val; return; + case "w": $w[%rest] = %val; return; + case "x": $x[%rest] = %val; return; + case "y": $y[%rest] = %val; return; + case "z": $z[%rest] = %val; return; + case "_": $_[%rest] = %val; return; + } + error("_bllua_set_var: invalid variable name " @ %name); + return ""; +} + +echo(" Executed libts-support.cs"); diff --git a/src/util/libts.lua b/src/util/libts.lua new file mode 100644 index 0000000..5b2daa9 --- /dev/null +++ b/src/util/libts.lua @@ -0,0 +1,212 @@ + +-- 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 only has access to the sandboxed lua environment, just like user code. + +ts = _bllua_ts + +-- Provide limited OS functions +os = os or {} +function os.time() return math.floor(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 +-- Used to wrap io.open to allow reading from zips (using TS) +-- Not perfect because TS file I/O sucks +-- Can't read nulls, can't distinguish between CRLF and LF. +-- Todo someday: actually read the zip in lua? +local file_meta = { + read = function(file, mode) + file:_init() + if not file or type(file)~='table' or not file._is_file then error('File:read: Not a file', 2) end + if file._is_open ~= true then error('File:read: File is closed', 2) end + if mode=='*n' then + local ws, n = file.data:match('^([ \t\r\n]*)([0-9%.%-e]+)', file.pos) + if n then + file.pos = file.pos + #ws + #n + return n + else + return nil + end + elseif mode=='*a' then + local d = file.data:sub(file.pos, #file.data) + file.pos = #file.data + 1 + return d + elseif mode=='*l' then + local l, ws = file.data:match('^([^\r\n]*)(\r?\n)', file.pos) + if not l then + l = file.data:match('^([^\r\n]*)$', file.pos); ws = ''; + if l=='' then return nil end + end + if l then + file.pos = file.pos + #l + #ws + return l + else + return nil + end + elseif type(mode)=='number' then + local d = file.data:sub(file.pos, file.pos+mode) + file.pos = file.pos + #d + return d + else + error('File:read: Invalid mode \''..mode..'\'', 2) + end + end, + lines = function(file) + file:_init() + return function() + return file:read('*l') + end + end, + close = function(file) + if not file._is_open then error('File:close: File is not open', 2) end + file._is_open = false + end, + __index = function(f, k) return rawget(f, k) or getmetatable(f)[k] end, + _init = function(f) + if not f.data then + f.data = _bllua_ts.call('_bllua_ReadEntireFile', f.filename) + end + end, +} +local function new_file_obj(fn) + local file = { + _is_file = true, + _is_open = true, + pos = 1, + __index = file_meta.__index, + filename = fn, + data = nil, + } + setmetatable(file, file_meta) + return file +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{ + 'add-ons', 'base', 'config', 'saves', 'screenshots', 'shaders' +} +local function io_open_absolute(fn, mode) + -- if file exists, use original mode + local res, err = _bllua_io_open(fn, mode) + if res then return res end + + -- otherwise, if TS sees file but Lua doesn't, it must be in a zip, so use TS reader + local dir = fn:match('^[^/]+') + if not allowed_zip_dirs[dir:lower()] then return nil, 'File is not in one of the allowed directories' end + local exist = _bllua_ts.call('isFile', fn) == '1' + if not exist then return nil, err end + + if mode~=nil and mode~='r' and mode~='rb' then + return nil, 'Files in zips can only be opened in read mode' end + + -- return a temp lua file object with the data + local fi = new_file_obj(fn) + return fi +end + +io = io or {} +function io.open(fn, mode, errn) + errn = errn or 1 + + -- try to open the file with relative path, otherwise use absolute path + local curfn = debug.getfilename(errn + 1) or _bllua_ts.getvar('Con::File') + if curfn == '' then curfn = nil end + if fn:find('^%.') then + local relfn = curfn and fn:find('^%./') and + curfn:gsub('[^/]+$', '')..fn:gsub('^%./', '') + if relfn then + local fi, err = io_open_absolute(relfn, mode, errn+1) + return fi, err, relfn + else + return nil, 'Invalid path', fn + end + else + local fi, err = io_open_absolute(fn, mode, errn+1) + return fi, err, fn + end +end +function io.lines(fn) + local fi, err, fn2 = io.open(fn, nil, 2) + if not fi then error('Error opening file \''..fn2..'\': '..err, 2) end + return fi:lines() +end +function io.type(f) + if type(f)=='table' and f._is_file then + return f._is_open and 'file' or 'closed file' + else + return _bllua_io_type(f) + end +end + +-- provide dofile +function dofile(fn, errn) + errn = errn or 1 + + local fi, err, fn2 = io.open(fn, 'r', errn+1) + if not fi then error('Error executing file \''..fn2..'\': '..err, errn+1) end + + print('Executing '..fn2) + local text = fi:read('*a') + fi:close() + return assert(loadstring('--[['..fn2..']]'..text))() +end + +-- provide require (just a wrapper for dofile) +-- searches for ?.lua and ?/init.lua in the following directories: +-- location of current file +-- blockland directory +-- current add-on +local function file_exists(fn, errn) + local fi, err, fn2 = io.open(fn, 'r', errn+1) + if fi then + fi:close() + return fn2 + else + return nil + end +end +function require(mod) + local fp = mod:gsub('%.', '/') + local fns = { + './'..fp..'.lua', -- local file + './'..fp..'/init.lua', -- local library + fp..'.lua', -- global file + fp..'/init.lua', -- global library + } + if fp:lower():find('^add-ons/') then + local addonpath = fp:lower():match('^add-ons/[^/]+')..'/' + table.insert(fns, addonpath..fp..'.lua') -- add-on file + table.insert(fns, addonpath..fp..'/init.lua') -- add-on library + end + for _,fn in ipairs(fns) do + local fne = file_exists(fn, 2) + if fne then + return dofile(fne, 2) + end + end + return _bllua_requiresecure(mod) +end + +-- Exposure to TS +function _bllua_getvar(name) return _G[name] end +function _bllua_setvar(name, val) _G[name] = val end +function _bllua_eval(code) return loadstring(code)() end +function _bllua_exec(fn) return dofile(fn, 2) end + +local function isValidCode(code) + local f,e = loadstring(code) + return f~=nil +end +function _bllua_smarteval(code) + if (not code:find('^print%(')) and isValidCode('print('..code..')') then + code = 'print('..code..')' end + local f,e = loadstring(code) + if f then + return f() + else + print(e) + end +end + +_bllua_ts.call('echo', ' Executed libts.lua') diff --git a/src/util/loadaddons.cs b/src/util/loadaddons.cs new file mode 100644 index 0000000..956c3df --- /dev/null +++ b/src/util/loadaddons.cs @@ -0,0 +1,412 @@ +// Package to allow add-ons to use server.lua or client.lua +// instead of or in addition to server.cs or client.cs +// Relevant .lua files are is executed before .cs files. + +function _bllua_strEndsWith(%str, %sch) { + %schL = strLen(%sch); + return getSubStr(%str, strLen(%str)-%schL, %schL) $= %sch; +} +//function _bllua_strRemoveEnd(%str, %sch) { +// %schL = strLen(%sch); +// return getSubStr(%str, 0, strLen(%str)-%schL); +//} +function _bllua_fileIsExecCs(%fn) { + return + _bllua_strEndsWith(%fn, "/server.cs" ) || + _bllua_strEndsWith(%fn, "/server.lua") || + _bllua_strEndsWith(%fn, "/client.cs" ) || + _bllua_strEndsWith(%fn, "/client.lua"); +} +function _bllua_execAddon(%dirName, %type) { + %i = 0; + %fnLua = "Add-Ons/" @ %dirName @ "/" @ %type @ ".lua"; + if(isFile(%fnLua)) { luaexec(%fnLua); %i++; } + %fnCs = "Add-Ons/" @ %dirName @ "/" @ %type @ ".cs"; + if(isFile(%fnCs )) { exec(%fnCs ); %i++; } + if(%i==0) { + error("Error Loading Add-On " @ %dirName @ ": Neither " @ + %type @ ".cs nor " @ %type @ ".lua exist"); + } +} + +// Rewrite built-in functions that scan for server.cs or client.cs +// and make them scan for server.lua or client.lua as well +// Note: I had to completely override several large functions, +// many of which are highly redundant, because Badspot didn't know +// what functional decomposition was when he wrote this shit. +package _bllua_addon_exec { + function CustomGameGuiServer::populateAddOnList() { + deleteVariables("$CustomGameGuiServer::AddOn*"); + $CustomGameGuiServer::AddOnCount = 0; + %pattern = "Add-Ons/*/server.*"; + %filename = findFirstFile(%pattern); + while(isFile(%filename)) { + if(_bllua_fileIsExecCs(%filename)) { + %path = filePath(%filename); + %dirName = getSubStr(%path, strlen("Add-Ons/"), strlen(%path) - strlen("Add-Ons/")); + if(!%seenDirName[%dirName]) { + %seenDirName[%dirName] = 1; + %varName = getSafeVariableName(%dirName); + if(isValidAddOn(%dirName, 1)) { + $CustomGameGuiServer::AddOn[$CustomGameGuiServer::AddOnCount] = %dirName; + $CustomGameGuiServer::AddOnCount++; + } + } + } + %filename = findNextFile(%pattern); + } + } + function GameModeGuiServer::GetMissingAddOns(%filename) { + if(!isFile(%filename)) { + error("ERROR: GameModeGuiServer::GetMissingAddOns(" @ %filename @ ") - file does not exist"); + return 0; + } + %path = filePath(%filename); + %missingAddons = ""; + %descriptionFile = %path @ "/description.txt"; + %previewFile = %path @ "/preview.jpg"; + %thumbFile = %path @ "/thumb.jpg"; + %saveFile = %path @ "/save.bls"; + %colorSetFile = %path @ "/colorSet.txt"; + if(!isFile(%descriptionFile)) + %missingAddons = %missingAddons TAB %descriptionFile; + if(!isFile(%previewFile)) + %missingAddons = %missingAddons TAB %previewFile; + if(!isFile(%thumbFile)) + %missingAddons = %missingAddons TAB %thumbFile; + if(!isFile(%saveFile)) + %missingAddons = %missingAddons TAB %saveFile; + if(!isFile(%colorSetFile)) + %missingAddons = %missingAddons TAB %colorSetFile; + %file = new FileObject(""){}; + %file.openForRead(%filename); + while(!%file.isEOF()) { + %line = %file.readLine(); + %label = getWord(%line, 0); + %value = trim(getWords(%line, 1, 999)); + if(%label !$= "") { + if(getSubStr(%label, 0, 2) !$= "//") { + if(%label $= "ADDON") { + if(!isFile("Add-Ons/" @ %value @ "/description.txt") || + (!isFile("Add-Ons/" @ %value @ "/server.cs" ) && + !isFile("Add-Ons/" @ %value @ "/server.lua") ) ) { + if(strlen(%missingAddons) > 0) + %missingAddons = %missingAddons TAB %value; + else + %missingAddons = %value; + } + } else { + if(%label $= "MUSIC") { + if(!isFile("Add-Ons/Music/" @ %value @ ".ogg")) { + if(strlen(%missingAddons) > 0) + %missingAddons = %missingAddons TAB %value @ ".ogg"; + else + %missingAddons = %value; + } + } + } + } + } + } + %file.close(); + %file.delete(); + return %missingAddons; + } + function loadAddOns() { + echo(""); + updateAddOnList(); + echo("--------- Loading Add-Ons (+BlockLua) ---------"); + deleteVariables("$AddOnLoaded__*"); + %dir = "Add-Ons/*/server.*"; + %filename = findFirstFile(%dir); + %dirCount = 0; + if(isFile("Add-Ons/System_ReturnToBlockland/server.cs")) { + %dirNameList[%dirCount] = "System_ReturnToBlockland"; + %dirCount++; + } + while(%filename !$= "") { + if(_bllua_fileIsExecCs(%filename)) { + %path = filePath(%filename); + %dirName = getSubStr(%path, strlen("Add-Ons/"), strlen(%path) - strlen("Add-Ons/")); + if(!%seenDirName[%dirName]) { + %seenDirName[%dirName] = 1; + if(%dirName !$= "System_ReturnToBlockland") { + %dirNameList[%dirCount] = %dirName; + %dirCount++; + } + } + } + %filename = findNextFile(%dir); + } + for(%addOnItr = 0; %addOnItr < %dirCount; %addOnItr++) { + %dirName = %dirNameList[%addOnItr]; + %varName = getSafeVariableName(%dirName); + if(!$Server::Dedicated) { + if(getRealTime() - $lastProgressBarTime > 200) { + LoadingProgress.setValue(%addOnItr / %dirCount); + $lastProgressBarTime = getRealTime(); + Canvas.repaint(); + } + } + if($AddOn__[%varName] $= 1 && isValidAddOn(%dirName)) { + if(%dirName $= "JVS_Content" && $AddOn__["Support_LegacyDoors"] $= 1) { + echo(" Skipping JVS_Content in favor of Support_LegacyDoors"); + } else if(!$AddOnLoaded__[%varName]) { + $AddOnLoaded__[%varName] = 1; + %zipFile = "Add-Ons/" @ %dirName @ ".zip"; + if(isFile(%zipFile)) { + %zipCRC = getFileCRC(%zipFile); + echo("\c5Loading Add-On: " @ %dirName @ " \c2(CRC:" @ %zipCRC @ ")"); + } else { + echo("\c5Loading Add-On: " @ %dirName); + } + if(VerifyAddOnScripts(%dirName)==0) { + echo("\c3ADD-ON " @ %dirName @ " CONTAINS SYNTAX ERRORS\n"); + } else { + %oldDBCount = DataBlockGroup.getCount(); + _bllua_execAddon(%dirName, "server"); + %dbDiff = DataBlockGroup.getCount() - %oldDBCount; + echo("\c2" @ %dbDiff @ " datablocks added."); + echo(""); + } + } + } + } + echo(""); + } + function loadGameModeAddOns() { + echo(""); + echo("--------- Loading Add-Ons (Game Mode) (+BlockLua) ---------"); + deleteVariables("$AddOnLoaded__*"); + for(%i=0; %i<$GameMode::AddOnCount; %i++) { + %dirName = $GameMode::AddOn[%i]; + %varName = getSafeVariableName(%dirName); + if(!$Server::Dedicated) { + if(getRealTime() - $lastProgressBarTime > 200) { + LoadingProgress.setValue(%i / $GameMode::AddOnCount); + $lastProgressBarTime = getRealTime(); + Canvas.repaint(); + } + } + if(!isValidAddOn(%dirName)) { + error("ERROR: Invalid add-on \'" @ %dirName @ "\' specified for game mode \'" @ $GameModeArg @ "\'"); + } else { + $AddOnLoaded__[%varName] = 1; + %zipFile = "Add-Ons/" @ %dirName @ ".zip"; + if(isFile(%zipFile)) { + %zipCRC = getFileCRC(%zipFile); + echo("\c5Loading Add-On: " @ %dirName @ " \c2(CRC:" @ %zipCRC @ ")"); + } else { + echo("\c5Loading Add-On: " @ %dirName); + } + if(VerifyAddOnScripts(%dirName) == 0) { + echo("\c3ADD-ON " @ %dirName @ " CONTAINS SYNTAX ERRORS\n"); + } else { + %oldDBCount = DataBlockGroup.getCount(); + _bllua_execAddon(%dirName, "server"); + %dbDiff = DataBlockGroup.getCount() - %oldDBCount; + echo("\c2" @ %dbDiff @ " datablocks added."); + echo(""); + } + } + } + echo(""); + } + function loadClientAddOns() { + echo(""); + echo("--------- Loading Client Add-Ons (+BlockLua) ---------"); + if(isFile("base/server/crapOns_Cache.cs")) + exec("base/server/crapOns_Cache.cs"); + %dir = "Add-Ons/*/client.*"; + %filename = findFirstFile(%dir); + %dirCount = 0; + if(isFile("Add-Ons/System_ReturnToBlockland/client.cs")) { + %dirNameList[%dirCount] = "System_ReturnToBlockland"; + %dirCount++; + } + while(%filename !$= "") { + if(_bllua_fileIsExecCs(%filename)) { + %path = filePath(%filename); + %dirName = getSubStr(%path, strlen("Add-Ons/"), strlen(%path) - strlen("Add-Ons/")); + if(!%seenDirName[%dirName]) { + %seenDirName[%dirName] = 1; + if(%dirName !$= "System_ReturnToBlockland") { + %dirNameList[%dirCount] = %dirName; + %dirCount++; + } + } + } + %filename = findNextFile(%dir); + } + for(%i=0; %i<%dirCount; %i++) { + %dirName = %dirNameList[%i]; + %varName = getSafeVariableName(%dirName); + echo(""); + echo("Client checking Add-On: " @ %dirName); + if(!clientIsValidAddOn(%dirName, 1)) { + //deleteVariables("$AddOn__" @ %varName); // wtf + } else { + %name = %dirName; + %zipFile = "Add-Ons/" @ %dirName @ ".zip"; + if(isFile(%zipFile)) { + %zipCRC = getFileCRC(%zipFile); + echo("\c5Loading Add-On: " @ %dirName @ " \c2(CRC:" @ %zipCRC @ ")"); + } else { + echo("\c5Loading Add-On: " @ %dirName); + } + if(ClientVerifyAddOnScripts(%dirName)==0) + echo("\c3ADD-ON " @ %dirName @ " CONTAINS SYNTAX ERRORS\n"); + else + _bllua_execAddon(%dirName, "client"); + } + } + echo(""); + } + function updateAddOnList() { + echo("\n--------- Updating Add-On List (+BlockLua) ---------"); + deleteVariables("$AddOn__*"); + if(isFile("config/server/ADD_ON_LIST.cs")) { + exec("config/server/ADD_ON_LIST.cs"); + } else { + exec("base/server/defaultAddOnList.cs"); + } + if(isFile("base/server/crapOns_Cache.cs")) { + exec("base/server/crapOns_Cache.cs"); + } + %dir = "Add-Ons/*/server.*"; + %fileCount = getFileCount(%dir); + %filename = findFirstFile(%dir); + while(%filename !$= "") { + if(_bllua_fileIsExecCs(%filename)) { + %path = filePath(%filename); + %dirName = getSubStr(%path, strlen("Add-Ons/"), strlen(%path) - strlen("Add-Ons/")); + if(!%seenDirName[%dirName]) { + %seenDirName[%dirName] = 1; + %varName = getSafeVariableName(%dirName); + echo("Checking Add-On " @ %dirName); + if(!isValidAddOn(%dirName, 1)) { + deleteVariables("$AddOn__" @ %varName); + } else { + if (mFloor($AddOn__[%varName]) <= 0) + $AddOn__[%varName] = -1; + else + $AddOn__[%varName] = 1; + } + } + } + %filename = findNextFile(%dir); + } + echo(""); + export("$AddOn__*", "config/server/ADD_ON_LIST.cs"); + } +}; +activatePackage(_bllua_addon_exec); + +// Have to make new versions of these because packaging them is blocked FSFR +function forceRequiredAddOn_L(%dirName) { + if(%dirName $= "JVS_Content") { + if($GameModeArg $= "") { + if($AddOn__["Support_LegacyDoors"] == 1 || !isFile("add-ons/JVS_Content/server.cs") || ($AddOn__["Support_LegacyDoors"] != 1 && $AddOn__["JVS_Content"] != 1)) { + %dirName = "Support_LegacyDoors"; + } + } else { + %foundJVSContent = 0; + for(%i=0; %i<$GameMode::AddOnCount; %i++) { + if ($GameMode::AddOn[%i] $= "JVS_Content") { + %foundJVSContent = 1; + } + } + if(!%foundJVSContent) + %dirName = "Support_LegacyDoors"; + } + } + if(strstr(%dirName, " ") != -1) + %dirName = strreplace(%dirName, " ", "_"); + //if(strstr(%dirName, "/") != -1) + // return $Error::AddOn_Nested; + %varName = getSafeVariableName(%dirName); + if($GameModeArg !$= "") { + %foundIt = 0; + for(%i=0; %i<$GameMode::AddOnCount; %i++) { + if ($GameMode::AddOn[%i] $= %dirName) { + %foundIt = 1; + break; + } + } + if(!%foundIt) { + error("ERROR: ForceRequiredAddOn_L(\'" @ %dirName @ "\') - you can\'t force load an add-on that is not included in gamemode.txt"); + if (GameWindowExists() && !$Server::Dedicated) { + schedule(11, 0, MessageBoxOK, "Game Mode Error", "Required add-on " @ %dirName @ " should be added to gamemode.txt"); + } + if (!isEventPending($disconnectEvent)) { + $disconnectEvent = schedule(10, 0, disconnect); + } + return $Error::AddOn_NotFound; + } + } + if($AddOnLoaded__[%varName] == 1) + return $Error::None; + if($AddOn__[%varName] $= "" && $GameModeArg $= "" || !isValidAddOn(%dirName)) { + error("ERROR: ForceRequiredAddOn() - " @ %dirName @ " is not a valid add-on"); + return $Error::AddOn_NotFound; + } + echo(" Loading Add-On " @ %dirName @ ""); + _bllua_execAddon(%dirName, "server"); + $AddOnLoaded__[%varName] = 1; + if($AddOn__[%varName] $= 1) + return $Error::None; + else + return $Error::AddOn_Disabled; +} +function loadRequiredAddOn_L(%dirName) { + if(%dirName $= "JVS_Content") { + if($GameModeArg $= "") { + if($AddOn__["Support_LegacyDoors"] == 1 || !isFile("add-ons/JVS_Content/server.cs") || ($AddOn__["Support_LegacyDoors"] != 1 && $AddOn__["JVS_Content"] != 1)) { + %dirName = "Support_LegacyDoors"; + } + } else { + %foundJVSContent = 0; + for(%i=0; %i<$GameMode::AddOnCount; %i++) { + if ($GameMode::AddOn[%i] $= "JVS_Content") { + %foundJVSContent = 1; + } + } + if(!%foundJVSContent) + %dirName = "Support_LegacyDoors"; + } + } + if(strstr(%dirName, " ") != -1) + %dirName = strreplace(%dirName, " ", "_"); + //if(strstr(%dirName, "/") != -1) + // return $Error::AddOn_Nested; + %varName = getSafeVariableName(%dirName); + if ($GameModeArg !$= "") { + %foundIt = 0; + for(%i=0; %i<$GameMode::AddOnCount; %i++) { + if ($GameMode::AddOn[%i] $= %dirName) { + %foundIt = 1; + break; + } + } + if(!%foundIt) { + error("ERROR: LoadRequiredAddOn_L(\'" @ %dirName @ "\') - you can\'t force load an add-on that is not included in gamemode.txt"); + if (GameWindowExists() && !$Server::Dedicated) + schedule(11, 0, MessageBoxOK, "Game Mode Error", "Required add-on " @ %dirName @ " should be added to gamemode.txt"); + if (!isEventPending($disconnectEvent)) + $disconnectEvent = schedule(10, 0, disconnect); + return $Error::AddOn_NotFound; + } + } + if($AddOnLoaded__[%varName] == 1) + return $Error::None; + if($AddOn__[%varName] $= 1) { + echo(" Loading Add-On " @ %dirName @ ""); + _bllua_execAddon(%dirName, "server"); + $AddOnLoaded__[%varName] = 1; + return $Error::None; + } else { + return $Error::AddOn_Disabled; + } +} + +echo(" Executed loadaddons.cs"); diff --git a/src/util/std.lua b/src/util/std.lua new file mode 100644 index 0000000..23ddaf5 --- /dev/null +++ b/src/util/std.lua @@ -0,0 +1,360 @@ + +-- Basic functionality that should be standard in Lua + + +-- Table / List +-- Whether a table contains no keys +function table.empty(t) + for _,_ in pairs(t) do return false end + return true +end +-- Apply a function to each key in a table +function table.map(f, ...) + local ts = {...} + local u = {} + for k,_ in pairs(ts[1]) do + local args = {} + for j=1,#ts do args[j] = ts[j][i] end + u[i] = f(unpack(args)) + end + return u +end +function table.map_list(f, ...) + local ts = {...} + local u = {} + for i=1,#ts[1] do + local args = {} + for j=1,#ts do args[j] = ts[j][i] end + u[i] = f(unpack(args)) + end + return u +end +-- Swap keys/values +function table.swap(t) + local u = {} + for k,v in pairs(t) do u[v] = k end + return u +end +-- Reverse a list +function table.reverse(l) + local m = {} + for i=1,#l do m[#l-i+1] = l[i] end + return m +end +-- Convert i->v to v->true +function table.values(l) + local u = {} + for _,v in ipairs(l) do u[v] = true end + return u +end +-- Make a list of keys +function table.keys(t) + local u = {} + for k,_ in pairs(t) do table.insert(u, k) end + return u +end +-- Whether a table is a list/array (has only monotonic integer keys) +function table.islist(t) + local n = 0 + for i,_ in pairs(t) do + if type(i)~='number' or i%1~=0 then return false end + n = n+1 + end + return n==#t +end +-- Append contents of other tables to first table +function table.append(t, ...) + local a = {...} + for _,u in ipairs(a) do + for _,v in ipairs(u) do table.insert(t,v) end + end + return t +end +-- Create a new table containing all keys from any number of tables +-- latter tables in the arg list override prior ones +-- overlaps, NOT appends, integer keys +function table.join(...) + local ts = {...} + local w = {} + for _,t in ipairs(ts) do + for k,v in pairs(t) do w[k] = v end + end + return w +end +-- Whether a table contains a certain value in any key +function table.contains(t,s) + for _,v in pairs(t) do + if v==s then return true end + end + return false +end +function table.contains_list(t,s) + for _,v in ipairs(t) do + if v==s then return true end + end + return false +end +-- Copy a table to another table +function table.copy(t) + local u = {} + for k,v in pairs(t) do u[k] = v end + return u +end +function table.copy_list(l) + local m = {} + for i,v in ipairs(l) do m[i] = v end + return m +end +-- Sort a table in a new copy +function table.sortcopy(t, f) + local u = table.copy_list(t) + table.sort(u, f) + return u +end +-- Remove a value from a table +function table.removevalue(t, r) + local rem = {} + for k,v in pairs(t) do + if v==r then table.insert(rem, k) end + end + for _,k in ipairs(rem) do t[k] = nil end +end +function table.removevalue_list(t, r) + for i = #t, 1, -1 do + if t[i]==r then + table.remove(t, i) + end + end +end +-- Export tables into formatted executable strings +local function tabs(tabLevel) + return (' '):rep(tabLevel) +end +local valueToString +local function tableToString(t, tabLevel, seen) + if type(t)~='table' or (getmetatable(t) and getmetatable(t).__tostring) then + return tostring(t) + elseif table.islist(t) then + if #t==0 then + return '{}' + else + local strs = {} + local containsTables = false + for _,v in ipairs(t) do + if type(v)=='table' then containsTables = true end + table.insert(strs, valueToString(v, tabLevel+1, seen)..',') + end + if containsTables or #t>3 then + return '{\n'..tabs(tabLevel+1) + ..table.concat(strs, '\n'..tabs(tabLevel+1)) + ..'\n'..tabs(tabLevel)..'}' + else + return '{ '..table.concat(strs, ' ')..' }' + end + end + else + local containsNonStringKeys = false + for k,v in pairs(t) do + if type(k)~='string' or k:find('[^a-zA-Z0-9_]') then + containsNonStringKeys = true + elseif type(k)=='table' then + error('table.tostring: table contains a table as key, cannot serialize') + end + end + local strs = {} + if containsNonStringKeys then + for k,v in pairs(t) do + table.insert(strs, '\n'..tabs(tabLevel+1) + ..'['..valueToString(k, tabLevel+1, seen)..'] = ' + ..valueToString(v, tabLevel+1, seen)..',') + end + else + for k,v in pairs(t) do + table.insert(strs, '\n'..tabs(tabLevel+1) + ..k..' = '..valueToString(v, tabLevel+1, seen)..',') + end + end + return '{'..table.concat(strs)..'\n'..tabs(tabLevel)..'}' + end +end +valueToString = function(v, tabLevel, seen) + local t = type(v) + if t=='table' then + if seen[v] then + return 'nil --[[ already seen: '..tostring(v)..' ]]' + else + seen[v] = true + return tableToString(v, tabLevel, seen) + end + elseif t=='string' then + return '\''..string.escape(v)..'\'' + elseif t=='number' or t=='boolean' then + return tostring(v) + else + --error('table.tostring: table contains a '..t..' value, cannot serialize') + return 'nil --[[ cannot serialize '..t..': '..tostring(v)..' ]]' + end +end +function table.tostring(t) + return tableToString(t, 0, {}) +end + + +-- String + +-- Split string into table by separator +-- or by chars if no separator given +-- if regex is not true, sep is treated as a regex pattern +function string.split(str, sep, noregex) + if type(str)~='string' then + error('string.split: argument #1: expected string, got '..type(str), 2) end + if sep==nil or sep=='' then + local t = {} + local ns = #str + for x = 1, ns do + table.insert(t, str:sub(x, x)) + end + return t + elseif type(sep)=='string' then + local t = {} + if #str>0 then + local first = 1 + while true do + local last, newfirst = str:find(sep, first, noregex) + if not last then break end + table.insert(t, str:sub(first, last-1)) + first = newfirst+1 + end + table.insert(t, str:sub(first, #str)) + end + return t + else + error( + 'string.split: argument #2: expected string or nil, got '..type(sep), 2) + end +end +-- Split string to a list of char bytes +function string.bytes(s) + local b = {} + for i=1,#s do + local c = s:sub(i,i) + table.insert(b, c:byte()) + end + return b +end +-- Trim leading and trailing whitespace +function string.trim(s, ws) + ws = ws or '[ \t\r\t]' + return s:gsub('^'..ws..'+', ''):gsub(ws..'+$', '')..'' +end +-- String slicing and searching using [] operator +local str_meta = getmetatable('') +local str_meta_index_old= str_meta.__index +function str_meta.__index(s,k) + if type(k)=='string' then + return str_meta_index_old[k] + elseif type(k)=='number' then + if k<0 then k = #s+k+1 end + return string.sub(s,k,k) + elseif type(k)=='table' then + local a = k[1]<0 and (#s+k[1]+1) or k[1] + local b = k[2]<0 and (#s+k[2]+1) or k[2] + return string.sub(s,a,b) + end +end +-- String iterator +function string.chars(s) + local i = 0 + return function() + i = i+1 + if i<=#s then return s:sub(i,i) + else return nil end + end +end +-- Escape sequences +local defaultEscapes = { + ['\\'] = '\\\\', + ['\''] = '\\\'', + ['\"'] = '\\\"', + ['\t'] = '\\t', + ['\r'] = '\\r', + ['\n'] = '\\n', + ['\0'] = '\\0', +} +function string.escape(s, escapes) + escapes = escapes or defaultEscapes + local t = {} + for i=1,#s do + local c = s:sub(i,i) + table.insert(t, escapes[c] or c) + end + return table.concat(t) +end +local defaultEscapeChar = '\\' +local defaultUnescapes = { + ['\\'] = '\\', + ['\''] = '\'', + ['\"'] = '\"', + ['t'] = '\t', + ['r'] = '\r', + ['n'] = '\n', + ['0'] = '\0', +} +function string.unescape(s, escapeChar, unescapes) + escapeChar = escapeChar or defaultEscapeChar + unescapes = unescapes or defaultUnescapes + local t = {} + local inEscape = false + for i=1,#s do + local c = s:sub(i,i) + if inEscape then + table.insert(t, unescapes[c] + or error('string.unescape: invalid escape sequence: \'' + ..escapeChar..c..'\'')) + elseif c==escapeChar then + inEscape = true + else + table.insert(t, c) + end + end + return table.concat(t) +end + + +-- IO + +io = io or {} +-- Read entire file at once, return nil,err if access failed +function io.readfile(filename) + local fi,err = io.open(filename, 'rb') + if not fi then return nil,err end + local s = fi:read("*a") + fi:close() + return s +end +-- Write data to file all at once, return true if success / false,err if failure +function io.writefile(filename, data) + local fi,err = io.open(filename, 'wb') + if not fi then return false,err end + fi:write(data) + fi:close() + return true,nil +end + + +-- Math + +-- Round +function math.round(x) + return math.floor(x+0.5) +end +-- Mod that accounts for floating point inaccuracy +function math.mod(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 + else return m end +end +-- Clamp value between min and max +function math.clamp(v, n, x) + return math.min(x, math.max(v, n)) +end diff --git a/src/util/vector.lua b/src/util/vector.lua new file mode 100644 index 0000000..ec242b4 --- /dev/null +++ b/src/util/vector.lua @@ -0,0 +1,219 @@ + +-- Vector math class with operators +local vector_meta +local vector_new +local function vector_check(v, n, name, argn) + if not v.__is_vector then + error('vector '..name..': argument #'..(argn or 1) + ..': expected vector, got '..type(v), n+1) end +end +local function vector_checksamelen(v1, v2, name) + vector_check(v1, 3, name, 1) + vector_check(v2, 3, name, 2) + if #v1~=#v2 then + error('vector '..name..': vector lengths do not match (lengths are ' + ..#v1..' and '..#v2..')', 3) end + return #v1 +end +local function vector_checklen(v1, v2, name, len) + vector_check(v1, 3, name, 1) + vector_check(v2, 3, name, 2) + if #v1~=len or #v2~=len then + error('vector '..name..': vector lengths are not '..len..' (lengths are ' + ..#v1..' and '..#v2..')', 3) end +end +local function vector_opnnn(name, op) + return function(v1, v2) + local len = vector_checksamelen(v1, v2, name) + local v3 = {} + for i = 1, len do + v3[i] = op(v1[i], v2[i]) + end + return vector_new(v3) + end +end +local function vector_opnxn(name, op) + return function(v1, v2) + local v1v = type(v1)=='table' and v1.__is_vector + local v2v = type(v2)=='table' and v2.__is_vector + if v1v and v2v then + local len = vector_checksamelen(v1, v2, name) + local v3 = {} + for i = 1, len do + v3[i] = op(v1[i], v2[i]) + end + return vector_new(v3) + else + if v2v then v1,v2 = v2,v1 end + local len = #v1 + local v3 = {} + for i = 1, len do + v3[i] = op(v1[i], v2) + end + return vector_new(v3) + end + end +end +local function vector_opn0n(name, op) + return function(v1) + --vector_check(v1, 1, name) + local len = #v1 + local v2 = {} + for i = 1, len do + v2[i] = op(v1[i]) + end + return vector_new(v2) + end +end +local vector_indices = {x = 1, y = 2, z = 3, w = 4, r = 1, g = 2, b = 3, a = 4} +local vector_meta = { + __is_vector = true, + __index = function(t, k) + if tonumber(k) then return rawget(t, k) + elseif vector_indices[k] then return rawget(t, vector_indices[k]) + else return getmetatable(t)[k] + end + end, + __newindex = function(t, k, v) + if tonumber(k) then rawset(t, k, v) + elseif vector_indices[k] then rawset(t, vector_indices[k], v) + else return + end + end, + __add = vector_opnnn('add', function(x1, x2) return x1+x2 end), + __sub = vector_opnnn('sub', function(x1, x2) return x1-x2 end), + __mul = vector_opnxn('mul', function(x1, x2) return x1*x2 end), + __div = vector_opnxn('div', function(x1, x2) return x1/x2 end), + __pow = vector_opnxn('pow', function(x1, x2) return x1^x2 end), + __unm = vector_opn0n('inv', function(x1) return -x1 end), + __concat = nil, + --__len = function(v1) return #v1 end, + __len = nil, + __eq = function(v1, v2) + local len = vector_checksamelen(v1, v2, 'equals') + for i = 1, len do + if v1[i]~=v2[i] then return false end + end + return true + end, + __lt = nil, + __le = nil, + __call = nil, + abs = vector_opn0n('abs', math.abs), + length = function(v1) + --vector_check(v1, 2, 'length') + local len = #v1 + local l = 0 + for i = 1, len do + l = l + v1[i]^2 + end + return math.sqrt(l) + end, + normalize = function(v1) + --vector_check(v1, 2, 'normal') + local length = v1:length() + local len = #v1 + local v3 = {} + for i = 1, len do + if length==0 then v3[i] = 0 + else v3[i] = v1[i]/length end + end + return vector_new(v3) + end, + __tostring = function(v1) + --vector_check(v1, 2, 'tostring') + local st = {} + local len = #v1 + for i = 1, len do + table.insert(st, tostring(v1[i])) + end + return '{ '..table.concat(st, ', ')..' }' + end, + unpack = function(v1) return unpack(v1) end, + floor = vector_opn0n('floor', function(x1) return math.floor(x1) end), + ceil = vector_opn0n('ceil' , function(x1) return math.ceil (x1) end), + round = vector_opn0n('round', function(x1) return math.floor(x1+0.5) end), + dot = function(v1, v2) + local len = vector_checksamelen(v1, v2, 'dot') + local x = 0 + for i = 1, len do + x = x + v1[i]*v2[i] + end + return x + end, + cross = function(v1, v2) + vector_checklen(v1, v2, 'cross', 3) + return vector_new{ + v1[2]*v2[3] - v1[3]*v2[2], + v1[3]*v2[1] - v1[1]*v2[3], + v1[1]*v2[2] - v1[2]*v2[1], + } + end, + rotateByAngleId = function(v1, r) + --vector_check(v1, 2, 'rotate') + if type(r)~='number' or r%1~=0 then + error('vector rotateByAngleId: invalid rotation '..tostring(r), 2) end + r = r%4 + local v2 + if r==0 then v2 = vector_new{ v1[1], v1[2], v1[3] } + elseif r==1 then v2 = vector_new{ v1[2], -v1[1], v1[3] } + 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 + end, + rotate2d = function(v, r) + --vector_check(v, 2, 'rotate2d') + if type(r)~='number' then + error('vector rotate2d: invalid rotation '..tostring(r), 2) end + local len = math.sqrt(v[1]^2 + v[2]^2) + local ang = math.atan2(v[2], v[1]) + r + local v2 = vector_new{ math.cos(ang)*len, math.sin(ang)*len } + return v2 + end, + tsString = function(v) + --vector_check(v, 2, 'tsString') + return table.concat(v, ' ') + end, + distance = function(v1, v2) + local len = vector_checksamelen(v1, v2, 'distance') + local sum = 0 + for i=1,len do + sum = sum + (v1[i] - v2[i])^2 + end + return math.sqrt(sum) + end, + copy = function(v) + --vector_check(v, 2, 'copy') + return vector_new(v) + end, +} +vector_new = function(vi) + if vi then + if type(vi)=='string' then + local vi2 = {} + for val in vi:gmatch('[0-9%.%-e]+') do + table.insert(vi2, tonumber(val)) + end + vi = vi2 + elseif type(vi)~='table' then + error('vector: argument #1: expected input table, got '..type(vi), 2) + end + local v = {} + if #vi>0 then + for i = 1, #vi do v[i] = vi[i] end + else + for n, i in pairs(vector_indices) do v[i] = vi[n] end + if #v==0 then + error('vector: argument #1: table contains no values', 2) + end + end + setmetatable(v, vector_meta) + return v + else + error('vector: argument #1: expected input table, got nil', 2) + end +end + +vector = vector_new +return vector_new