/* Copyright (C) 2015 Graham Sanderson, All Rights Reserved */ #include "extdll.h" #include "eiface.h" #include "util.h" #include "game.h" #include "gslua.h" #include "lua/lua.hpp" #define MAX_LUA_LIB_FUNCS 200 #define MAX_LUA_LIB_GLOBALS 200 static void LuaRegisterGlobals(void); static int LUA_PrintConsole(lua_State *L); struct gsLuaRun_s g_gsLuaRun; typedef enum gsLuaType { LTYPE_INT, LTYPE_STRING, LTYPE_FLOAT, LTYPE_FUNC } gsLuaType; typedef union gsLuaGlobal { int i; char const *str; float f; lua_CFunction fn; } gsLuaGlobal; typedef struct gsLuaRegGlobal { const char *name; gsLuaGlobal value; gsLuaType type; } gsLuaRegGlobal; enum { LF_PRINT_CONSOLE = 6 }; static gsLuaRegGlobal gsLib_GLOBALS[] = { { "at_notice", at_notice, LTYPE_INT }, { "at_console", at_console, LTYPE_INT }, { "at_aiconsole", at_aiconsole, LTYPE_INT }, { "at_warning", at_warning, LTYPE_INT }, { "at_error", at_error, LTYPE_INT }, { "at_logged", at_logged, LTYPE_INT }, { "Print_Console", 0, LTYPE_FUNC }, // [marrub] c++ hates unions so this must be 0 and later be given a pointer { NULL } }; // --- Init/quit --- void LuaInit(void) { gsLib_GLOBALS[LF_PRINT_CONSOLE].value.fn = LUA_PrintConsole; g_L = luaL_newstate(); luaopen_base(g_L); luaopen_math(g_L); luaopen_string(g_L); g_bLuaInitialized = TRUE; ALERT(at_console, "[HLua] Lua initialized.\n"); LuaRegisterGlobals(); if(luaL_dostring(g_L, "Print_Console(at_console, \"[HLua::Lua] Initialization success!\")") == TRUE) { LuaError("[HLua] Failed initial Lua test.\n"); } } void LuaQuit(void) { lua_close(g_L); ALERT(at_console, "[HLua] Lua shutdown.\n"); } void LuaReload(void) { LuaQuit(); LuaInit(); } BOOL LuaCheckNull(void const *vpToCheck) { BOOL bReturn; bReturn = (vpToCheck == NULL); if(bReturn) { LuaWarning("[HLua] Null pointer exception!\n"); } return bReturn; } void LuaCall(char *szFuncName) { if(lua_pcall(g_L, 0, 0, 0) != LUA_OK) { LuaWarning("[HLua] Failed to run function %s\nLua: %s\n", szFuncName, lua_tostring(g_L, -1)); } } void LuaCall(char *szFuncName, int iArgs) { if(lua_pcall(g_L, iArgs, 0, 0) != LUA_OK) { LuaWarning("[HLua] Failed to run function %s\nLua: %s\n", szFuncName, lua_tostring(g_L, -1)); } } void LuaSetTable(char *szIndex, float fValue) { lua_pushstring(g_L, szIndex); lua_pushnumber(g_L, fValue); lua_settable(g_L, -3); } void LuaSetTable(int iIndex, float fValue) { lua_pushinteger(g_L, iIndex); lua_pushnumber(g_L, fValue); lua_settable(g_L, -3); } void LuaSetTable(char *szIndex, vec3_t vValue) { lua_pushstring(g_L, szIndex); lua_createtable(g_L, 3, 0); LuaSetTable(0, vValue.x); LuaSetTable(1, vValue.y); LuaSetTable(2, vValue.z); lua_settable(g_L, -3); } void LuaRunScript(char *szFileName) { if(luaL_dofile(g_L, szFileName) == TRUE) { LuaWarning("[HLua] Failed to run script %s\nLua: %s\n", szFileName, lua_tostring(g_L, -1)); } } BOOL LuaGet(char *szName, int iType, BOOL bGetField, BOOL bWarn) { BOOL bReturn; int iGottenType; if(bGetField) { bReturn = ((iGottenType = lua_getfield(g_L, -1, szName)) == iType); } else { bReturn = ((iGottenType = lua_getglobal(g_L, szName)) == iType); } if(bWarn && !bReturn) LuaWarning("[HLua] Incorrect type for %s (expected %d, got %d)\n", szName, iType, iGottenType); return bReturn; } void LuaParseScripts(void) { FILE *fScripts; char szLn[1024]; char szFilenamePulledOutOfMyAss[MAX_PATH]; char szAlsoPulledOutOfMyAss[MAX_PATH]; GET_GAME_DIR(szAlsoPulledOutOfMyAss); strcat(szAlsoPulledOutOfMyAss, "/lua"); CreateDirectory(szAlsoPulledOutOfMyAss, NULL); strcpy(szFilenamePulledOutOfMyAss, szAlsoPulledOutOfMyAss); strcat(szFilenamePulledOutOfMyAss, "/scripts.txt"); fScripts = fopen(szFilenamePulledOutOfMyAss, "r"); ALERT(at_console, "[HLua] Running script table.\n"); if(fScripts == NULL) { LuaError("[HLua] Failed to open lua/scripts.txt!\n"); return; } while(fgets(szLn, 1024, fScripts) != NULL) { BOOL bContinue = FALSE; if(szLn[0] == '\r' || szLn[0] == '\n') continue; char ch = szLn[0], pvch = szLn[0]; for(int i = 1; ch != '\0'; pvch = ch, ch = szLn[i++]) { if(i == 1) continue; if(pvch == '/' && ch == '/') { bContinue = TRUE; break; } if(ch == '\n' || ch == '\r') { szLn[i-1] = '\0'; break; } } if(bContinue == TRUE) continue; char szSeriouslyIHaveALotOfThingsInMyAss[MAX_PATH]; strcpy(szSeriouslyIHaveALotOfThingsInMyAss, szAlsoPulledOutOfMyAss); strcat(szSeriouslyIHaveALotOfThingsInMyAss, szLn); LuaRunScript(szSeriouslyIHaveALotOfThingsInMyAss); } } // --- Binded lua functions and globals --- static void LuaRegisterGlobals(void) { int i; ALERT(at_console, "[HLua] Registering globals.\n"); for(i = 0; i < MAX_LUA_LIB_GLOBALS; i++) { if(gsLib_GLOBALS[i].name == NULL) break; switch(gsLib_GLOBALS[i].type) { case LTYPE_INT: lua_pushnumber(g_L, gsLib_GLOBALS[i].value.i); break; case LTYPE_STRING: lua_pushstring(g_L, gsLib_GLOBALS[i].value.str); break; case LTYPE_FLOAT: lua_pushnumber(g_L, gsLib_GLOBALS[i].value.f); break; case LTYPE_FUNC: lua_pushcfunction(g_L, gsLib_GLOBALS[i].value.fn); break; default: LuaError("[HLua] Invalid type in global initializer!\n"); return; } lua_setglobal(g_L, gsLib_GLOBALS[i].name); } ALERT(at_console, "[HLua] Global registry success, put out %d globals.\n", i); } static int LUA_PrintConsole(lua_State *L) { const char *szToWrite = luaL_checkstring(L, 2); ALERT_TYPE eType = (ALERT_TYPE)luaL_checkinteger(L, 1); LuaCheckNull(szToWrite); ALERT(eType, "%s\n", szToWrite); return 0; }