UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cl_lua.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 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 */
35 lua_State* cl_luastate = nullptr;
36 /* hash map for storing callback references */
38 
39 /* references to SWIG generated lua bindings */
40 extern "C" int luaopen_ufo (lua_State *L);
41 
47 static 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 
87 static 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 
126 void CL_InitLua (void) {
127  /* clean up old state */
128  if (cl_luastate) {
129  CL_ShutdownLua();
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 
151 void CL_ShutdownLua (void) {
152  if (cl_luastate) {
153  HASH_DeleteTable (&cl_callback);
154  lua_close(cl_luastate);
155  cl_luastate = nullptr;
156  }
157 }
158 
162 lua_State* CL_GetLuaState (void) {
163  return cl_luastate;
164 }
165 
171 void 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 
190 void 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 }
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
lua_State * CL_GetLuaState(void)
Returns the lua state for the client side.
Definition: cl_lua.cpp:162
void CL_ShutdownLua(void)
Shutdown the ui-lua interfacing environment.
Definition: cl_lua.cpp:151
lua_State * cl_luastate
Definition: cl_lua.cpp:35
void HASH_DeleteTable(hashTable_s **t)
Deletes a hash table and sets the pointer to NULL.
Definition: hashtable.cpp:351
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition: files.cpp:384
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
hashTable_s * HASH_NewTable(bool ownsKeys, bool ownsValues, bool duplicateOverwrite)
Creates a new hash table and sets it initial capacity.
Definition: hashtable.cpp:287
int luaopen_ufo(lua_State *L)
The hash table structure, contains an array of buckets being indexed by the hash function.
Definition: hashtable.cpp:96
unsigned int key
Definition: cl_input.cpp:68
void CL_InitLua(void)
Initializes the ui-lua interfacing environment.
Definition: cl_lua.cpp:126
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 * HASH_Get(hashTable_s *t, const void *key, int nkey)
Returns the value for a given key.
Definition: hashtable.cpp:467
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
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
void CL_ExecuteCallback(lua_State *L, const char *key)
Calls the registered lua onload callback function.
Definition: cl_lua.cpp:190
uint8_t byte
Definition: ufotypes.h:34
void CL_RegisterCallback(const char *key, LUA_FUNCTION fnc)
Registers a lua callback function with a key.
Definition: cl_lua.cpp:171
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
hashTable_s * cl_callback
Definition: cl_lua.cpp:37