UFO: Alien Invasion
cl_lua.cpp
Go to the documentation of this file.
1
6/*
7Copyright (C) 2002-2022 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 int len = FS_LoadFile (module, &buffer);
61 if (len != -1) {
62 /* found, the contents of the file is now present in buffer */
63 /* load the contents into the lua state */
64 if (luaL_loadbuffer (L, (const char*) buffer, len, module) == 0) {
65 return 1;
66 }
67 else {
68 /* push error string onto the stack */
69 sprintf(errmsg, "custom loader error - cannot load module named [%s]\n", module);
70 lua_pushstring (L, errmsg);
71 }
72 }
73 else {
74 /* push error string onto the stack */
75 sprintf(errmsg, "custom loader error - cannot find module named [%s]\n", module);
76 lua_pushstring (L, errmsg);
77 }
78 /* an error occured, return 0*/
79 return 0;
80}
81
82
87static void CL_InsertModuleLoader (lua_State* L) {
88 /* save stack position */
89 int pos = lua_gettop (L);
90
91 /* push the global table 'package' on the stack */
92 lua_getfield (L, LUA_GLOBALSINDEX, "package");
93 /* using the table 'package', push the 'loaders' field on the stack */
94 lua_getfield (L, -1, "loaders");
95 /* remote the 'package' entry from the stack */
96 lua_remove (L, -2);
97
98 /* the lua stack now only holds the field 'loaders' on top */
99 /* next, determine the number of loaders by counting (lua doesn't have a function for this) */
100 int nloaders = 0;
101 /* lua_next pushes a (key, value) pair using the first entry following the key already on the stack;
102 in this case we start with a nil key so lua_next will return the first (key,value) pair in the table
103 of loaders */
104 lua_pushnil (L);
105 /* if lua_next reaches the end, it returns 0 */
106 while (lua_next (L, -2) != 0) {
107 /* lua_next has pushed a (key,value) pair on the stack; remove the value, keep the key
108 for the next iteration */
109 lua_pop (L, 1);
110 nloaders++;
111 }
112
113 /* now that we have the number of entries in the 'loaders' table, we can add or own loader */
114 lua_pushinteger (L, nloaders + 1);
115 lua_pushcfunction (L, CL_UfoModuleLoader);
116 lua_rawset (L, -3);
117
118 /* restore stack position */
119 lua_settop (L, pos);
120}
121
122
126void CL_InitLua (void) {
127 /* clean up old state */
128 if (cl_luastate) {
130 }
131
132 /* initialize new lua environment dedicated to the ui */
133 cl_luastate = luaL_newstate();
134
135 /* add basic lua libraries to the lua environment */
136 luaL_openlibs(cl_luastate);
137
138 /* insert custom module loader */
140
141 /* add the ufo module -> exposes common functions */
143
144 /* initialize hash table for onload callback mechanism */
145 cl_callback = HASH_NewTable (true, true, true);
146}
147
151void CL_ShutdownLua (void) {
152 if (cl_luastate) {
154 lua_close(cl_luastate);
155 cl_luastate = nullptr;
156 }
157}
158
162lua_State* CL_GetLuaState (void) {
163 return cl_luastate;
164}
165
171void CL_RegisterCallback (const char* key, LUA_FUNCTION fnc) {
172 int regvalue = (int) fnc;
173 /* store regvalue into the list of handlers */
174 int len = strlen (key);
175 if (len > 0) {
176 HASH_Insert (cl_callback, key, len, &regvalue, sizeof(regvalue));
177 }
178 else {
179 Com_Printf("CL_RegisterCallback: lua callback registration error: script name has zero length!\n");
180 }
181}
182
190void CL_ExecuteCallback (lua_State *L, const char* key) {
191 /* look up the handler */
192 void *value = HASH_Get(cl_callback, key, strlen (key));
193 if (value) {
194 int regvalue = * ((int*)value);
195 lua_rawgeti (L, LUA_REGISTRYINDEX, regvalue);
196 if (lua_pcall (L, 0, 0, 0) != 0) {
197 Com_Printf ("lua error: %s\n", lua_tostring(cl_luastate, -1));
198 };
199 }
200}
unsigned int key
Definition: cl_input.cpp:68
lua_State * CL_GetLuaState(void)
Returns the lua state for the client side.
Definition: cl_lua.cpp:162
lua_State * cl_luastate
Definition: cl_lua.cpp:35
void CL_InitLua(void)
Initializes the ui-lua interfacing environment.
Definition: cl_lua.cpp:126
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:171
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:151
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:87
void CL_ExecuteCallback(lua_State *L, const char *key)
Calls the registered lua onload callback function.
Definition: cl_lua.cpp:190
hashTable_s * cl_callback
Definition: cl_lua.cpp:37
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
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.
Definition: hashtable.cpp:467
hashTable_s * HASH_NewTable(bool ownsKeys, bool ownsValues, bool duplicateOverwrite)
Creates a new hash table and sets it initial capacity.
Definition: hashtable.cpp:287
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.
Definition: hashtable.cpp:369
void HASH_DeleteTable(hashTable_s **t)
Deletes a hash table and sets the pointer to NULL.
Definition: hashtable.cpp:351
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