diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..759bf36 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,97 @@ +name: build + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + linux: + name: Linux + runs-on: ubuntu-18.04 + + steps: + - name: Checkout server + uses: actions/checkout@v2 + with: + repository: callofduty4x/CoD4x_Server + path: server + + - name: Set up needed libs + run: | + sudo apt-get install g++-multilib gcc-multilib + sudo dpkg --add-architecture i386 + sudo apt-get install nasm:i386 paxctl:i386 libtommath-dev:i386 + wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz + sudo tar -zxvf libiconv-1.16.tar.gz + cd libiconv-1.16 + sudo ./configure --prefix=/usr/local --host=i686-linux-gnu "CFLAGS=-m32" "CXXFLAGS=-m32" "LDFLAGS=-m32" + sudo make + sudo make install + sudo ln -s /usr/local/lib/libiconv.so.2 /usr/lib/libiconv.so.2 + sudo ldconfig + + - name: Checkout plugin + uses: actions/checkout@v2 + with: + repository: leiizko/cod4x_lua_plugin + path: server/plugins/lua + + - name: Build plugin + run: | + cd server/plugins/lua + make ICONV=true + + windows: + name: Windows + runs-on: windows-latest + + steps: + - name: Get MinGW (i686-8.1.0-release-posix-dwarf) + run: | + $Uri = "https://downloads.sourceforge.net/mingw-w64/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z" + $filename = "mingw32.7z" + cd C:/ + Start-BitsTransfer -Source $Uri -Destination $filename + 7z x $filename + + - name: Get NASM + uses: ilammy/setup-nasm@v1 + + - name: Checkout server + uses: actions/checkout@v2 + with: + repository: callofduty4x/CoD4x_Server + path: server + + - name: Get pexports + run: | + cd server + Invoke-WebRequest "https://github.com/callofduty4x/CoD4x_Server/raw/master/tools/pexports-0.47-mingw32-bin.tar.xz" -OutFile "pexports.tar.xz" + 7z x pexports.tar.xz + 7z x pexports.tar + + - name: Build server + run: | + $path = $env:Path + $env:Path = "C:\mingw32\bin;" + $env:Path += $path + cd server + mingw32-make + + - name: Checkout plugin + uses: actions/checkout@v2 + with: + repository: leiizko/cod4x_lua_plugin + path: server/plugins/lua + + - name: Build plugin + run: | + $path = $env:Path + $env:Path = "C:\mingw32\bin;" + $env:Path += $path + cd server/plugins/lua + mingw32-make ICONV=true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..2e82f9c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,107 @@ +name: release + +on: + release: + types: [created] + +jobs: + linux: + name: Linux + runs-on: ubuntu-18.04 + + steps: + - name: Checkout server + uses: actions/checkout@v2 + with: + repository: callofduty4x/CoD4x_Server + path: server + + - name: Set up needed libs + run: | + sudo apt-get install g++-multilib gcc-multilib + sudo dpkg --add-architecture i386 + sudo apt-get install nasm:i386 paxctl:i386 libtommath-dev:i386 + wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz + sudo tar -zxvf libiconv-1.16.tar.gz + cd libiconv-1.16 + sudo ./configure --prefix=/usr/local --host=i686-linux-gnu "CFLAGS=-m32" "CXXFLAGS=-m32" "LDFLAGS=-m32" + sudo make + sudo make install + sudo ln -s /usr/local/lib/libiconv.so.2 /usr/lib/libiconv.so.2 + sudo ldconfig + + - name: Checkout plugin + uses: actions/checkout@v2 + with: + repository: leiizko/cod4x_lua_plugin + path: server/plugins/lua + + - name: Build plugin + run: | + cd server/plugins/lua + make ICONV=true + + - name: Publish + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + token: ${{ secrets.GITHUB_TOKEN }} + artifacts: "server/plugins/lua/lua.so" + + windows: + name: Windows + runs-on: windows-latest + + steps: + - name: Get MinGW (i686-8.1.0-release-posix-dwarf) + run: | + $Uri = "https://downloads.sourceforge.net/mingw-w64/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z" + $filename = "mingw32.7z" + cd C:/ + Start-BitsTransfer -Source $Uri -Destination $filename + 7z x $filename + + - name: Get NASM + uses: ilammy/setup-nasm@v1 + + - name: Checkout server + uses: actions/checkout@v2 + with: + repository: callofduty4x/CoD4x_Server + path: server + + - name: Get pexports + run: | + cd server + Invoke-WebRequest "https://github.com/callofduty4x/CoD4x_Server/raw/master/tools/pexports-0.47-mingw32-bin.tar.xz" -OutFile "pexports.tar.xz" + 7z x pexports.tar.xz + 7z x pexports.tar + + - name: Build server + run: | + $path = $env:Path + $env:Path = "C:\mingw32\bin;" + $env:Path += $path + cd server + mingw32-make + + - name: Checkout plugin + uses: actions/checkout@v2 + with: + repository: leiizko/cod4x_lua_plugin + path: server/plugins/lua + + - name: Build plugin + run: | + $path = $env:Path + $env:Path = "C:\mingw32\bin;" + $env:Path += $path + cd server/plugins/lua + mingw32-make ICONV=true + + - name: Publish + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + token: ${{ secrets.GITHUB_TOKEN }} + artifacts: "server/plugins/lua/lua.dll" diff --git a/functions.c b/functions.c new file mode 100644 index 0000000..766d6b8 --- /dev/null +++ b/functions.c @@ -0,0 +1,944 @@ +#include "main.h" +#include "functions.h" + +void registerFunctionsToLua() +{ + // Register functions + lua_register( LuaVM, "Plugin_AddCommand", Lua_Cmd_AddCommand ); + lua_register( LuaVM, "Plugin_ScrAddFunction", Lua_ScrAddFunction ); + + // Add functions + lua_register( LuaVM, "Plugin_Scr_AddEntity", Lua_Scr_AddEntity ); + lua_register( LuaVM, "Plugin_Scr_AddInt", Lua_Scr_AddInt ); + lua_register( LuaVM, "Plugin_Scr_AddFloat", Lua_Scr_AddFloat ); + lua_register( LuaVM, "Plugin_Scr_AddBool", Lua_Scr_AddBool ); + lua_register( LuaVM, "Plugin_Scr_AddString", Lua_Scr_AddString ); + lua_register( LuaVM, "Plugin_Scr_AddUndefined", Lua_Scr_AddUndefined ); + lua_register( LuaVM, "Plugin_Scr_AddVector", Lua_Scr_AddVector ); + lua_register( LuaVM, "Plugin_Scr_AddArray", Lua_Scr_AddArray ); + lua_register( LuaVM, "Plugin_Scr_MakeArray", Lua_Scr_MakeArray ); + lua_register( LuaVM, "Plugin_Scr_AddArrayKeys", Lua_Scr_AddArrayKeys ); + + // Script threads + lua_register( LuaVM, "Plugin_Scr_ExecEntThread", Lua_Scr_ExecEntThread ); + lua_register( LuaVM, "Plugin_Scr_ExecThread", Lua_Scr_ExecThread ); + lua_register( LuaVM, "Plugin_Scr_FreeThread", Lua_Scr_FreeThread ); + // Get functions + lua_register( LuaVM, "Plugin_Scr_GetNumParam", Lua_Scr_GetNumParam ); + lua_register( LuaVM, "Plugin_Scr_GetInt", Lua_Scr_GetInt ); + lua_register( LuaVM, "Plugin_Scr_GetFloat", Lua_Scr_GetFloat ); + lua_register( LuaVM, "Plugin_Scr_GetString", Lua_Scr_GetString ); + lua_register( LuaVM, "Plugin_Scr_GetEntity", Lua_Scr_GetEntity ); + lua_register( LuaVM, "Plugin_Scr_GetType", Lua_Scr_GetType ); + lua_register( LuaVM, "Plugin_Scr_GetVector", Lua_Scr_GetVector ); + lua_register( LuaVM, "Plugin_Cmd_Argv", Lua_Cmd_Argv ); + lua_register( LuaVM, "Plugin_Cmd_Argc", Lua_Cmd_Argc ); + + // Utility + lua_register( LuaVM, "Plugin_Printf", Lua_Printf ); + lua_register( LuaVM, "Plugin_DPrintf", Lua_DPrintf ); + lua_register( LuaVM, "Plugin_GetVersion", Lua_GetPluginVersion ); + lua_register( LuaVM, "Plugin_Milliseconds", Lua_GetMilliseconds ); + lua_register( LuaVM, "Plugin_Scr_Error", Lua_Scr_Error ); + lua_register( LuaVM, "Plugin_Scr_ParamError", Lua_Scr_ParamError ); + lua_register( LuaVM, "Plugin_Scr_ObjectError", Lua_Scr_ObjectError ); + lua_register( LuaVM, "Plugin_Error", Lua_Error ); + + // iconv +#ifdef EICONV + lua_register( LuaVM, "Plugin_iconv_open", Lua_iconv_open ); + lua_register( LuaVM, "Plugin_iconv_close", Lua_iconv_close ); + lua_register( LuaVM, "Plugin_iconv", Lua_iconv ); +#endif // EICONV +} + +#ifdef EICONV + +#define MAX_CD 3 +iconv_t cd_g[ MAX_CD ]; +int Lua_iconv( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 2 ) + { + luaL_error( L, "Plugin_iconv: Function requires exactly 2 parameters!" ); + return 1; + } + + if( !lua_isnumber ( L, 1 ) ) + { + luaL_error( L, "Plugin_iconv: parameter 1 must be an integer!" ); + return 1; + } + + int idx = lua_tointeger( L, 1 ); + + if( idx < 0 || idx >= MAX_CD || cd_g[ idx ] == NULL ) + { + luaL_error( L, "Plugin_iconv: parameter 1 is invalid!" ); + return 1; + } + + if( !lua_isstring( L, 2 ) ) + { + luaL_error( L, "Plugin_iconv: parameter 2 must be a string!" ); + return 1; + } + + char *inbuf = (char *)lua_tostring( L, 2 ); + size_t inbytesleft = lua_objlen( L, 2 ); + char outbufa[ 1024 ]; + char *outbuf = outbufa; + char *outbuf_start = outbufa; + size_t outbytesleft = 1024; + + size_t ret = iconv( cd_g[ idx ], &inbuf, &inbytesleft, &outbuf, &outbytesleft ); + if( ret == ( size_t )( -1 ) ) + { + if( errno == EILSEQ ) + { + luaL_error( L, "Plugin_iconv: An invalid multibyte sequence is encountered in the input!" ); + return 1; + } + else if( errno == EINVAL ) + { + luaL_error( L, "Plugin_iconv: An incomplete multibyte sequence is encountered in the input!" ); + return 1; + } + else if( errno == E2BIG ) + { + luaL_error( L, "Plugin_iconv: The output buffer has no more room for the next converted character!" ); + return 1; + } + else + { + luaL_error( L, "Plugin_iconv: Unknown error!" ); + return 1; + } + } + *outbuf = '\0'; + lua_pushstring( L, outbuf_start ); + return 1; +} + +int Lua_iconv_close( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_iconv_close: Function requires exactly 1 parameter!" ); + return 1; + } + + if( !lua_isnumber ( L, 1 ) ) + { + luaL_error( L, "Plugin_iconv_close: parameter 1 must be an integer!" ); + return 1; + } + + int idx = lua_tointeger( L, 1 ); + + if( idx < 0 || idx >= MAX_CD || cd_g[ idx ] == NULL ) + { + luaL_error( L, "Plugin_iconv_close: parameter 1 is invalid!" ); + return 1; + } + + int status = iconv_close( cd_g[ idx ] ); + if( status == -1 ) + { + luaL_error( L, "Plugin_iconv_close: Unknown error!" ); + return 1; + } + + cd_g[ idx ] = NULL; + lua_pushinteger( L, status ); + + return 1; +} + +int Lua_iconv_open( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 2 ) + { + luaL_error( L, "Plugin_iconv_open: Function requires exactly 2 parameters!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_iconv_open: parameter 1 must be a string!" ); + return 1; + } + + const char *toCode = (const char *)lua_tostring( L, 1 ); + + if( !lua_isstring( L, 2 ) ) + { + luaL_error( L, "Plugin_iconv_open: parameter 2 must be a string!" ); + return 1; + } + + const char *fromCode = (const char *)lua_tostring( L, 2 ); + + int idx = -1; + for( int i = 0; i < MAX_CD; i++ ) + { + if( cd_g[ i ] == NULL ) + { + idx = i; + break; + } + } + if( idx < 0 ) + { + luaL_error( L, "Plugin_iconv_open: No free conversion slots!" ); + return 1; + } + + cd_g[ idx ]= iconv_open( toCode, fromCode ); + + if( cd_g[ idx ] != ( iconv_t )( -1 ) ) + { + lua_pushinteger( L, idx ); + return 1; + } + else + { + if( errno == EINVAL ) + { + luaL_error( L, "Plugin_iconv_open: The conversion from fromcode to tocode is not supported!" ); + return 1; + } + else + { + luaL_error( L, "Plugin_iconv_open: Unknown error!" ); + return 1; + } + } +} +#endif // EICONV + +int Lua_Cmd_AddCommand( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 2 ) + { + luaL_error( L, "Plugin_AddCommand: Function requires exactly 2 parameters!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_AddCommand: parameter 1 must be a string!" ); + return 1; + } + char *funcName = (char *)lua_tostring( L, 1 ); + + if (!lua_isstring( L, 2 ) ) + { + luaL_error( L, "Plugin_AddCommand: parameter 2 must be an integer!" ); + return 1; + } + int power = lua_tointeger( L, 2 ); + + char *callback = AllocStub( funcName ); + + SetCall( (DWORD)callback + 5, Global_LuaHandler ); + + Plugin_AddCommand( funcName, (void *)callback, power ); + + return 0; +} + +int Lua_ScrAddFunction( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_ScrAddFunction: Function requires exactly 1 parameter!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_ScrAddFunction: parameter 1 must be a string!" ); + return 1; + } + char *funcName = (char *)lua_tostring( L, 1 ); + + char *callback = AllocStub( funcName ); + + SetCall( (DWORD)callback + 5, Global_LuaHandler ); + + Plugin_ScrAddFunction( funcName, (void *)callback ); + + return 0; +} + +int Lua_Scr_AddEntity( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_AddEntity: takes exactly one argument!\n" ); + return 1; + } + + if ( !lua_islightuserdata( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_AddEntity: Argument 1 must be an gentity_t!\n" ); + return 1; + } + + gentity_t* ent = (gentity_t*)lua_touserdata( L, 1 ); + + Plugin_Scr_AddEntity( ent ); + + return 0; +} + + +int Lua_Scr_AddInt( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Scr_AddInt: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Scr_AddInt: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + Plugin_Scr_AddInt( i ); + + return 0; +} + +int Lua_Scr_AddFloat( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Scr_AddFloat: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Scr_AddFloat: Argument must be a float!\n" ); + return 1; + } + + float i = (float)lua_tonumber( L, 1 ); + + Plugin_Scr_AddFloat( i ); + + return 0; +} + +int Lua_Scr_AddBool( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_AddBool: takes exactly one argument!\n" ); + return 1; + } + + if( lua_isboolean( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_AddBool: Argument must be boolean!\n" ); + return 1; + } + + qboolean add = lua_toboolean( L, 1 ); + + Plugin_Scr_AddBool( add ); + + return 0; +} + +int Lua_Scr_AddString( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_AddString: Function requires exactly 1 parameters!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_AddString: parameter 1 must be a string!" ); + return 1; + } + char *string = (char *)lua_tostring( L, 1 ); + + Plugin_Scr_AddString( string ); + + return 0; +} + +int Lua_Scr_AddUndefined( lua_State *L ) +{ + Plugin_Scr_AddUndefined(); + + return 0; +} + +int Lua_Scr_AddVector( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_AddVector: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_istable( L, 1 )) + { + luaL_error( L, "Plugin_Scr_AddVector: Argument must be a vec3!\n" ); + return 1; + } + + vec3_t vec; + + for ( int i = 1; i <= 3; i++ ) + { + lua_pushinteger( L, i ); + lua_gettable( L, 1 ); + + if( lua_isnil( L, -1 ) ) + { + luaL_error( L, "Plugin_Scr_AddVector: Argument must be a vec3!\n" ); + return 1; + } + + if ( !lua_isnumber( L, -1 ) ) + { + luaL_error( L, "Plugin_Scr_AddVector: vec3 must be a number!\n" ); + return 1; + } + + vec[ i - 1 ] = (float)lua_tonumber( L, -1 ); + lua_pop( L, 1 ); + } + + Plugin_Scr_AddVector( vec ); + + return 0; +} + +int Lua_Scr_AddArray( lua_State *L ) +{ + Plugin_Scr_AddArray(); + + return 0; +} + +int Lua_Scr_MakeArray( lua_State *L ) +{ + Plugin_Scr_MakeArray(); + + return 0; +} + +int Lua_Scr_AddArrayKeys( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_AddArrayKeys: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Plugin_Scr_AddArrayKeys: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + Plugin_Scr_AddArrayKeys( i ); + + return 0; +} + +int Lua_Scr_ExecEntThread( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 3 ) + { + luaL_error( L, "Lua_Scr_ExecEntThread: takes three arguments!\n" ); + return 1; + } + + if ( !lua_islightuserdata( L, 1 ) ) + { + luaL_error( L, "Lua_Scr_ExecEntThread: Argument 1 must be an gentity_t!\n" ); + return 1; + } + + gentity_t* ent = (gentity_t*)lua_touserdata( L, 1 ); + + if ( !lua_isnumber( L, 2 ) ) + { + luaL_error( L, "Lua_Scr_ExecEntThread: Argument 2 must be an integer!\n" ); + return 1; + } + + int callbackHook = lua_tointeger( L, 2 ); + + if ( !lua_isnumber( L, 3 ) ) + { + luaL_error( L, "Lua_Scr_ExecEntThread: Argument 3 must be an integer!\n" ); + return 1; + } + + int numArgs = (unsigned int)lua_tointeger( L, 3 ); + + int result = (int)Plugin_Scr_ExecEntThread( ent, callbackHook, numArgs ); + + lua_pushinteger( L, result ); + + return 1; +} + +int Lua_Scr_ExecThread( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 2 ) + { + luaL_error( L, "Plugin_Scr_ExecThread: takes two arguments!\n" ); + return 1; + } + + if ( !lua_isnumber( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_ExecThread: Argument 1 must be an integer!\n" ); + return 1; + } + + int callbackHook = lua_tointeger( L, 1 ); + + if ( !lua_isnumber( L, 2 ) ) + { + luaL_error( L, "Plugin_Scr_ExecThread: Argument 2 must be an integer!\n" ); + return 1; + } + + int numArgs = (unsigned int)lua_tointeger( L, 2 ); + + int result = (int)Plugin_Scr_ExecThread( callbackHook, numArgs ); + + lua_pushinteger( L, result ); + + return 1; +} + +int Lua_Scr_FreeThread( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_FreeThread: takes exactly one argument!\n" ); + return 1; + } + + if ( !lua_isnumber( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_FreeThread: Argument 1 must be an integer!\n" ); + return 1; + } + + short threadId = (short)lua_tointeger( L, 1 ); + + Plugin_Scr_FreeThread( threadId ); + + return 0; +} + +int Lua_Scr_GetNumParam( lua_State *L ) +{ + int result = Plugin_Scr_GetNumParam(); + + lua_pushinteger( L, result ); + + return 1; +} + +int Lua_Scr_GetFloat( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Scr_GetFloat: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Scr_GetFloat: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + float result = Plugin_Scr_GetFloat( i ); + + lua_pushnumber( L, (double)result ); + + return 1; +} + +int Lua_Scr_GetVector( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_GetVector: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Plugin_Scr_GetVector: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + vec3_t vec; + + Plugin_Scr_GetVector( i, &vec ); + + lua_newtable( L ); + for( int i = 0; i < 3; i++ ) + { + lua_pushnumber( L, vec[ i ] ); + lua_rawseti( L, -2, i + 1 ); + } + + return 1; +} + +int Lua_Cmd_Argc( lua_State *L ) +{ + int c = Plugin_Cmd_Argc(); + + lua_pushinteger( L, c ); + + return 1; +} + +int Lua_Cmd_Argv( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Cmd_Argv: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Plugin_Cmd_Argv: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + char *result = Plugin_Cmd_Argv( i ); + + lua_pushstring( L, result ); + + return 1; +} + +int Lua_Scr_GetType( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_GetType: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Plugin_Scr_GetType: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + unsigned int result = Plugin_Scr_GetType( i ); + + lua_pushinteger( L, result ); + + return 1; +} + +int Lua_Scr_GetInt( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_GetInt: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Plugin_Scr_GetInt: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + int result = Plugin_Scr_GetInt( i ); + + lua_pushinteger( L, result ); + + return 1; +} + +int Lua_Scr_GetString( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_GetString: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Plugin_Scr_GetString: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + char *result = Plugin_Scr_GetString( i ); + + lua_pushstring( L, result ); + + return 1; +} + +int Lua_Scr_GetEntity( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_GetEntity: takes exactly one argument!\n" ); + return 1; + } + + if (!lua_isnumber( L, 1 )) + { + luaL_error( L, "Plugin_Scr_GetEntity: Argument must be an integer!\n" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + gentity_t *result = Plugin_Scr_GetEntity( i ); + + lua_pushlightuserdata( L, result ); + + return 1; +} + +int Lua_Printf( lua_State *L ) +{ + int n = lua_gettop( L ); + if( n != 1 ) + { + luaL_error( L, "Plugin_Printf: Function takes exactly one parameter!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_Printf: parameter must be a string!" ); + return 1; + } + + Plugin_Printf( (char *)lua_tostring( L, 1 ) ); + + return 0; +} + +int Lua_DPrintf( lua_State *L ) +{ + int n = lua_gettop( L ); + if( n != 1 ) + { + luaL_error( L, "Plugin_DPrintf: Function takes exactly one parameter!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_DPrintf: parameter must be a string!" ); + return 1; + } + + Plugin_DPrintf( (char *)lua_tostring( L, 1 ) ); + + return 0; +} + +int Lua_GetPluginVersion( lua_State *L ) +{ + double version = PLUGIN_VERSION_MAJOR + ( PLUGIN_VERSION_MINOR * 0.1 ); + + lua_pushnumber( L, version ); + + return 1; +} + +int Lua_GetMilliseconds( lua_State *L ) +{ + int msec = Plugin_Milliseconds(); + + lua_pushinteger( L, msec ); + + return 1; +} + +int Lua_Error( lua_State *L ) +{ + int n = lua_gettop( L ); + if( n != 2 ) + { + luaL_error( L, "Plugin_Error: Function takes two parameters!" ); + return 1; + } + + if( !lua_isnumber( L, 1 ) ) + { + luaL_error( L, "Plugin_Error: parameter 1 must be an int!" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + if ( !lua_isstring( L, 2 ) ) + { + luaL_error( L, "Plugin_Error: parameter 2 must be a string!" ); + return 1; + } + + const char *string = (const char *)lua_tostring( L, 2 ); + + Plugin_Error( i, string ); + + return 0; +} + +int Lua_Scr_ObjectError( lua_State *L ) +{ + int n = lua_gettop( L ); + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_ObjectError: Function takes exactly one parameter!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_ObjectError: parameter must be a string!" ); + return 1; + } + + const char *string = (const char *)lua_tostring( L, 1 ); + + Plugin_Scr_ObjectError( string ); + + return 0; +} + +int Lua_Scr_Error( lua_State *L ) +{ + int n = lua_gettop( L ); + if( n != 1 ) + { + luaL_error( L, "Plugin_Scr_Error: Function takes exactly one parameter!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_Error: parameter must be a string!" ); + return 1; + } + + const char *string = (const char *)lua_tostring( L, 1 ); + + Plugin_Scr_Error( string ); + + return 0; +} + +int Lua_Scr_ParamError( lua_State *L ) +{ + int n = lua_gettop( L ); + if( n != 2 ) + { + luaL_error( L, "Plugin_Scr_ParamError: Function takes two parameters!" ); + return 1; + } + + if( !lua_isnumber( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_Error: parameter 1 must be an int!" ); + return 1; + } + + int i = lua_tointeger( L, 1 ); + + if ( !lua_isstring( L, 2 ) ) + { + luaL_error( L, "Plugin_Scr_Error: parameter 2 must be a string!" ); + return 1; + } + + const char *string = (const char *)lua_tostring( L, 2 ); + + Plugin_Scr_ParamError( i, string ); + + return 0; +} \ No newline at end of file diff --git a/functions.h b/functions.h new file mode 100644 index 0000000..24878b6 --- /dev/null +++ b/functions.h @@ -0,0 +1,60 @@ +#ifndef FUNCTIONS_H +#define FUNCTIONS_H + +#ifdef EICONV + #include + #include +#endif // EICONV + +void registerFunctionsToLua(); + +// Register functions +int Lua_Cmd_AddCommand( lua_State *L ); +int Lua_ScrAddFunction( lua_State *L ); + +// Add functions +int Lua_Scr_AddEntity( lua_State *L ); +int Lua_Scr_AddInt( lua_State *L ); +int Lua_Scr_AddFloat( lua_State *L ); +int Lua_Scr_AddBool( lua_State *L ); +int Lua_Scr_AddString( lua_State *L ); +int Lua_Scr_AddUndefined( lua_State *L ); +int Lua_Scr_AddVector( lua_State *L ); +int Lua_Scr_AddArray( lua_State *L ); +int Lua_Scr_MakeArray( lua_State *L ); +int Lua_Scr_AddArrayKeys( lua_State *L ); + +// Script threads +int Lua_Scr_ExecEntThread( lua_State *L ); +int Lua_Scr_ExecThread( lua_State *L ); +int Lua_Scr_FreeThread( lua_State *L ); + +// Get functions +int Lua_Scr_GetNumParam( lua_State *L ); +int Lua_Scr_GetInt( lua_State *L ); +int Lua_Scr_GetFloat( lua_State *L ); +int Lua_Scr_GetString( lua_State *L ); +int Lua_Scr_GetEntity( lua_State *L ); +int Lua_Scr_GetType( lua_State *L ); +int Lua_Scr_GetVector( lua_State *L ); +int Lua_Cmd_Argv( lua_State *L ); +int Lua_Cmd_Argc( lua_State *L ); + +// Utility +int Lua_Printf( lua_State *L ); +int Lua_DPrintf( lua_State *L ); +int Lua_GetPluginVersion( lua_State *L ); +int Lua_GetMilliseconds( lua_State *L ); +int Lua_Scr_Error( lua_State *L ); +int Lua_Scr_ParamError( lua_State *L ); +int Lua_Scr_ObjectError( lua_State *L ); +int Lua_Error( lua_State *L ); + +// iconv +#ifdef EICONV +int Lua_iconv_open( lua_State *L ); +int Lua_iconv_close( lua_State *L ); +int Lua_iconv( lua_State *L ); +#endif // EICONV + +#endif // FUNCTIONS_H \ No newline at end of file diff --git a/http.c b/http.c new file mode 100644 index 0000000..2599f52 --- /dev/null +++ b/http.c @@ -0,0 +1,190 @@ +#include "main.h" +#include "http.h" + +lua_httpReq openRequests[ LUA_HTTP_MAXOPENREQUESTS ]; + +void httpInit() +{ + lua_register( LuaVM, "Plugin_HTTP_makeRequest", Lua_HTTP_makeRequest ); +} + +int Lua_HTTP_makeRequest( lua_State *L ) +{ + int n = lua_gettop( L ); + + if( n < 3 ) + { + luaL_error( L, "Plugin_HTTP_makeRequest: Function requires 4 parameters!" ); + return 1; + } + + if( !lua_isstring( L, 1 ) ) + { + luaL_error( L, "Plugin_Scr_AddString: parameter 1 must be a string!" ); + return 1; + } + char *url = (char *)lua_tostring( L, 1 ); + + if( !lua_isstring( L, 2 ) ) + { + luaL_error( L, "Plugin_Scr_AddString: parameter 2 must be a string!" ); + return 1; + } + char *data = (char *)lua_tostring( L, 2 ); + + if( !lua_isstring( L, 3 ) ) + { + luaL_error( L, "Plugin_Scr_AddString: parameter 3 must be a string!" ); + return 1; + } + char *callback = (char *)lua_tostring( L, 3 ); + char *method = "POST"; + + if( n == 4 ) + { + if( !lua_isstring( L, 4 ) ) + { + luaL_error( L, "Plugin_Scr_AddString: parameter 4 must be a string!" ); + return 1; + } + method = (char *)lua_tostring( L, 4 ); + } + + lua_httpReq* r; + for( int i = 0; i < LUA_HTTP_MAXOPENREQUESTS; ++i ) + { + if( openRequests[ i ].request == NULL ) + { + r = &openRequests[ i ]; + break; + } + } + + if( r == NULL ) + { + Plugin_DPrintf( "Lua HTTP: max open requests reached!\n" ); + lua_pushinteger( L, 0 ); + return 1; + } + + r->callback = callback; + if( !Q_stricmp( method, "POST" ) ) + { + r->request = Plugin_HTTP_MakeHttpRequest( url, method, (byte *)data, strlen(data), "Content-Type: application/json\r\n" ); + } + else + { + r->request = Plugin_HTTP_MakeHttpRequest( url, method, NULL, 0, NULL ); + } + + if( r->request == NULL ) + { + Plugin_DPrintf( "Lua HTTP: Could not open new http request!\n" ); + lua_pushinteger( L, 0 ); + return 1; + } + + lua_pushinteger( L, 1 ); + return 1; +} + +void Lua_HTTP_updateRequests() +{ + int i = 0; + lua_httpReq* r = &openRequests[ i ]; + + while( r->request != NULL ) + { + int errCode = Plugin_HTTP_SendReceiveData( r->request ); + + if( errCode == 1 || errCode == -1 ) + { + byte* data = r->request->recvmsg.data + r->request->headerLength; + + lua_getglobal( LuaVM, r->callback ); + + if( errCode == 1 ) + { + lua_pushstring( LuaVM, (char *)data ); + } + else + { + lua_pushstring( LuaVM, NULL ); + } + Plugin_Lua_pcall( LuaVM, 1, LUA_MULTRET ); + + lua_settop( LuaVM, 0 ); + + Plugin_HTTP_FreeObj( r->request ); + r->request = NULL; + r->callback = NULL; + + popRequest( i ); + r = &openRequests[ i ]; + + continue; + } + + i++; + r = &openRequests[ i ]; + } +} + +void popRequest( int index ) +{ + for( int i = index; i < LUA_HTTP_MAXOPENREQUESTS; ++i ) + { + if( i + 1 >= LUA_HTTP_MAXOPENREQUESTS || openRequests[ i + 1 ].request == NULL ) + { + openRequests[ i ].request = NULL; + openRequests[ i ].callback = NULL; + break; + } + + openRequests[ i ] = openRequests[ i + 1 ]; + } +} + +int Q_stricmpn( const char *s1, const char *s2, int n ) +{ + int c1, c2; + + if ( s1 == NULL ) { + if ( s2 == NULL ) + return 0; + else + return -1; + } + else if ( s2==NULL ) + return 1; + + + + do { + c1 = *s1++; + c2 = *s2++; + + if (!n--) { + return 0; // strings are equal until end point + } + + if (c1 != c2) { + if (c1 >= 'a' && c1 <= 'z') { + c1 -= ('a' - 'A'); + } + if (c2 >= 'a' && c2 <= 'z') { + c2 -= ('a' - 'A'); + } + if (c1 != c2) { + return c1 < c2 ? -1 : 1; + } + } + } while (c1); + + return 0; // strings are equal +} + +int Q_stricmp( const char *s1, const char *s2 ) +{ + return (s1 && s2) ? Q_stricmpn (s1, s2, 99999) : -1; +} \ No newline at end of file diff --git a/http.h b/http.h new file mode 100644 index 0000000..e4ec2a0 --- /dev/null +++ b/http.h @@ -0,0 +1,20 @@ +#ifndef HTTP_H +#define HTTP_H + +#define LUA_HTTP_MAXOPENREQUESTS 64 + +typedef struct +{ + ftRequest_t* request; + char* callback; +} lua_httpReq; + +void httpInit(); +int Lua_HTTP_makeRequest( lua_State *L ); +void Lua_HTTP_updateRequests(); +void popRequest( int index ); + +int Q_stricmpn( const char *s1, const char *s2, int n ); +int Q_stricmp( const char *s1, const char *s2 ); + +#endif // HTTP_H \ No newline at end of file diff --git a/main.c b/main.c index 0f0d1c8..80c08c1 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,10 @@ #include "main.h" -#include +#include "functions.h" +#include "http.h" + +lua_State *LuaVM = NULL; +char *AllocMem = NULL; +int definedFunctions = 0; void Sv_LoadLuaScript() { @@ -38,57 +43,6 @@ void Sv_LuaDebug() Plugin_Printf( "Elements on stack: %i\n", lua_gettop( LuaVM ) ); } -void registerFunctionsToLua() -{ - // Register functions - lua_register( LuaVM, "Plugin_AddCommand", Lua_Cmd_AddCommand ); - lua_register( LuaVM, "Plugin_ScrAddFunction", Lua_ScrAddFunction ); - - // Add functions - lua_register( LuaVM, "Plugin_Scr_AddEntity", Lua_Scr_AddEntity ); - lua_register( LuaVM, "Plugin_Scr_AddInt", Lua_Scr_AddInt ); - lua_register( LuaVM, "Plugin_Scr_AddFloat", Lua_Scr_AddFloat ); - lua_register( LuaVM, "Plugin_Scr_AddBool", Lua_Scr_AddBool ); - lua_register( LuaVM, "Plugin_Scr_AddString", Lua_Scr_AddString ); - lua_register( LuaVM, "Plugin_Scr_AddUndefined", Lua_Scr_AddUndefined ); - lua_register( LuaVM, "Plugin_Scr_AddVector", Lua_Scr_AddVector ); - lua_register( LuaVM, "Plugin_Scr_AddArray", Lua_Scr_AddArray ); - lua_register( LuaVM, "Plugin_Scr_MakeArray", Lua_Scr_MakeArray ); - lua_register( LuaVM, "Plugin_Scr_AddArrayKeys", Lua_Scr_AddArrayKeys ); - - // Script threads - lua_register( LuaVM, "Plugin_Scr_ExecEntThread", Lua_Scr_ExecEntThread ); - lua_register( LuaVM, "Plugin_Scr_ExecThread", Lua_Scr_ExecThread ); - lua_register( LuaVM, "Plugin_Scr_FreeThread", Lua_Scr_FreeThread ); - // Get functions - lua_register( LuaVM, "Plugin_Scr_GetNumParam", Lua_Scr_GetNumParam ); - lua_register( LuaVM, "Plugin_Scr_GetInt", Lua_Scr_GetInt ); - lua_register( LuaVM, "Plugin_Scr_GetFloat", Lua_Scr_GetFloat ); - lua_register( LuaVM, "Plugin_Scr_GetString", Lua_Scr_GetString ); - lua_register( LuaVM, "Plugin_Scr_GetEntity", Lua_Scr_GetEntity ); - lua_register( LuaVM, "Plugin_Scr_GetType", Lua_Scr_GetType ); - lua_register( LuaVM, "Plugin_Scr_GetVector", Lua_Scr_GetVector ); - lua_register( LuaVM, "Plugin_Cmd_Argv", Lua_Cmd_Argv ); - lua_register( LuaVM, "Plugin_Cmd_Argc", Lua_Cmd_Argc ); - - // Utility - lua_register( LuaVM, "Plugin_Printf", Lua_Printf ); - lua_register( LuaVM, "Plugin_DPrintf", Lua_DPrintf ); - lua_register( LuaVM, "Plugin_GetVersion", Lua_GetPluginVersion ); - lua_register( LuaVM, "Plugin_Milliseconds", Lua_GetMilliseconds ); - lua_register( LuaVM, "Plugin_Scr_Error", Lua_Scr_Error ); - lua_register( LuaVM, "Plugin_Scr_ParamError", Lua_Scr_ParamError ); - lua_register( LuaVM, "Plugin_Scr_ObjectError", Lua_Scr_ObjectError ); - lua_register( LuaVM, "Plugin_Error", Lua_Error ); - - // iconv -#ifdef EICONV - lua_register( LuaVM, "Plugin_iconv_open", Lua_iconv_open ); - lua_register( LuaVM, "Plugin_iconv_close", Lua_iconv_close ); - lua_register( LuaVM, "Plugin_iconv", Lua_iconv ); -#endif // EICONV -} - PCL int OnInit() { LuaVM = luaL_newstate(); @@ -110,6 +64,7 @@ PCL int OnInit() luaL_openlibs( LuaVM ); registerFunctionsToLua(); + httpInit(); Plugin_AddCommand( "lua_loadscript", Sv_LoadLuaScript, 0 ); Plugin_AddCommand( "lua_debug", Sv_LuaDebug, 0 ); @@ -129,975 +84,166 @@ PCL void OnInfoRequest( pluginInfo_t *info ) strncpy(info->longDescription, "Adds support for Lua based plugins, most suitable for adding script functions that are too expensive to run in GSC.", sizeof(info->longDescription)); } -#ifdef EICONV - -#define MAX_CD 3 -iconv_t cd_g[ MAX_CD ]; -static int Lua_iconv( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 2 ) - { - luaL_error( L, "Plugin_iconv: Function requires exactly 2 parameters!" ); - return 1; - } - - if( !lua_isnumber ( L, 1 ) ) - { - luaL_error( L, "Plugin_iconv: parameter 1 must be an integer!" ); - return 1; - } - - int idx = lua_tointeger( L, 1 ); - - if( idx < 0 || idx >= MAX_CD || cd_g[ idx ] == NULL ) - { - luaL_error( L, "Plugin_iconv: parameter 1 is invalid!" ); - return 1; - } - - if( !lua_isstring( L, 2 ) ) - { - luaL_error( L, "Plugin_iconv: parameter 2 must be a string!" ); - return 1; - } - - char *inbuf = (char *)lua_tostring( L, 2 ); - size_t inbytesleft = lua_objlen( L, 2 ); - char outbufa[ 1024 ]; - char *outbuf = outbufa; - char *outbuf_start = outbufa; - size_t outbytesleft = 1024; - - size_t ret = iconv( cd_g[ idx ], &inbuf, &inbytesleft, &outbuf, &outbytesleft ); - if( ret == ( size_t )( -1 ) ) - { - if( errno == EILSEQ ) - { - luaL_error( L, "Plugin_iconv: An invalid multibyte sequence is encountered in the input!" ); - return 1; - } - else if( errno == EINVAL ) - { - luaL_error( L, "Plugin_iconv: An incomplete multibyte sequence is encountered in the input!" ); - return 1; - } - else if( errno == E2BIG ) - { - luaL_error( L, "Plugin_iconv: The output buffer has no more room for the next converted character!" ); - return 1; - } - else - { - luaL_error( L, "Plugin_iconv: Unknown error!" ); - return 1; - } - } - *outbuf = '\0'; - lua_pushstring( L, outbuf_start ); - return 1; -} - -static int Lua_iconv_close( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_iconv_close: Function requires exactly 1 parameter!" ); - return 1; - } - - if( !lua_isnumber ( L, 1 ) ) - { - luaL_error( L, "Plugin_iconv_close: parameter 1 must be an integer!" ); - return 1; - } - - int idx = lua_tointeger( L, 1 ); - - if( idx < 0 || idx >= MAX_CD || cd_g[ idx ] == NULL ) - { - luaL_error( L, "Plugin_iconv_close: parameter 1 is invalid!" ); - return 1; - } - - int status = iconv_close( cd_g[ idx ] ); - if( status == -1 ) - { - luaL_error( L, "Plugin_iconv_close: Unknown error!" ); - return 1; - } - - cd_g[ idx ] = NULL; - lua_pushinteger( L, status ); - - return 1; -} - -static int Lua_iconv_open( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 2 ) - { - luaL_error( L, "Plugin_iconv_open: Function requires exactly 2 parameters!" ); - return 1; - } - - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_iconv_open: parameter 1 must be a string!" ); - return 1; - } - - const char *toCode = (const char *)lua_tostring( L, 1 ); - - if( !lua_isstring( L, 2 ) ) - { - luaL_error( L, "Plugin_iconv_open: parameter 2 must be a string!" ); - return 1; - } - - const char *fromCode = (const char *)lua_tostring( L, 2 ); - - int idx = -1; - for( int i = 0; i < MAX_CD; i++ ) - { - if( cd_g[ i ] == NULL ) - { - idx = i; - break; - } - } - if( idx < 0 ) - { - luaL_error( L, "Plugin_iconv_open: No free conversion slots!" ); - return 1; - } - - cd_g[ idx ]= iconv_open( toCode, fromCode ); - - if( cd_g[ idx ] != ( iconv_t )( -1 ) ) - { - lua_pushinteger( L, idx ); - return 1; - } - else - { - if( errno == EINVAL ) - { - luaL_error( L, "Plugin_iconv_open: The conversion from fromcode to tocode is not supported!" ); - return 1; - } - else - { - luaL_error( L, "Plugin_iconv_open: Unknown error!" ); - return 1; - } - } -} -#endif // EICONV - -static int Lua_Cmd_AddCommand( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 2 ) - { - luaL_error( L, "Plugin_AddCommand: Function requires exactly 2 parameters!" ); - return 1; - } - - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_AddCommand: parameter 1 must be a string!" ); - return 1; - } - char *funcName = (char *)lua_tostring( L, 1 ); - - if (!lua_isstring( L, 2 ) ) - { - luaL_error( L, "Plugin_AddCommand: parameter 2 must be an integer!" ); - return 1; - } - int power = lua_tointeger( L, 2 ); - - char *callback = AllocStub( funcName ); - - SetCall( (DWORD)callback + 5, Global_LuaHandler ); - - Plugin_AddCommand( funcName, (void *)callback, power ); - - return 0; -} - -static int Lua_ScrAddFunction( lua_State *L ) +int Lua_TraceBack( lua_State* L ) { - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_ScrAddFunction: Function requires exactly 1 parameter!" ); - return 1; - } + Plugin_Printf( "****************** Lua Error: ******************\n\n%s\n", lua_tostring( L, -1 ) ); + luaL_traceback( L, L, NULL, 1 ); - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_ScrAddFunction: parameter 1 must be a string!" ); - return 1; - } - char *funcName = (char *)lua_tostring( L, 1 ); - - char *callback = AllocStub( funcName ); - - SetCall( (DWORD)callback + 5, Global_LuaHandler ); + Plugin_Printf( "%s\n\n************************************************\n", lua_tostring( L, -1 ) ); - Plugin_ScrAddFunction( funcName, (void *)callback ); - return 0; } -static int Lua_Scr_AddEntity( lua_State *L ) +int Plugin_Lua_pcall( lua_State* L, int nargs, int nret ) { - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_AddEntity: takes exactly one argument!\n" ); - return 1; - } + int hpos = lua_gettop( L ) - nargs; + + lua_pushcfunction( L, Lua_TraceBack ); - if ( !lua_islightuserdata( L, 1 ) ) - { - luaL_error( L, "Plugin_Scr_AddEntity: Argument 1 must be an gentity_t!\n" ); - return 1; - } + lua_insert( L, hpos ); - gentity_t* ent = (gentity_t*)lua_touserdata( L, 1 ); + int ret = lua_pcall( L, nargs, nret, hpos ); - Plugin_Scr_AddEntity( ent ); + lua_remove( L, hpos ); - return 0; + return ret; } - -static int Lua_Scr_AddInt( lua_State *L ) +char *AllocStub( char *funcName ) { - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Scr_AddInt: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Scr_AddInt: Argument must be an integer!\n" ); - return 1; - } + char *mem = AllocMem; + mem += STUB_SIZE * definedFunctions; + definedFunctions++; - int i = lua_tointeger( L, 1 ); + char *callback = mem; - Plugin_Scr_AddInt( i ); + *(char*)mem = 0x68; + mem += sizeof( char ); + *(int32_t*)mem = (int32_t)funcName; + mem += sizeof( int32_t ); + *(char*)mem = 0xe8; + mem += sizeof( char ); + *(int32_t*)mem = 0; + mem += sizeof( int32_t ); + *(char*)mem = 0x83; + mem += sizeof( char ); + *(char*)mem = 0xc4; + mem += sizeof( char ); + *(char*)mem = 0x04; + mem += sizeof( char ); + *(char*)mem = 0xc3; + mem += sizeof( char ); - return 0; + return callback; } -static int Lua_Scr_AddFloat( lua_State *L ) +DWORD SetCall(DWORD addr, void* destination) { - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Scr_AddFloat: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Scr_AddFloat: Argument must be a float!\n" ); - return 1; - } - - float i = (float)lua_tonumber( L, 1 ); - - Plugin_Scr_AddFloat( i ); - - return 0; -} -static int Lua_Scr_AddBool( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_AddBool: takes exactly one argument!\n" ); - return 1; - } - - if( lua_isboolean( L, 1 ) ) - { - luaL_error( L, "Plugin_Scr_AddBool: Argument must be boolean!\n" ); - return 1; - } - - qboolean add = lua_toboolean( L, 1 ); - - Plugin_Scr_AddBool( add ); - - return 0; -} + DWORD callwidth; + DWORD restore; + byte* baddr = (byte*)addr; -static int Lua_Scr_AddString( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_AddString: Function requires exactly 1 parameters!" ); - return 1; - } - - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_Scr_AddString: parameter 1 must be a string!" ); - return 1; - } - char *string = (char *)lua_tostring( L, 1 ); + callwidth = (DWORD)( destination - (void*)baddr - 5); + *baddr = 0xe8; + baddr++; - Plugin_Scr_AddString( string ); + restore = *(DWORD*)baddr; + *(DWORD*)baddr = callwidth; - return 0; + return restore; } -static int Lua_Scr_AddUndefined( lua_State *L ) +void *aligned_malloc( int size, int ALIGN ) { - Plugin_Scr_AddUndefined(); + void *mem = malloc(size + (ALIGN - 1)); + + void *ptr = (void**)((uintptr_t)(mem + (ALIGN - 1)) & ~(ALIGN - 1)); - return 0; + return ptr; } -static int Lua_Scr_AddVector( lua_State *L ) +PCL void OnPlayerAddBan(baninfo_t* baninfo) { - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_AddVector: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_istable( L, 1 )) - { - luaL_error( L, "Plugin_Scr_AddVector: Argument must be a vec3!\n" ); - return 1; - } + lua_getglobal( LuaVM, "OnPlayerAddBan" ); - vec3_t vec; - - for ( int i = 1; i <= 3; i++ ) + if( lua_isfunction( LuaVM, -1 ) ) { - lua_pushinteger( L, i ); - lua_gettable( L, 1 ); + char pid[128]; + char sid[128]; + char aid[128]; + Plugin_SteamIDToString( baninfo->playerid, pid, sizeof( pid ) ); + Plugin_SteamIDToString( baninfo->steamid, sid, sizeof( sid ) ); + Plugin_SteamIDToString( baninfo->adminsteamid, aid, sizeof( aid ) ); - if( lua_isnil( L, -1 ) ) - { - luaL_error( L, "Plugin_Scr_AddVector: Argument must be a vec3!\n" ); - return 1; - } + int perm = 0; + if( baninfo->duration == 0 ) + perm = 1; - if ( !lua_isnumber( L, -1 ) ) - { - luaL_error( L, "Plugin_Scr_AddVector: vec3 must be a number!\n" ); - return 1; - } + lua_pushstring( LuaVM, pid ); + lua_pushstring( LuaVM, sid ); + lua_pushstring( LuaVM, aid ); + lua_pushinteger( LuaVM, perm ); - vec[ i - 1 ] = (float)lua_tonumber( L, -1 ); - lua_pop( L, 1 ); + Plugin_Lua_pcall( LuaVM, 4, LUA_MULTRET ); } - Plugin_Scr_AddVector( vec ); - - return 0; -} - -static int Lua_Scr_AddArray( lua_State *L ) -{ - Plugin_Scr_AddArray(); - - return 0; -} - -static int Lua_Scr_MakeArray( lua_State *L ) -{ - Plugin_Scr_MakeArray(); - - return 0; + lua_settop( LuaVM, 0 ); } -static int Lua_Scr_AddArrayKeys( lua_State *L ) +PCL void OnPlayerDC(client_t* client, const char* reason) { - int n = lua_gettop( L ); + lua_getglobal( LuaVM, "OnPlayerDC" ); - if( n != 1 ) + if( lua_isfunction( LuaVM, -1 ) ) { - luaL_error( L, "Plugin_Scr_AddArrayKeys: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Plugin_Scr_AddArrayKeys: Argument must be an integer!\n" ); - return 1; + char pid[128]; + char sid[128]; + Plugin_SteamIDToString( client->playerid, pid, sizeof( pid ) ); + Plugin_SteamIDToString( client->steamid, sid, sizeof( sid ) ); + + lua_pushinteger( LuaVM, Plugin_GetClientNumForClient( client ) ); + lua_pushstring( LuaVM, pid ); + lua_pushstring( LuaVM, sid ); + + Plugin_Lua_pcall( LuaVM, 3, LUA_MULTRET ); } - int i = lua_tointeger( L, 1 ); - - Plugin_Scr_AddArrayKeys( i ); - - return 0; + lua_settop( LuaVM, 0 ); } -static int Lua_Scr_ExecEntThread( lua_State *L ) +PCL void OnFrame() { - int n = lua_gettop( L ); - - if( n != 3 ) - { - luaL_error( L, "Lua_Scr_ExecEntThread: takes three arguments!\n" ); - return 1; - } + Lua_HTTP_updateRequests(); - if ( !lua_islightuserdata( L, 1 ) ) - { - luaL_error( L, "Lua_Scr_ExecEntThread: Argument 1 must be an gentity_t!\n" ); - return 1; - } - - gentity_t* ent = (gentity_t*)lua_touserdata( L, 1 ); - - if ( !lua_isnumber( L, 2 ) ) - { - luaL_error( L, "Lua_Scr_ExecEntThread: Argument 2 must be an integer!\n" ); - return 1; - } + lua_getglobal( LuaVM, "OnFrame" ); - int callbackHook = lua_tointeger( L, 2 ); - - if ( !lua_isnumber( L, 3 ) ) + if( lua_isfunction( LuaVM, -1 ) ) { - luaL_error( L, "Lua_Scr_ExecEntThread: Argument 3 must be an integer!\n" ); - return 1; + Plugin_Lua_pcall( LuaVM, 0, LUA_MULTRET ); } - int numArgs = (unsigned int)lua_tointeger( L, 3 ); - - int result = (int)Plugin_Scr_ExecEntThread( ent, callbackHook, numArgs ); - - lua_pushinteger( L, result ); - - return 1; + lua_settop( LuaVM, 0 ); } -static int Lua_Scr_ExecThread( lua_State *L ) +PCL void OnPlayerGotAuthInfo(netadr_t* from, uint64_t* playerid, uint64_t *steamid, char *rejectmsg, qboolean *returnNow, client_t* cl) { - int n = lua_gettop( L ); - - if( n != 2 ) - { - luaL_error( L, "Plugin_Scr_ExecThread: takes two arguments!\n" ); - return 1; - } + lua_getglobal( LuaVM, "OnPlayerGotAuthInfo" ); - if ( !lua_isnumber( L, 1 ) ) + if( lua_isfunction( LuaVM, -1 ) ) { - luaL_error( L, "Plugin_Scr_ExecThread: Argument 1 must be an integer!\n" ); - return 1; + char pid[128]; + char sid[128]; + Plugin_SteamIDToString( cl->playerid, pid, sizeof( pid ) ); + Plugin_SteamIDToString( cl->steamid, sid, sizeof( sid ) ); + + lua_pushinteger( LuaVM, Plugin_GetClientNumForClient( cl ) ); + lua_pushstring( LuaVM, pid ); + lua_pushstring( LuaVM, sid ); + lua_pushstring( LuaVM, rejectmsg ); + + Plugin_Lua_pcall( LuaVM, 4, LUA_MULTRET ); } - int callbackHook = lua_tointeger( L, 1 ); - - if ( !lua_isnumber( L, 2 ) ) - { - luaL_error( L, "Plugin_Scr_ExecThread: Argument 2 must be an integer!\n" ); - return 1; - } - - int numArgs = (unsigned int)lua_tointeger( L, 2 ); - - int result = (int)Plugin_Scr_ExecThread( callbackHook, numArgs ); - - lua_pushinteger( L, result ); - - return 1; -} - -static int Lua_Scr_FreeThread( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_FreeThread: takes exactly one argument!\n" ); - return 1; - } - - if ( !lua_isnumber( L, 1 ) ) - { - luaL_error( L, "Plugin_Scr_FreeThread: Argument 1 must be an integer!\n" ); - return 1; - } - - short threadId = (short)lua_tointeger( L, 1 ); - - Plugin_Scr_FreeThread( threadId ); - - return 0; -} - -static int Lua_Scr_GetNumParam( lua_State *L ) -{ - int result = Plugin_Scr_GetNumParam(); - - lua_pushinteger( L, result ); - - return 1; -} - -static int Lua_Scr_GetFloat( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Scr_GetFloat: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Scr_GetFloat: Argument must be an integer!\n" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - float result = Plugin_Scr_GetFloat( i ); - - lua_pushnumber( L, (double)result ); - - return 1; -} - -static int Lua_Scr_GetVector( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_GetVector: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Plugin_Scr_GetVector: Argument must be an integer!\n" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - vec3_t vec; - - Plugin_Scr_GetVector( i, &vec ); - - lua_newtable( L ); - for( int i = 0; i < 3; i++ ) - { - lua_pushnumber( L, vec[ i ] ); - lua_rawseti( L, -2, i + 1 ); - } - - return 1; -} - -static int Lua_Cmd_Argc( lua_State *L ) -{ - int c = Plugin_Cmd_Argc(); - - lua_pushinteger( L, c ); - - return 1; -} - -static int Lua_Cmd_Argv( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Cmd_Argv: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Plugin_Cmd_Argv: Argument must be an integer!\n" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - char *result = Plugin_Cmd_Argv( i ); - - lua_pushstring( L, result ); - - return 1; -} - -static int Lua_Scr_GetType( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_GetType: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Plugin_Scr_GetType: Argument must be an integer!\n" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - unsigned int result = Plugin_Scr_GetType( i ); - - lua_pushinteger( L, result ); - - return 1; -} - -static int Lua_Scr_GetInt( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_GetInt: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Plugin_Scr_GetInt: Argument must be an integer!\n" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - int result = Plugin_Scr_GetInt( i ); - - lua_pushinteger( L, result ); - - return 1; -} - -static int Lua_Scr_GetString( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_GetString: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Plugin_Scr_GetString: Argument must be an integer!\n" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - char *result = Plugin_Scr_GetString( i ); - - lua_pushstring( L, result ); - - return 1; -} - -static int Lua_Scr_GetEntity( lua_State *L ) -{ - int n = lua_gettop( L ); - - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_GetEntity: takes exactly one argument!\n" ); - return 1; - } - - if (!lua_isnumber( L, 1 )) - { - luaL_error( L, "Plugin_Scr_GetEntity: Argument must be an integer!\n" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - gentity_t *result = Plugin_Scr_GetEntity( i ); - - lua_pushlightuserdata( L, result ); - - return 1; -} - -static int Lua_Printf( lua_State *L ) -{ - int n = lua_gettop( L ); - if( n != 1 ) - { - luaL_error( L, "Plugin_Printf: Function takes exactly one parameter!" ); - return 1; - } - - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_Printf: parameter must be a string!" ); - return 1; - } - - Plugin_Printf( (char *)lua_tostring( L, 1 ) ); - - return 0; -} - -static int Lua_DPrintf( lua_State *L ) -{ - int n = lua_gettop( L ); - if( n != 1 ) - { - luaL_error( L, "Plugin_DPrintf: Function takes exactly one parameter!" ); - return 1; - } - - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_DPrintf: parameter must be a string!" ); - return 1; - } - - Plugin_DPrintf( (char *)lua_tostring( L, 1 ) ); - - return 0; -} - -static int Lua_GetPluginVersion( lua_State *L ) -{ - double version = PLUGIN_VERSION_MAJOR + ( PLUGIN_VERSION_MINOR * 0.1 ); - - lua_pushnumber( L, version ); - - return 1; -} - -static int Lua_GetMilliseconds( lua_State *L ) -{ - int msec = Plugin_Milliseconds(); - - lua_pushinteger( L, msec ); - - return 1; -} - -static int Lua_Error( lua_State *L ) -{ - int n = lua_gettop( L ); - if( n != 2 ) - { - luaL_error( L, "Plugin_Error: Function takes two parameters!" ); - return 1; - } - - if( !lua_isnumber( L, 1 ) ) - { - luaL_error( L, "Plugin_Error: parameter 1 must be an int!" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - if ( !lua_isstring( L, 2 ) ) - { - luaL_error( L, "Plugin_Error: parameter 2 must be a string!" ); - return 1; - } - - const char *string = (const char *)lua_tostring( L, 2 ); - - Plugin_Error( i, string ); - - return 0; -} - -static int Lua_Scr_ObjectError( lua_State *L ) -{ - int n = lua_gettop( L ); - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_ObjectError: Function takes exactly one parameter!" ); - return 1; - } - - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_Scr_ObjectError: parameter must be a string!" ); - return 1; - } - - const char *string = (const char *)lua_tostring( L, 1 ); - - Plugin_Scr_ObjectError( string ); - - return 0; -} - -static int Lua_Scr_Error( lua_State *L ) -{ - int n = lua_gettop( L ); - if( n != 1 ) - { - luaL_error( L, "Plugin_Scr_Error: Function takes exactly one parameter!" ); - return 1; - } - - if( !lua_isstring( L, 1 ) ) - { - luaL_error( L, "Plugin_Scr_Error: parameter must be a string!" ); - return 1; - } - - const char *string = (const char *)lua_tostring( L, 1 ); - - Plugin_Scr_Error( string ); - - return 0; -} - -static int Lua_Scr_ParamError( lua_State *L ) -{ - int n = lua_gettop( L ); - if( n != 2 ) - { - luaL_error( L, "Plugin_Scr_ParamError: Function takes two parameters!" ); - return 1; - } - - if( !lua_isnumber( L, 1 ) ) - { - luaL_error( L, "Plugin_Scr_Error: parameter 1 must be an int!" ); - return 1; - } - - int i = lua_tointeger( L, 1 ); - - if ( !lua_isstring( L, 2 ) ) - { - luaL_error( L, "Plugin_Scr_Error: parameter 2 must be a string!" ); - return 1; - } - - const char *string = (const char *)lua_tostring( L, 2 ); - - Plugin_Scr_ParamError( i, string ); - - return 0; -} - - - - -static int Lua_TraceBack( lua_State* L ) -{ - Plugin_Printf( "****************** Lua Error: ******************\n\n%s\n", lua_tostring( L, -1 ) ); - luaL_traceback( L, L, NULL, 1 ); - - Plugin_Printf( "%s\n\n************************************************\n", lua_tostring( L, -1 ) ); - - return 0; -} - -static int Plugin_Lua_pcall( lua_State* L, int nargs, int nret ) -{ - int hpos = lua_gettop( L ) - nargs; - - lua_pushcfunction( L, Lua_TraceBack ); - - lua_insert( L, hpos ); - - int ret = lua_pcall( L, nargs, nret, hpos ); - - lua_remove( L, hpos ); - - return ret; -} - -char *AllocStub( char *funcName ) -{ - char *mem = AllocMem; - mem += STUB_SIZE * definedFunctions; - definedFunctions++; - - char *callback = mem; - - *(char*)mem = 0x68; - mem += sizeof( char ); - *(int32_t*)mem = (int32_t)funcName; - mem += sizeof( int32_t ); - *(char*)mem = 0xe8; - mem += sizeof( char ); - *(int32_t*)mem = 0; - mem += sizeof( int32_t ); - *(char*)mem = 0x83; - mem += sizeof( char ); - *(char*)mem = 0xc4; - mem += sizeof( char ); - *(char*)mem = 0x04; - mem += sizeof( char ); - *(char*)mem = 0xc3; - mem += sizeof( char ); - - return callback; -} - -DWORD SetCall(DWORD addr, void* destination) -{ - - DWORD callwidth; - DWORD restore; - byte* baddr = (byte*)addr; - - callwidth = (DWORD)( destination - (void*)baddr - 5); - *baddr = 0xe8; - baddr++; - - restore = *(DWORD*)baddr; - *(DWORD*)baddr = callwidth; - - return restore; -} - -void *aligned_malloc( int size, int ALIGN ) -{ - void *mem = malloc(size + (ALIGN - 1)); - - void *ptr = (void**)((uintptr_t)(mem + (ALIGN - 1)) & ~(ALIGN - 1)); - - return ptr; + lua_settop( LuaVM, 0 ); } \ No newline at end of file diff --git a/main.h b/main.h index a9db7a7..5d432b9 100644 --- a/main.h +++ b/main.h @@ -6,11 +6,7 @@ #include "inc/lualib.h" #include "inc/lauxlib.h" #include - -#ifdef EICONV -#include -#include -#endif // EICONV +#include #ifdef _WIN32 #include @@ -22,68 +18,17 @@ #define MAX_FUNCTIONS 0x40 #define STUB_SIZE 0x20 #define PLUGIN_VERSION_MAJOR 0 -#define PLUGIN_VERSION_MINOR 3 +#define PLUGIN_VERSION_MINOR 4 typedef unsigned int long DWORD; -static lua_State *LuaVM; -static char *AllocMem = NULL; -static int definedFunctions = 0; +extern lua_State *LuaVM; +extern char *AllocMem; +extern int definedFunctions; +int Lua_TraceBack( lua_State* L ); +int Plugin_Lua_pcall( lua_State* L, int nargs, int nret ); void Global_LuaHandler( char *funcName ); -void registerFunctionsToLua(); -static int Lua_TraceBack( lua_State* L ); -static int Plugin_Lua_pcall( lua_State* L, int nargs, int nret ); - - -// Register functions -static int Lua_Cmd_AddCommand( lua_State *L ); -static int Lua_ScrAddFunction( lua_State *L ); - -// Add functions -static int Lua_Scr_AddEntity( lua_State *L ); -static int Lua_Scr_AddInt( lua_State *L ); -static int Lua_Scr_AddFloat( lua_State *L ); -static int Lua_Scr_AddBool( lua_State *L ); -static int Lua_Scr_AddString( lua_State *L ); -static int Lua_Scr_AddUndefined( lua_State *L ); -static int Lua_Scr_AddVector( lua_State *L ); -static int Lua_Scr_AddArray( lua_State *L ); -static int Lua_Scr_MakeArray( lua_State *L ); -static int Lua_Scr_AddArrayKeys( lua_State *L ); - -// Script threads -static int Lua_Scr_ExecEntThread( lua_State *L ); -static int Lua_Scr_ExecThread( lua_State *L ); -static int Lua_Scr_FreeThread( lua_State *L ); - -// Get functions -static int Lua_Scr_GetNumParam( lua_State *L ); -static int Lua_Scr_GetInt( lua_State *L ); -static int Lua_Scr_GetFloat( lua_State *L ); -static int Lua_Scr_GetString( lua_State *L ); -static int Lua_Scr_GetEntity( lua_State *L ); -static int Lua_Scr_GetType( lua_State *L ); -static int Lua_Scr_GetVector( lua_State *L ); -static int Lua_Cmd_Argv( lua_State *L ); -static int Lua_Cmd_Argc( lua_State *L ); - -// Utility -static int Lua_Printf( lua_State *L ); -static int Lua_DPrintf( lua_State *L ); -static int Lua_GetPluginVersion( lua_State *L ); -static int Lua_GetMilliseconds( lua_State *L ); -static int Lua_Scr_Error( lua_State *L ); -static int Lua_Scr_ParamError( lua_State *L ); -static int Lua_Scr_ObjectError( lua_State *L ); -static int Lua_Error( lua_State *L ); - -// iconv -#ifdef EICONV -static int Lua_iconv_open( lua_State *L ); -static int Lua_iconv_close( lua_State *L ); -static int Lua_iconv( lua_State *L ); -#endif // EICONV void *aligned_malloc( int size, int ALIGN ); char *AllocStub( char *funcName );