/** G_LuaHook_EntitySpawn * <function>( entitynum ); */ qboolean G_LuaHook_EntitySpawn(char *function, int entity) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm && (vm->type == VMT_MAPSCRIPT)) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, function)) continue; // Arguments lua_pushinteger(vm->L, entity); // Call if(!G_LuaCall(vm, function, 1, 0)) { //G_LuaStopVM(vm); continue; } // Return values } } return qfalse; }
/** G_LuaHook_SetPlayerSkill * et_SetPlayerSkill( cno, skill ) callback */ qboolean G_LuaHook_SetPlayerSkill(int cno, skillType_t skill) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_SetPlayerSkill")) continue; // Arguments lua_pushinteger(vm->L, cno); lua_pushinteger(vm->L, (int)skill); // Call if(!G_LuaCall(vm, "et_SetPlayerSkill", 2, 1)) { //G_LuaStopVM(vm); continue; } // Return values if(lua_isnumber(vm->L, -1)) { if(lua_tointeger(vm->L, -1) == -1) { return qtrue; } } } } return qfalse; }
/** G_LuaHook_Print * et_Print( text ) callback */ void G_LuaHook_Print(char *text) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_Print")) continue; // Arguments lua_pushstring(vm->L, text); // Call if(!G_LuaCall(vm, "et_Print", 1, 0)) { //G_LuaStopVM(vm); continue; } // Return values } } }
/** G_LuaHook_Obituary * (customObit) = et_Obituary( victim, killer, meansOfDeath ) callback */ qboolean G_LuaHook_Obituary(int victim, int killer, int meansOfDeath, char *customObit) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_Obituary")) continue; // Arguments lua_pushinteger(vm->L, victim); lua_pushinteger(vm->L, killer); lua_pushinteger(vm->L, meansOfDeath); // Call if(!G_LuaCall(vm, "et_Obituary", 3, 1)) { //G_LuaStopVM(vm); continue; } // Return values if(lua_isstring(vm->L, -1)) { Q_strncpyz(customObit, lua_tostring(vm->L, -1), MAX_STRING_CHARS); return qtrue; } } } return qfalse; }
void LuaHook_G_ClientPrint(char *text, int entnum) { int i; lvm_t *vm; gentity_t *ent; if(!entnum) return; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0) continue; if(!G_LuaGetFunction(vm, "GClientPrint")) continue; lua_pushstring(vm->L, text); ent = &g_entities[entnum]; if(!ent || !ent->inuse) lua_pushnil(vm->L); else Lua_PushEntity(vm->L, ent); if(!G_LuaCall(vm, "GClientPrint", 2, 0)) continue; } } }
/** G_LuaStopVM( vm ) * Stops one virtual machine, and calls its et_Quit callback. */ void G_LuaStopVM(lua_vm_t * vm) { if(vm == NULL) return; if(vm->code != NULL) { free(vm->code); vm->code = NULL; } if(vm->L) { if(G_LuaGetNamedFunction(vm, "et_Quit")) G_LuaCall(vm, "et_Quit", 0, 0); lua_close(vm->L); vm->L = NULL; } if(vm->id >= 0) { if(lVM[vm->id] == vm) lVM[vm->id] = NULL; if(!vm->err) { LOG("Lua API: Lua module [%s] [%s] unloaded.\n", vm->file_name, vm->mod_signature); } } free(vm); }
//xreal most of the params gone. void G_LuaHook_ClientSpawn(int clientNum) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_ClientSpawn")) continue; // Arguments lua_pushinteger(vm->L, clientNum); /* //xreal args gone. lua_pushinteger(vm->L, (int)revived); lua_pushinteger(vm->L, (int)teamChange); lua_pushinteger(vm->L, (int)restoreHealth); */ // Call if(!G_LuaCall(vm, "et_ClientSpawn", 1, 0)) { //G_LuaStopVM(vm); continue; } // Return values } } }
/** G_LuaHook_ConsoleCommand * intercepted = et_ConsoleCommand( command ) callback */ qboolean G_LuaHook_ConsoleCommand(char *command) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_ConsoleCommand")) continue; // Arguments lua_pushstring(vm->L, command); // Call if(!G_LuaCall(vm, "et_ConsoleCommand", 1, 1)) { //G_LuaStopVM(vm); continue; } // Return values if(lua_isnumber(vm->L, -1)) { if(lua_tointeger(vm->L, -1) == 1) { return qtrue; } } } } return qfalse; }
/** void G_LuaHook_ClientUserinfoChanged(int clientNum); * et_ClientUserinfoChanged( clientNum ) callback */ void G_LuaHook_ClientUserinfoChanged(int clientNum) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_ClientUserinfoChanged")) continue; // Arguments lua_pushinteger(vm->L, clientNum); // Call if(!G_LuaCall(vm, "et_ClientUserinfoChanged", 1, 0)) { //G_LuaStopVM(vm); continue; } // Return values } } }
/** G_LuaHook_ClientConnect * rejectreason = et_ClientConnect( clientNum, firstTime, isBot ) callback */ qboolean G_LuaHook_ClientConnect(int clientNum, qboolean firstTime, qboolean isBot, char *reason) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_ClientConnect")) continue; // Arguments lua_pushinteger(vm->L, clientNum); lua_pushinteger(vm->L, (int)firstTime); lua_pushinteger(vm->L, (int)isBot); // Call if(!G_LuaCall(vm, "et_ClientConnect", 3, 1)) { //G_LuaStopVM(vm); continue; } // Return values if(lua_isstring(vm->L, -1)) { Q_strncpyz(reason, lua_tostring(vm->L, -1), MAX_STRING_CHARS); return qtrue; } } } return qfalse; }
/** G_LuaHook_RunFrame * et_RunFrame( levelTime ) callback */ void G_LuaHook_RunFrame(int levelTime) { int i; lua_vm_t *vm; for(i = 0; i < LUA_NUM_VM; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 /*|| vm->err */ ) continue; if(!G_LuaGetNamedFunction(vm, "et_RunFrame")) continue; // Arguments lua_pushinteger(vm->L, levelTime); // Call if(!G_LuaCall(vm, "et_RunFrame", 1, 0)) { //G_LuaStopVM(vm); continue; } // Return values } } }
qboolean LuaHook_G_EntityTrigger(char *function, int entnum, int othernum) { int i; lvm_t *vm; lua_State *t; gentity_t *ent; gentity_t *other; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0) continue; t = lua_newthread(vm->L); if(!t) { if(!G_LuaGetFunction(vm, function)) continue; ent = &g_entities[entnum]; if(!ent || !ent->inuse) lua_pushnil(vm->L); else Lua_PushEntity(vm->L, ent); other = &g_entities[othernum]; if(!other || !other->inuse) lua_pushnil(vm->L); else Lua_PushEntity(vm->L, other); if(!G_LuaCall(vm, function, 2, 0)) { continue; } } else { if(!G_LuaGetFunctionT(t, function)) continue; ent = &g_entities[entnum]; if(!ent || !ent->inuse) lua_pushnil(t); else Lua_PushEntity(t, ent); other = &g_entities[othernum]; if(!other || !other->inuse) lua_pushnil(t); else Lua_PushEntity(t, other); if(!G_LuaResume(vm, t, function, 2)) continue; } } } return qfalse; }
void LuaHook_G_Print(char *text) { int i; lvm_t *vm; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 ) continue; if(!G_LuaGetFunction(vm, "GPrint")) continue; lua_pushstring(vm->L, text); if(!G_LuaCall(vm, "GPrint", 1, 0)) { continue; } } } }
void LuaHook_G_RunFrame(int levelTime) { int i; lvm_t *vm; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 ) continue; if(!G_LuaGetFunction(vm, "RunFrame")) continue; lua_pushinteger(vm->L, levelTime); if(!G_LuaCall(vm, "RunFrame", 1, 0)) { continue; } } } }
void LuaHook_G_Shutdown(int restart) { int i; lvm_t *vm; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 ) continue; if(!G_LuaGetFunction(vm, "ShutdownGame")) continue; lua_pushinteger(vm->L, restart); if(!G_LuaCall(vm, "ShutdownGame", 1, 0)) { continue; } } } }
qboolean LuaHook_G_EntityReachedAngular(char *function, int entnum) { int i; lvm_t *vm; lua_State *t; gentity_t *ent; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0) continue; t = lua_newthread(vm->L); if(!t) { if(!G_LuaGetFunction(vm, function)) continue; ent = &g_entities[entnum]; if(!ent || !ent->inuse) lua_pushnil(vm->L); else Lua_PushEntity(vm->L, ent); if(!G_LuaCall(vm, function, 1, 0)) continue; } else { if(!G_LuaGetFunctionT(t, function)) continue; ent = &g_entities[entnum]; if(!ent || !ent->inuse) lua_pushnil(t); else Lua_PushEntity(t, ent); if(!G_LuaResume(vm, t, function, 1)) continue; } } } return qfalse; }
void LuaHook_G_InitGame(int levelTime, int randomSeed, int restart) { int i; lvm_t *vm; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0 ) continue; if(!G_LuaGetFunction(vm, "InitGame")) continue; lua_pushinteger(vm->L, levelTime); lua_pushinteger(vm->L, randomSeed); lua_pushinteger(vm->L, restart); if(!G_LuaCall(vm, "InitGame", 3, 0)) { continue; } } } }
qboolean LuaHook_G_EntityDie(char *function, int entnum, int inflictornum, int attackernum, int dmg, int mod) { int i; lvm_t *vm; lua_State *t; gentity_t *ent; gentity_t *inflictor; gentity_t *attacker; for(i = 0; i < NUM_VMS; i++) { vm = lVM[i]; if(vm) { if(vm->id < 0) continue; t = lua_newthread(vm->L); if(!t) { if(!G_LuaGetFunction(vm, function)) continue; ent = &g_entities[entnum]; if(!ent || !ent->inuse) lua_pushnil(vm->L); else Lua_PushEntity(vm->L, ent); inflictor = &g_entities[inflictornum]; if(!inflictor || !inflictor->inuse) lua_pushnil(vm->L); else Lua_PushEntity(vm->L, inflictor); attacker = &g_entities[attackernum]; if(!attacker || !attacker->inuse) lua_pushnil(vm->L); else Lua_PushEntity(vm->L, attacker); lua_pushinteger(vm->L, dmg); lua_pushinteger(vm->L, mod); if(!G_LuaCall(vm, function, 5, 0)) { continue; } } else { if(!G_LuaGetFunctionT(t, function)) continue; ent = &g_entities[entnum]; if(!ent || !ent->inuse) lua_pushnil(t); else Lua_PushEntity(t, ent); inflictor = &g_entities[inflictornum]; if(!inflictor || !inflictor->inuse) lua_pushnil(t); else Lua_PushEntity(t, inflictor); attacker = &g_entities[attackernum]; if(!attacker || !attacker->inuse) lua_pushnil(t); else Lua_PushEntity(t, attacker); lua_pushinteger(t, dmg); lua_pushinteger(t, mod); if(!G_LuaResume(vm, t, function, 5)) continue; } } } return qfalse; }
qboolean G_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_Game(vm->L); Luaopen_Qmath(vm->L); Luaopen_Mover(vm->L); Luaopen_Vector(vm->L); Luaopen_Entity(vm->L); Luaopen_Cinematic(vm->L); Luaopen_Sound(vm->L); Luaopen_Trace(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)); G_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(!G_LuaCall(vm, "G_LuaStartVM", 0, 0)) return qfalse; LUA_LOG("Lua: Loading %s\n", vm->filename); return qtrue; }
/** G_LuaStartVM( vm ) * Starts one individual virtual machine. */ qboolean G_LuaStartVM(lua_vm_t * vm) { int res = 0; char homepath[MAX_QPATH], gamepath[MAX_QPATH]; // Open a new lua state vm->L = luaL_newstate(); if(!vm->L) { LOG("Lua API: Lua failed to initialise.\n"); return qfalse; } // Initialise the lua state luaL_openlibs(vm->L); // set LUA_PATH and LUA_CPATH // TODO: add "fs_basepath/fs_game/?.lua;" to LUA_PATH // and LUA_CPATH for linux machines 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); // register globals 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); // register predefined constants 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); //xreal //lua_regconstinteger(vm->L, SAY_BUDDY); //lua_regconstinteger(vm->L, SAY_TEAMNL); lua_regconststring(vm->L, HOSTARCH); lua_setglobal(vm->L, "et"); // register functions luaopen_et(vm->L); luaopen_game(vm->L); luaopen_qmath(vm->L); luaopen_mover(vm->L); luaopen_vector(vm->L); // Load the code res = luaL_loadbuffer(vm->L, vm->code, vm->code_size, vm->file_name); if(res == LUA_ERRSYNTAX) { LOG("Lua API: syntax error during pre-compilation: %s\n", lua_tostring(vm->L, -1)); lua_pop(vm->L, 1); vm->err++; return qfalse; } else if(res == LUA_ERRMEM) { LOG("Lua API: memory allocation error #1 ( %s )\n", vm->file_name); vm->err++; return qfalse; } // Execute the code if(!G_LuaCall(vm, "G_LuaStartVM", 0, 0)) return qfalse; LOG("Lua API: Loading %s\n", vm->file_name); return qtrue; }