Crossfire Client, Branch
R11627
|
00001 const char * const rcsid_common_script_lua_c = 00002 "$Id$"; 00003 /* 00004 Crossfire client, a client program for the crossfire program. 00005 00006 Copyright (C) 2006-2007 Mark Wedel & Crossfire Development Team 00007 This source file also Copyright (C) 2006 Nicolas Weeger 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 2 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program; if not, write to the Free Software 00021 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00022 00023 The author can be reached via e-mail to crossfire-devel@real-time.com 00024 */ 00025 00026 #ifndef WIN32 00027 #include <ctype.h> 00028 #include <errno.h> 00029 #include <sys/types.h> 00030 #include <sys/socket.h> 00031 #include <sys/wait.h> 00032 #include <signal.h> 00033 #endif 00034 00035 #include <client.h> 00036 00037 #ifdef HAVE_LUA 00038 /* It seems easier to just comment everything out if we don't have 00039 * lua vs trying to play around with it in the makefiles. 00040 */ 00041 00042 #include <external.h> 00043 #include <script_lua.h> 00044 #include <lua.h> 00045 #include <lualib.h> 00046 00047 struct script_state 00048 { 00049 lua_State* state; 00050 const char* filename; 00051 }; 00052 00053 #if 0 00054 static void *l_alloc (void * /*ud*/, void *ptr, size_t /*osize*/, size_t nsize) 00055 { 00056 if (nsize == 0) { 00057 free(ptr); 00058 return NULL; 00059 } 00060 else 00061 return realloc(ptr, nsize); 00062 } 00063 #endif 00064 00065 static const char* l_readerfile(lua_State *L, void *data, size_t *size) 00066 { 00067 static char buf[4096]; 00068 FILE* file = (FILE*)data; 00069 *size = fread(buf, 1, 4096, file); 00070 if ( !*size && ferror(file) ) 00071 return NULL; 00072 if ( !*size && feof(file)) 00073 return NULL; 00074 return buf; 00075 } 00076 00077 static struct script_state* scripts = NULL; 00078 static int script_count = 0; 00079 00080 static void update_player(lua_State* lua) 00081 { 00082 lua_pushstring(lua, "player"); 00083 lua_gettable(lua, LUA_GLOBALSINDEX); 00084 if (!lua_istable(lua, -1)) 00085 { 00086 lua_pop(lua, 1); 00087 return; 00088 } 00089 00090 lua_pushstring(lua, "hp"); 00091 lua_pushnumber(lua, cpl.stats.hp); 00092 lua_settable(lua, -3); 00093 lua_pushstring(lua, "gr"); 00094 lua_pushnumber(lua, cpl.stats.grace); 00095 lua_settable(lua, -3); 00096 lua_pushstring(lua, "sp"); 00097 lua_pushnumber(lua, cpl.stats.sp); 00098 lua_settable(lua, -3); 00099 lua_pushstring(lua, "food"); 00100 lua_pushnumber(lua, cpl.stats.food); 00101 lua_settable(lua, -3); 00102 00103 lua_pop(lua, 1); 00104 } 00105 00106 static void do_item(lua_State* lua, item* it) 00107 { 00108 lua_newtable(lua); 00109 lua_pushstring(lua, "s_name"); 00110 lua_pushstring(lua, it->s_name); 00111 lua_settable(lua, -3); 00112 lua_pushstring(lua, "magical"); 00113 lua_pushnumber(lua, it->magical); 00114 lua_settable(lua, -3); 00115 lua_pushstring(lua, "cursed"); 00116 lua_pushnumber(lua, it->cursed); 00117 lua_settable(lua, -3); 00118 lua_pushstring(lua, "damned"); 00119 lua_pushnumber(lua, it->damned); 00120 lua_settable(lua, -3); 00121 lua_pushstring(lua, "unpaid"); 00122 lua_pushnumber(lua, it->unpaid); 00123 lua_settable(lua, -3); 00124 lua_pushstring(lua, "locked"); 00125 lua_pushnumber(lua, it->locked); 00126 lua_settable(lua, -3); 00127 lua_pushstring(lua, "applied"); 00128 lua_pushnumber(lua, it->applied); 00129 lua_settable(lua, -3); 00130 lua_pushstring(lua, "open"); 00131 lua_pushnumber(lua, it->open); 00132 lua_settable(lua, -3); 00133 } 00134 00135 static void update_inv(lua_State* lua) 00136 { 00137 item* it; 00138 int index = 1; 00139 lua_pushstring(lua, "inv"); 00140 lua_newtable(lua); 00141 lua_settable(lua, LUA_GLOBALSINDEX); 00142 lua_pushstring(lua, "inv"); 00143 lua_gettable(lua, LUA_GLOBALSINDEX); 00144 00145 for ( it = cpl.ob->inv; it; it = it->next ) 00146 { 00147 lua_pushnumber(lua, index++); 00148 do_item(lua, it); 00149 lua_settable(lua, -3); 00150 } 00151 lua_pop(lua, 1); 00152 } 00153 00154 static void update_ground(lua_State* lua) 00155 { 00156 item* it; 00157 int index = 1; 00158 lua_pushstring(lua, "ground"); 00159 lua_newtable(lua); 00160 lua_settable(lua, LUA_GLOBALSINDEX); 00161 lua_pushstring(lua, "ground"); 00162 lua_gettable(lua, LUA_GLOBALSINDEX); 00163 00164 for ( it = cpl.below->inv; it; it = it->next ) 00165 { 00166 if ( it->tag == 0 || strlen(it->s_name) == 0 ) 00167 continue; 00168 00169 lua_pushnumber(lua, index++); 00170 00171 do_item(lua, it); 00172 lua_settable(lua, -3); 00173 } 00174 lua_pop(lua, 1); 00175 } 00176 00177 00178 static int lua_draw(lua_State *L) { 00179 int n = lua_gettop(L); /* number of arguments */ 00180 const char* what; 00181 if ( n != 1 ) 00182 { 00183 lua_pushstring(L, "draw what?"); 00184 lua_error(L); 00185 } 00186 if ( !lua_isstring(L, 1) ) 00187 { 00188 lua_pushstring(L, "expected a string"); 00189 lua_error(L); 00190 } 00191 00192 what = lua_tostring(L,1); 00193 draw_info(what, NDI_RED); 00194 00195 return 0; 00196 } 00197 00198 static int lua_issue(lua_State *L) { 00199 int n = lua_gettop(L); /* number of arguments */ 00200 const char* what; 00201 int repeat, must_send; 00202 if ( n != 3 ) 00203 { 00204 lua_pushstring(L, "syntax is cfissue repeat must_send command"); 00205 lua_error(L); 00206 } 00207 if ( !lua_isnumber(L, 1) ) 00208 { 00209 lua_pushstring(L, "expected a number"); 00210 lua_error(L); 00211 } 00212 00213 if ( !lua_isnumber(L, 2) ) 00214 { 00215 lua_pushstring(L, "expected a number"); 00216 lua_error(L); 00217 } 00218 00219 if ( !lua_isstring(L, 3) ) 00220 { 00221 lua_pushstring(L, "expected a number"); 00222 lua_error(L); 00223 } 00224 00225 repeat = lua_tonumber(L, 1); 00226 must_send = lua_tonumber(L, 2); 00227 what = lua_tostring(L,3); 00228 send_command(what,repeat,must_send); 00229 00230 return 0; 00231 } 00232 00233 void script_lua_load(const char* name) 00234 { 00235 lua_State* lua; 00236 FILE* file; 00237 int load; 00238 int index = script_count; 00239 00240 file = fopen(name,"r"); 00241 if ( !file ) 00242 { 00243 draw_info("Invalid file",NDI_RED); 00244 return; 00245 } 00246 00247 lua = lua_open(); 00248 if ( !lua ) 00249 { 00250 draw_info("Memory allocation error.",NDI_RED); 00251 fclose(file); 00252 return; 00253 } 00254 luaopen_base(lua); 00255 lua_pop(lua,1); 00256 luaopen_table(lua); 00257 lua_pop(lua,1); 00258 00259 if (( load = lua_load(lua, l_readerfile, (void*)file, name))) 00260 { 00261 draw_info("Load error!",NDI_RED); 00262 if ( load == LUA_ERRSYNTAX ) 00263 draw_info("Syntax error!",NDI_RED); 00264 fclose(file); 00265 lua_close(lua); 00266 return; 00267 } 00268 fclose(file); 00269 00270 lua_register(lua, "cfdraw", lua_draw); 00271 lua_register(lua, "cfissue", lua_issue); 00272 00273 lua_pushstring(lua, "player"); 00274 lua_newtable(lua); 00275 lua_settable(lua, LUA_GLOBALSINDEX); 00276 update_player(lua); 00277 update_inv(lua); 00278 update_ground(lua); 00279 00280 /* Load functions, init script */ 00281 if (lua_pcall(lua, 0, 0, 0)) 00282 { 00283 draw_info("Init error!", NDI_RED); 00284 fclose(file); 00285 lua_close(lua); 00286 return; 00287 } 00288 00289 scripts = realloc(scripts,sizeof(scripts[0])*(script_count+1)); 00290 script_count++; 00291 scripts[index].filename = strdup_local(name); 00292 scripts[index].state = lua; 00293 00294 /* 00295 printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); 00296 printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); 00297 lua_pushstring(lua, "init"); 00298 printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); 00299 lua_gettable(lua, LUA_GLOBALSINDEX); 00300 printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); 00301 if (lua_isfunction(lua, lua_gettop(lua))) 00302 lua_call(lua, 0, 0); 00303 lua_pop(lua, 1); 00304 */ 00305 } 00306 00307 void script_lua_list(const char* param) 00308 { 00309 if ( script_count == 0 ) 00310 { 00311 draw_info("No LUA scripts are currently running",NDI_BLACK); 00312 } 00313 else 00314 { 00315 int i; 00316 char buf[1024]; 00317 00318 snprintf(buf, sizeof(buf), "%d LUA scripts currently running:",script_count); 00319 draw_info(buf,NDI_BLACK); 00320 for ( i=0;i<script_count;++i) 00321 { 00322 snprintf(buf, sizeof(buf), "%d %s",i+1,scripts[i].filename); 00323 draw_info(buf,NDI_BLACK); 00324 } 00325 } 00326 } 00327 00328 void script_lua_kill(const char* param) 00329 { 00330 int i; 00331 i = atoi(param) - 1; 00332 if ( i < 0 || i >= script_count ) 00333 { 00334 draw_info("Invalid script index!", NDI_BLACK); 00335 return; 00336 } 00337 lua_close(scripts[i].state); 00338 00339 if ( i < (script_count-1) ) 00340 { 00341 memmove(&scripts[i],&scripts[i+1],sizeof(scripts[i])*(script_count-i-1)); 00342 } 00343 00344 --script_count; 00345 } 00346 00347 void script_lua_stats() 00348 { 00349 int script; 00350 lua_State* lua; 00351 for ( script = 0; script < script_count; script++ ) 00352 { 00353 lua = scripts[script].state; 00354 lua_pushstring(lua, "event_stats"); 00355 lua_gettable(lua, LUA_GLOBALSINDEX); 00356 if (lua_isfunction(lua, lua_gettop(lua))) 00357 { 00358 int luaerror; 00359 update_player(lua); 00360 update_inv(lua); 00361 update_ground(lua); 00362 if ( ( luaerror = lua_pcall(lua, 0, 0, 0) ) ) 00363 { 00364 const char* what = lua_tostring(lua, lua_gettop(lua)); 00365 draw_info(what,NDI_RED); 00366 lua_pop(lua,1); 00367 } 00368 } 00369 else 00370 lua_pop(lua, 1); 00371 } 00372 } 00373 00374 int script_lua_command(const char* command, const char* param) 00375 { 00376 int script; 00377 lua_State* lua; 00378 int ret = 0; 00379 for ( script = 0; script < script_count; script++ ) 00380 { 00381 lua = scripts[script].state; 00382 lua_pushstring(lua, "event_command"); 00383 lua_gettable(lua, LUA_GLOBALSINDEX); 00384 if (lua_isfunction(lua, lua_gettop(lua))) 00385 { 00386 int luaerror; 00387 update_player(lua); 00388 update_inv(lua); 00389 update_ground(lua); 00390 lua_pushstring(lua, command); 00391 lua_pushstring(lua, param ? param : ""); 00392 if ( ( luaerror = lua_pcall(lua, 2, 1, 0) ) ) { 00393 const char* what = lua_tostring(lua, lua_gettop(lua)); 00394 draw_info(what,NDI_RED); 00395 lua_pop(lua,1); 00396 } 00397 else { 00398 ret = lua_tonumber(lua, 1); 00399 lua_pop(lua, 1); 00400 } 00401 } 00402 else 00403 lua_pop(lua, 1); 00404 } 00405 return ret; 00406 } 00407 00408 #endif /* HAVE_LIB_LUA */