HLua/dlls/gslua.cpp

262 lines
5.5 KiB
C++
Executable File

/* 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;
}