rpg-x2/cgame/cg_lua.c

387 lines
8.6 KiB
C
Raw Normal View History

// g_lua.c
#include "cg_lua.h"
#ifdef G_LUA
2011-12-05 23:36:06 +00:00
#if defined(__linux__) || defined(__WIN32__) || defined(__APPLE__) || 1 /* linux, mingw32, OS X - the 1 is temporary*/
#include <dirent.h> /* Note the MSVC project assumes mingw is installed at C:\MinGW\include */
#else // MSVC
// TODO: I don't care much about MSVC as I user mingw on Windows to compile :P
#endif
lvm_t *lVM[NUM_VMS];
fileHandle_t lualog;
void QDECL LUA_DEBUG(const char *fmt, ...)
{
va_list argptr;
char text[1024];
if(cg_debugLua.integer >= 1)
{
va_start(argptr, fmt);
Com_sprintf(text, sizeof(text), fmt, argptr);
va_end(argptr);
CG_Printf(S_COLOR_YELLOW "LUA DEBUG:" S_COLOR_WHITE " %s\n", text);
}
}
void QDECL LUA_LOG(const char *fmt, ...)
{
va_list argptr;
char buff[1024], string[1024];
int min, tens, sec;
va_start(argptr, fmt);
Com_sprintf(buff, sizeof(buff), fmt, argptr);
va_end(argptr);
if(cg_logLua.integer) {
sec = cg.time / 1000;
min = sec / 60;
sec -= min * 60;
tens = sec / 10;
sec -= tens * 10;
Com_sprintf(string, sizeof(string), "%i:%i%i %s", min, tens, sec, buff);
trap_FS_Write(string, strlen(string), lualog);
}
}
qboolean LoadLuaFile(char *path, int num_vm)
{
int flen = 0;
char *code;
fileHandle_t f;
lvm_t *vm;
flen = trap_FS_FOpenFile(path, &f, FS_READ);
if(flen < 0)
{
LUA_LOG("Lua: can not open file %s\n", path);
CG_Printf(S_COLOR_YELLOW "Lua: can not open file %s\n", path);
trap_FS_FCloseFile(f);
return qfalse;
}
else
{
code = (char *)malloc(flen + 1);
if(!code) return qfalse;
trap_FS_Read(code, flen, f);
*(code + flen) = '\0';
trap_FS_FCloseFile(f);
vm = (lvm_t *) malloc(sizeof(lvm_t));
if(vm == NULL)
{
LUA_LOG("Lua: failed to allocate memory for lua VM\n");
CG_Printf(S_COLOR_YELLOW "Lua: failed to allocate memory for lua VM\n");
return qfalse;
}
memset(vm, 0, sizeof(lvm_t));
vm->id = -1;
Q_strncpyz(vm->filename, path, sizeof(vm->filename));
vm->code = code;
vm->code_size = flen;
vm->error = 0;
if(CG_LuaStartVM(vm) == qfalse)
{
CG_LuaStopVM(vm);
vm = NULL;
return qfalse;
}
else
{
vm->id = num_vm;
lVM[num_vm] = vm;
return qtrue;
}
}
//return qfalse;
}
qboolean CG_LuaInit()
{
2011-12-05 23:36:06 +00:00
#if defined(__linux__) || defined(__WIN32__) || defined(__APPLE__) || 1 /* linux, mingw32, OS X - the 1 is temporary*/
DIR *pdir = NULL;
struct dirent *pent = NULL;
#else // MSVC
#endif
CG_Printf("------- CG_LuaInit -------\n");
2011-12-05 23:36:06 +00:00
#if defined(__linux__) || defined(__WIN32__) || defined(__APPLE__) || 1 /* linux, mingw32, OS X - the 1 is temporary*/
#else // MSVC
#endif
// not much to do for now
if(cg_logLua.integer) {
trap_FS_FOpenFile("./cg_lua.log", &lualog, FS_APPEND);
}
CG_Printf("------- CG_LuaInit Finish -------\n");
return qtrue;
}
qboolean CG_LuaResume(lvm_t *vm, lua_State *T, char *func, int nargs) {
int res = lua_resume(T, nargs);
if(res == LUA_ERRRUN) {
LUA_LOG("Lua: %s error running lua script: %s\n", func, lua_tostring(T, -1));
CG_Printf(S_COLOR_YELLOW "Lua: %s error running lua script: %s\n", func, lua_tostring(T, -1));
lua_pop(T, 1);
vm->error++;
return qfalse;
} else if(res == LUA_ERRMEM) {
LUA_LOG("Lua: memory allocation error #2 ( %s )\n", vm->filename);
vm->error++;
return qfalse;
} else if(res == LUA_ERRERR) {
LUA_LOG("Lua: traceback error ( %s )\n", vm->filename);
CG_Printf(S_COLOR_YELLOW "Lua: traceback error ( %s )\n", vm->filename);
vm->error++;
return qfalse;
}
return qtrue;
}
qboolean CG_LuaCall(lvm_t * vm, char *func, int nargs, int nresults)
{
int res = lua_pcall(vm->L, nargs, nresults, 0);
if(res == LUA_ERRRUN)
{
LUA_LOG("Lua: %s error running lua script: %s\n", func, lua_tostring(vm->L, -1));
CG_Printf(S_COLOR_YELLOW "Lua: %s error running lua script: %s\n", func, lua_tostring(vm->L, -1));
lua_pop(vm->L, 1);
vm->error++;
return qfalse;
}
else if(res == LUA_ERRMEM)
{
LUA_LOG("Lua: memory allocation error #2 ( %s )\n", vm->filename);
vm->error++;
return qfalse;
}
else if(res == LUA_ERRERR)
{
LUA_LOG("Lua: traceback error ( %s )\n", vm->filename);
CG_Printf(S_COLOR_YELLOW "Lua: traceback error ( %s )\n", vm->filename);
vm->error++;
return qfalse;
}
return qtrue;
}
#define SAY_ALL 0
#define SAY_TEAM 1
qboolean CG_LuaGetFunctionT(lua_State *T, char *name)
{
if(T)
{
lua_getglobal(T, name);
if(lua_isfunction(T, -1))
{
return qtrue;
}
else
{
lua_pop(T, 1);
return qfalse;
}
}
return qfalse;
}
qboolean CG_LuaGetFunction(lvm_t * vm, char *name)
{
if(vm->L)
{
lua_getglobal(vm->L, name);
if(lua_isfunction(vm->L, -1))
{
return qtrue;
}
else
{
lua_pop(vm->L, 1);
return qfalse;
}
}
return qfalse;
}
qboolean CG_LuaStartVM(lvm_t * vm)
{
int res = 0;
char homepath[MAX_QPATH], gamepath[MAX_QPATH];
vm->L = luaL_newstate();
if(!vm->L)
{
LUA_LOG("Lua: Lua failed to initialise.\n");
return qfalse;
}
luaL_openlibs(vm->L);
trap_Cvar_VariableStringBuffer("fs_homepath", homepath, sizeof(homepath));
trap_Cvar_VariableStringBuffer("fs_game", gamepath, sizeof(gamepath));
lua_getglobal(vm->L, LUA_LOADLIBNAME);
if(lua_istable(vm->L, -1))
{
lua_pushstring(vm->L, va("%s%s%s%s?.lua;%s%s%s%slualib%slua%s?.lua",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
lua_setfield(vm->L, -2, "path");
lua_pushstring(vm->L, va("%s%s%s%s?.%s;%s%s%s%slualib%sclibs%s?.%s",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
lua_setfield(vm->L, -2, "cpath");
}
lua_pop(vm->L, 1);
Lua_RegisterGlobal(vm->L, "LUA_PATH", va("%s%s%s%s?.lua;%s%s%s%slualib%slua%s?.lua",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
Lua_RegisterGlobal(vm->L, "LUA_CPATH", va("%s%s%s%s?.%s;%s%s%s%slualib%sclibs%s?.%s",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
Lua_RegisterGlobal(vm->L, "LUA_DIRSEP", LUA_DIRSEP);
lua_newtable(vm->L);
Lua_RegConstInteger(vm->L, CS_PLAYERS);
Lua_RegConstInteger(vm->L, EXEC_NOW);
Lua_RegConstInteger(vm->L, EXEC_INSERT);
Lua_RegConstInteger(vm->L, EXEC_APPEND);
Lua_RegConstInteger(vm->L, FS_READ);
Lua_RegConstInteger(vm->L, FS_WRITE);
Lua_RegConstInteger(vm->L, FS_APPEND);
Lua_RegConstInteger(vm->L, FS_APPEND_SYNC);
Lua_RegConstInteger(vm->L, SAY_ALL);
Lua_RegConstInteger(vm->L, SAY_TEAM);
Lua_RegConstString(vm->L, HOSTARCH);
luaopen_base(vm->L);
luaopen_string(vm->L);
luaopen_coroutine(vm->L);
Luaopen_Qmath(vm->L);
Luaopen_Vector(vm->L);
res = luaL_loadbuffer(vm->L, vm->code, vm->code_size, vm->filename);
if(res == LUA_ERRSYNTAX)
{
LUA_LOG("Lua: syntax error during pre-compilation: %s\n", (char *)lua_tostring(vm->L, -1));
CG_Printf(S_COLOR_YELLOW "Lua: syntax error: %s\n", (char *)lua_tostring(vm->L, -1));
lua_pop(vm->L, 1);
vm->error++;
return qfalse;
}
else if(res == LUA_ERRMEM)
{
LUA_LOG("Lua: memory allocation error #1 ( %s )\n", vm->filename);
vm->error++;
return qfalse;
}
if(!CG_LuaCall(vm, "CG_LuaStartVM", 0, 0))
return qfalse;
LUA_LOG("Lua: Loading %s\n", vm->filename);
return qtrue;
}
void CG_LuaStopVM(lvm_t * vm)
{
if(vm == NULL)
return;
if(vm->code != NULL)
{
free(vm->code);
vm->code = NULL;
}
if(vm->id >= 0)
{
if(lVM[vm->id] == vm)
lVM[vm->id] = NULL;
if(!vm->error)
{
LUA_LOG("Lua: Lua module [%s] unloaded.\n", vm->filename);
}
}
free(vm);
}
void CG_LuaShutdown()
{
int i;
lvm_t *vm;
for(i = 0; i < NUM_VMS; i++)
{
vm = lVM[i];
if(vm)
{
CG_LuaStopVM(vm);
}
}
trap_FS_FCloseFile(lualog);
}
void CG_LuaStatus(void)
{
int i, cnt = 0;
for(i = 0; i < NUM_VMS; i++)
if(lVM[i])
cnt++;
if(cnt == 0)
{
CG_Printf("Lua: no scripts loaded.\n");
return;
}
else if(cnt == 1)
{
CG_Printf("Lua: showing lua information ( 1 module loaded )\n");
}
else
{
CG_Printf("Lua: showing lua information ( %d modules loaded )\n", cnt);
}
CG_Printf("%-2s %-24s\n", "VM", "Filename");
CG_Printf("-- ------------------------\n");
for(i = 0; i < NUM_VMS; i++)
{
if(lVM[i])
{
CG_Printf("%2d %-24s\n", lVM[i]->id, lVM[i]->filename);
}
}
CG_Printf("-- ------------------------\n");
}
lvm_t *CG_LuaGetVM(lua_State * L)
{
int i;
for(i = 0; i < NUM_VMS; i++)
if(lVM[i] && lVM[i]->L == L)
return lVM[i];
return NULL;
}
#endif