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