Crossfire Client, Branches  R11627
script_lua.c
Go to the documentation of this file.
1 const char * const rcsid_common_script_lua_c =
2  "$Id$";
3 /*
4  Crossfire client, a client program for the crossfire program.
5 
6  Copyright (C) 2006-2007 Mark Wedel & Crossfire Development Team
7  This source file also Copyright (C) 2006 Nicolas Weeger
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (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. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 
23  The author can be reached via e-mail to crossfire-devel@real-time.com
24 */
25 
26 #ifndef WIN32
27 #include <ctype.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/wait.h>
32 #include <signal.h>
33 #endif
34 
35 #include <client.h>
36 
37 #ifdef HAVE_LUA
38 /* It seems easier to just comment everything out if we don't have
39  * lua vs trying to play around with it in the makefiles.
40  */
41 
42 #include <external.h>
43 #include <script_lua.h>
44 #include <lua.h>
45 #include <lualib.h>
46 
47 struct script_state
48 {
49  lua_State* state;
50  const char* filename;
51 };
52 
53 #if 0
54 static void *l_alloc (void * /*ud*/, void *ptr, size_t /*osize*/, size_t nsize)
55 {
56  if (nsize == 0) {
57  free(ptr);
58  return NULL;
59  }
60  else
61  return realloc(ptr, nsize);
62 }
63 #endif
64 
65 static const char* l_readerfile(lua_State *L, void *data, size_t *size)
66 {
67  static char buf[4096];
68  FILE* file = (FILE*)data;
69  *size = fread(buf, 1, 4096, file);
70  if ( !*size && ferror(file) )
71  return NULL;
72  if ( !*size && feof(file))
73  return NULL;
74  return buf;
75 }
76 
77 static struct script_state* scripts = NULL;
78 static int script_count = 0;
79 
80 static void update_player(lua_State* lua)
81 {
82  lua_pushstring(lua, "player");
83  lua_gettable(lua, LUA_GLOBALSINDEX);
84  if (!lua_istable(lua, -1))
85  {
86  lua_pop(lua, 1);
87  return;
88  }
89 
90  lua_pushstring(lua, "hp");
91  lua_pushnumber(lua, cpl.stats.hp);
92  lua_settable(lua, -3);
93  lua_pushstring(lua, "gr");
94  lua_pushnumber(lua, cpl.stats.grace);
95  lua_settable(lua, -3);
96  lua_pushstring(lua, "sp");
97  lua_pushnumber(lua, cpl.stats.sp);
98  lua_settable(lua, -3);
99  lua_pushstring(lua, "food");
100  lua_pushnumber(lua, cpl.stats.food);
101  lua_settable(lua, -3);
102 
103  lua_pop(lua, 1);
104 }
105 
106 static void do_item(lua_State* lua, item* it)
107 {
108  lua_newtable(lua);
109  lua_pushstring(lua, "s_name");
110  lua_pushstring(lua, it->s_name);
111  lua_settable(lua, -3);
112  lua_pushstring(lua, "magical");
113  lua_pushnumber(lua, it->magical);
114  lua_settable(lua, -3);
115  lua_pushstring(lua, "cursed");
116  lua_pushnumber(lua, it->cursed);
117  lua_settable(lua, -3);
118  lua_pushstring(lua, "damned");
119  lua_pushnumber(lua, it->damned);
120  lua_settable(lua, -3);
121  lua_pushstring(lua, "unpaid");
122  lua_pushnumber(lua, it->unpaid);
123  lua_settable(lua, -3);
124  lua_pushstring(lua, "locked");
125  lua_pushnumber(lua, it->locked);
126  lua_settable(lua, -3);
127  lua_pushstring(lua, "applied");
128  lua_pushnumber(lua, it->applied);
129  lua_settable(lua, -3);
130  lua_pushstring(lua, "open");
131  lua_pushnumber(lua, it->open);
132  lua_settable(lua, -3);
133 }
134 
135 static void update_inv(lua_State* lua)
136 {
137  item* it;
138  int index = 1;
139  lua_pushstring(lua, "inv");
140  lua_newtable(lua);
141  lua_settable(lua, LUA_GLOBALSINDEX);
142  lua_pushstring(lua, "inv");
143  lua_gettable(lua, LUA_GLOBALSINDEX);
144 
145  for ( it = cpl.ob->inv; it; it = it->next )
146  {
147  lua_pushnumber(lua, index++);
148  do_item(lua, it);
149  lua_settable(lua, -3);
150  }
151  lua_pop(lua, 1);
152 }
153 
154 static void update_ground(lua_State* lua)
155 {
156  item* it;
157  int index = 1;
158  lua_pushstring(lua, "ground");
159  lua_newtable(lua);
160  lua_settable(lua, LUA_GLOBALSINDEX);
161  lua_pushstring(lua, "ground");
162  lua_gettable(lua, LUA_GLOBALSINDEX);
163 
164  for ( it = cpl.below->inv; it; it = it->next )
165  {
166  if ( it->tag == 0 || strlen(it->s_name) == 0 )
167  continue;
168 
169  lua_pushnumber(lua, index++);
170 
171  do_item(lua, it);
172  lua_settable(lua, -3);
173  }
174  lua_pop(lua, 1);
175 }
176 
177 
178 static int lua_draw(lua_State *L) {
179  int n = lua_gettop(L); /* number of arguments */
180  const char* what;
181  if ( n != 1 )
182  {
183  lua_pushstring(L, "draw what?");
184  lua_error(L);
185  }
186  if ( !lua_isstring(L, 1) )
187  {
188  lua_pushstring(L, "expected a string");
189  lua_error(L);
190  }
191 
192  what = lua_tostring(L,1);
193  draw_info(what, NDI_RED);
194 
195  return 0;
196 }
197 
198 static int lua_issue(lua_State *L) {
199  int n = lua_gettop(L); /* number of arguments */
200  const char* what;
201  int repeat, must_send;
202  if ( n != 3 )
203  {
204  lua_pushstring(L, "syntax is cfissue repeat must_send command");
205  lua_error(L);
206  }
207  if ( !lua_isnumber(L, 1) )
208  {
209  lua_pushstring(L, "expected a number");
210  lua_error(L);
211  }
212 
213  if ( !lua_isnumber(L, 2) )
214  {
215  lua_pushstring(L, "expected a number");
216  lua_error(L);
217  }
218 
219  if ( !lua_isstring(L, 3) )
220  {
221  lua_pushstring(L, "expected a number");
222  lua_error(L);
223  }
224 
225  repeat = lua_tonumber(L, 1);
226  must_send = lua_tonumber(L, 2);
227  what = lua_tostring(L,3);
228  send_command(what,repeat,must_send);
229 
230  return 0;
231 }
232 
233 void script_lua_load(const char* name)
234 {
235  lua_State* lua;
236  FILE* file;
237  int load;
238  int index = script_count;
239 
240  file = fopen(name,"r");
241  if ( !file )
242  {
243  draw_info("Invalid file",NDI_RED);
244  return;
245  }
246 
247  lua = lua_open();
248  if ( !lua )
249  {
250  draw_info("Memory allocation error.",NDI_RED);
251  fclose(file);
252  return;
253  }
254  luaopen_base(lua);
255  lua_pop(lua,1);
256  luaopen_table(lua);
257  lua_pop(lua,1);
258 
259  if (( load = lua_load(lua, l_readerfile, (void*)file, name)))
260  {
261  draw_info("Load error!",NDI_RED);
262  if ( load == LUA_ERRSYNTAX )
263  draw_info("Syntax error!",NDI_RED);
264  fclose(file);
265  lua_close(lua);
266  return;
267  }
268  fclose(file);
269 
270  lua_register(lua, "cfdraw", lua_draw);
271  lua_register(lua, "cfissue", lua_issue);
272 
273  lua_pushstring(lua, "player");
274  lua_newtable(lua);
275  lua_settable(lua, LUA_GLOBALSINDEX);
276  update_player(lua);
277  update_inv(lua);
278  update_ground(lua);
279 
280  /* Load functions, init script */
281  if (lua_pcall(lua, 0, 0, 0))
282  {
283  draw_info("Init error!", NDI_RED);
284  fclose(file);
285  lua_close(lua);
286  return;
287  }
288 
289  scripts = realloc(scripts,sizeof(scripts[0])*(script_count+1));
290  script_count++;
291  scripts[index].filename = strdup_local(name);
292  scripts[index].state = lua;
293 
294  /*
295  printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua))));
296  printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua))));
297  lua_pushstring(lua, "init");
298  printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua))));
299  lua_gettable(lua, LUA_GLOBALSINDEX);
300  printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua))));
301  if (lua_isfunction(lua, lua_gettop(lua)))
302  lua_call(lua, 0, 0);
303  lua_pop(lua, 1);
304  */
305 }
306 
307 void script_lua_list(const char* param)
308 {
309  if ( script_count == 0 )
310  {
311  draw_info("No LUA scripts are currently running",NDI_BLACK);
312  }
313  else
314  {
315  int i;
316  char buf[1024];
317 
318  snprintf(buf, sizeof(buf), "%d LUA scripts currently running:",script_count);
319  draw_info(buf,NDI_BLACK);
320  for ( i=0;i<script_count;++i)
321  {
322  snprintf(buf, sizeof(buf), "%d %s",i+1,scripts[i].filename);
323  draw_info(buf,NDI_BLACK);
324  }
325  }
326 }
327 
328 void script_lua_kill(const char* param)
329 {
330  int i;
331  i = atoi(param) - 1;
332  if ( i < 0 || i >= script_count )
333  {
334  draw_info("Invalid script index!", NDI_BLACK);
335  return;
336  }
337  lua_close(scripts[i].state);
338 
339  if ( i < (script_count-1) )
340  {
341  memmove(&scripts[i],&scripts[i+1],sizeof(scripts[i])*(script_count-i-1));
342  }
343 
344  --script_count;
345 }
346 
347 void script_lua_stats()
348 {
349  int script;
350  lua_State* lua;
351  for ( script = 0; script < script_count; script++ )
352  {
353  lua = scripts[script].state;
354  lua_pushstring(lua, "event_stats");
355  lua_gettable(lua, LUA_GLOBALSINDEX);
356  if (lua_isfunction(lua, lua_gettop(lua)))
357  {
358  int luaerror;
359  update_player(lua);
360  update_inv(lua);
361  update_ground(lua);
362  if ( ( luaerror = lua_pcall(lua, 0, 0, 0) ) )
363  {
364  const char* what = lua_tostring(lua, lua_gettop(lua));
365  draw_info(what,NDI_RED);
366  lua_pop(lua,1);
367  }
368  }
369  else
370  lua_pop(lua, 1);
371  }
372 }
373 
374 int script_lua_command(const char* command, const char* param)
375 {
376  int script;
377  lua_State* lua;
378  int ret = 0;
379  for ( script = 0; script < script_count; script++ )
380  {
381  lua = scripts[script].state;
382  lua_pushstring(lua, "event_command");
383  lua_gettable(lua, LUA_GLOBALSINDEX);
384  if (lua_isfunction(lua, lua_gettop(lua)))
385  {
386  int luaerror;
387  update_player(lua);
388  update_inv(lua);
389  update_ground(lua);
390  lua_pushstring(lua, command);
391  lua_pushstring(lua, param ? param : "");
392  if ( ( luaerror = lua_pcall(lua, 2, 1, 0) ) ) {
393  const char* what = lua_tostring(lua, lua_gettop(lua));
394  draw_info(what,NDI_RED);
395  lua_pop(lua,1);
396  }
397  else {
398  ret = lua_tonumber(lua, 1);
399  lua_pop(lua, 1);
400  }
401  }
402  else
403  lua_pop(lua, 1);
404  }
405  return ret;
406 }
407 
408 #endif /* HAVE_LIB_LUA */
char s_name[NAME_LEN]
Definition: item.h:51
void script_lua_list(const char *param)
int script_lua_command(const char *command, const char *param)
sint16 hp
Definition: client.h:216
Definition: script.c:134
void script_lua_kill(const char *param)
item * ob
Definition: client.h:272
sint16 food
Definition: client.h:223
struct item_struct * next
Definition: item.h:46
Stats stats
Definition: client.h:285
const char *const rcsid_common_script_lua_c
Definition: script_lua.c:1
uint16 applied
Definition: item.h:67
#define NDI_RED
Definition: newclient.h:204
sint16 grace
Definition: client.h:220
static struct script * scripts
Definition: script.c:161
uint16 locked
Definition: item.h:66
int send_command(const char *command, int repeat, int must_send)
Definition: player.c:195
item * below
Definition: client.h:273
Client_Player cpl
Definition: client.c:77
sint32 tag
Definition: item.h:54
char * name
Definition: image.c:61
uint16 magical
Definition: item.h:62
uint16 unpaid
Definition: item.h:65
void script_lua_stats(void)
uint16 open
Definition: item.h:68
char * strdup_local(const char *str)
Definition: misc.c:125
sint16 sp
Definition: client.h:218
void draw_info(const char *str, int color)
Definition: gx11.c:1773
void script_lua_load(const char *name)
uint16 damned
Definition: item.h:64
#define NDI_BLACK
Definition: newclient.h:201
struct item_struct * inv
Definition: item.h:49
uint16 cursed
Definition: item.h:63