UFO: Alien Invasion
Loading...
Searching...
No Matches
cl_lua.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "cl_lua.h"
27
28#include "../../shared/cxx.h"
29#include "../../shared/defines.h"
30#include "../../shared/shared.h"
31#include "../../common/hashtable.h"
32#include "../../common/filesys.h"
33
34/* global lua state for ui-lua interfacing */
35lua_State* cl_luastate = nullptr;
36/* hash map for storing callback references */
38
39/* references to SWIG generated lua bindings */
40extern "C" int luaopen_ufo (lua_State *L);
41
47static int CL_UfoModuleLoader (lua_State* L) {
48 /* this function is called by lua with the module name on the stack */
49 char module[256];
50 char errmsg[512];
51 const char* name = lua_tostring(L, -1);
52 byte* buffer;
53
54 /* initialize */
55 memset(module, 0, sizeof(module));
56 Com_sprintf(module, sizeof(module), "ufos/ui/%s", name);
57 memset(errmsg, 0, sizeof(errmsg));
58
59 /* find the module using ufo's filesystem */
60 Com_Printf("Lua custom-loading module: %s\n", name);
61 int len = FS_LoadFile(module, &buffer);
62 if (len != -1) {
63 /* found, the contents of the file is now present in buffer */
64 /* load the contents into the lua state */
65 if (luaL_loadbuffer(L, (const char*) buffer, len, module) == 0) {
66 return 1;
67 } else {
68 /* push error string onto the stack */
69 sprintf(errmsg, "Lua custom-loader error: cannot load module named [%s]:\n\t%s\n", module, lua_tostring(L, -1));
70 Com_Printf("%s", errmsg);
71 lua_pushstring(L, errmsg);
72 }
73 } else {
74 /* push error string onto the stack */
75 sprintf(errmsg, "Lua custom-loader error: cannot find module named [%s]\n", module);
76 Com_Printf("%s", errmsg);
77 lua_pushstring(L, errmsg);
78 }
79 /* an error occured, return 0*/
80 return 0;
81}
82
83
88static void CL_InsertModuleLoader (lua_State* L) {
89 /* save stack position */
90 int pos = lua_gettop(L);
91
92 lua_getglobal(L, "package");
93 if (lua_isnil(L, -1))
94 luaL_error(L, "Can't register searcher: package table does not exist.");
95 lua_getfield(L, -1, "searchers");
96 if (lua_isnil(L, -1))
97 luaL_error(L, "Can't register searcher: package.searchers table does not exist.");
98
99 /* remote the 'package' entry from the stack */
100 lua_remove(L, -2);
101
102 /* the lua stack now only holds the field 'loaders' on top */
103 /* next, determine the number of loaders by counting (lua doesn't have a function for this) */
104 int nloaders = 0;
105 /* lua_next pushes a (key, value) pair using the first entry following the key already on the stack;
106 in this case we start with a nil key so lua_next will return the first (key,value) pair in the table
107 of loaders */
108 lua_pushnil(L);
109 /* if lua_next reaches the end, it returns 0 */
110 while (lua_next(L, -2) != 0) {
111 /* lua_next has pushed a (key,value) pair on the stack; remove the value, keep the key
112 for the next iteration */
113 lua_pop(L, 1);
114 nloaders++;
115 }
116
117 /* now that we have the number of entries in the 'loaders' table, we can add our own loader */
118 lua_pushinteger(L, nloaders + 1);
119 lua_pushcfunction(L, CL_UfoModuleLoader);
120 lua_rawset(L, -3);
121
122 /* restore stack position */
123 lua_settop(L, pos);
124}
125
126
130void CL_InitLua (void) {
131 /* clean up old state */
132 if (cl_luastate) {
134 }
135
136 /* initialize new lua environment dedicated to the ui */
137 cl_luastate = luaL_newstate();
138
139 /* add basic lua libraries to the lua environment */
140 luaL_openlibs(cl_luastate);
141
142 /* insert custom module loader */
144
145 /* add the ufo module -> exposes common functions */
147
148 /* initialize hash table for onload callback mechanism */
149 cl_callback = HASH_NewTable(true, true, true);
150}
151
155void CL_ShutdownLua (void) {
156 if (cl_luastate) {
158 lua_close(cl_luastate);
159 cl_luastate = nullptr;
160 }
161}
162
166lua_State* CL_GetLuaState (void) {
167 return cl_luastate;
168}
169
175void CL_RegisterCallback (const char* key, LUA_FUNCTION fnc) {
176 int regvalue = (int) fnc;
177 /* store regvalue into the list of handlers */
178 int len = strlen(key);
179 if (len > 0) {
180 HASH_Insert(cl_callback, key, len, &regvalue, sizeof(regvalue));
181 }
182 else {
183 Com_Printf("CL_RegisterCallback: lua callback registration error: script name has zero length!\n");
184 }
185}
186
194void CL_ExecuteCallback (lua_State *L, const char* key) {
195 /* look up the handler */
196 void *value = HASH_Get(cl_callback, key, strlen (key));
197 if (value) {
198 int regvalue = * ((int*)value);
199 lua_rawgeti(L, LUA_REGISTRYINDEX, regvalue);
200 if (lua_pcall(L, 0, 0, 0) != 0) {
201 Com_Printf("lua error: %s\n", lua_tostring(cl_luastate, -1));
202 };
203 }
204}
unsigned int key
Definition cl_input.cpp:64
lua_State * CL_GetLuaState(void)
Returns the lua state for the client side.
Definition cl_lua.cpp:166
lua_State * cl_luastate
Definition cl_lua.cpp:35
void CL_InitLua(void)
Initializes the ui-lua interfacing environment.
Definition cl_lua.cpp:130
int luaopen_ufo(lua_State *L)
void CL_RegisterCallback(const char *key, LUA_FUNCTION fnc)
Registers a lua callback function with a key.
Definition cl_lua.cpp:175
static int CL_UfoModuleLoader(lua_State *L)
Loader that enables the lua files to access .ufo files through the ufo filesystem.
Definition cl_lua.cpp:47
void CL_ShutdownLua(void)
Shutdown the ui-lua interfacing environment.
Definition cl_lua.cpp:155
static void CL_InsertModuleLoader(lua_State *L)
This function adds loader to the lua table of module loaders that enables lua to access the ufo files...
Definition cl_lua.cpp:88
void CL_ExecuteCallback(lua_State *L, const char *key)
Calls the registered lua onload callback function.
Definition cl_lua.cpp:194
hashTable_s * cl_callback
Definition cl_lua.cpp:37
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void * HASH_Get(hashTable_s *t, const void *key, int nkey)
Returns the value for a given key.
hashTable_s * HASH_NewTable(bool ownsKeys, bool ownsValues, bool duplicateOverwrite)
Creates a new hash table and sets it initial capacity.
bool HASH_Insert(hashTable_s *t, const void *key, int nkey, const void *value, int nvalue)
Inserts a new value with given key into the hash table.
void HASH_DeleteTable(hashTable_s **t)
Deletes a hash table and sets the pointer to NULL.
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
QGL_EXTERN GLuint GLchar GLuint * len
Definition r_gl.h:99
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
int LUA_FUNCTION
callback signatures for functions defined in Lua
Definition scripts_lua.h:45
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
The hash table structure, contains an array of buckets being indexed by the hash function.
Definition hashtable.cpp:96