Crossfire Client, Branch  R11627
script_lua.c
Go to the documentation of this file.
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 */