rscompat: the "Provoking" uflag was added in 3.0.
[freeciv.git] / server / scripting / script_server.c
blobcd202477ba78cd4a537de36d63ff51e60f41111f
1 /*****************************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 *****************************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <time.h>
22 /* dependencies/lua */
23 #include "lua.h"
24 #include "lualib.h"
26 /* dependencies/tolua */
27 #include "tolua.h"
29 /* utility */
30 #include "astring.h"
31 #include "log.h"
32 #include "mem.h"
33 #include "registry.h"
35 /* common/scriptcore */
36 #include "api_game_specenum.h"
37 #include "luascript.h"
38 #include "luascript_signal.h"
39 #include "luascript_func.h"
40 #include "tolua_common_a_gen.h"
41 #include "tolua_common_z_gen.h"
42 #include "tolua_game_gen.h"
43 #include "tolua_signal_gen.h"
45 /* server */
46 #include "console.h"
47 #include "stdinhand.h"
49 /* server/scripting */
50 #include "tolua_server_gen.h"
52 #include "script_server.h"
54 /*****************************************************************************
55 Lua virtual machine state.
56 *****************************************************************************/
57 static struct fc_lua *fcl_main = NULL;
59 /*****************************************************************************
60 Optional game script code (useful for scenarios).
61 *****************************************************************************/
62 static char *script_server_code = NULL;
64 static void script_server_vars_init(void);
65 static void script_server_vars_free(void);
66 static void script_server_vars_load(struct section_file *file);
67 static void script_server_vars_save(struct section_file *file);
68 static void script_server_code_init(void);
69 static void script_server_code_free(void);
70 static void script_server_code_load(struct section_file *file);
71 static void script_server_code_save(struct section_file *file);
73 static void script_server_signals_create(void);
74 static void script_server_functions_define(void);
76 static void script_server_cmd_reply(struct fc_lua *fcl, enum log_level level,
77 const char *format, ...)
78 fc__attribute((__format__ (__printf__, 3, 4)));
80 /*****************************************************************************
81 Parse and execute the script in str
82 *****************************************************************************/
83 bool script_server_do_string(struct connection *caller, const char *str)
85 int status;
86 struct connection *save_caller;
87 luascript_log_func_t save_output_fct;
89 /* Set a log callback function which allows to send the results of the
90 * command to the clients. */
91 save_caller = fcl_main->caller;
92 save_output_fct = fcl_main->output_fct;
93 fcl_main->output_fct = script_server_cmd_reply;
94 fcl_main->caller = caller;
96 status = luascript_do_string(fcl_main, str, "cmd");
98 /* Reset the changes. */
99 fcl_main->caller = save_caller;
100 fcl_main->output_fct = save_output_fct;
102 return (status == 0);
105 /*****************************************************************************
106 Load script to a buffer
107 *****************************************************************************/
108 bool script_server_load_file(const char *filename, char **buf)
110 FILE *ffile;
111 struct stat stats;
112 char *buffer;
114 fc_stat(filename, &stats);
115 ffile = fc_fopen(filename, "r");
117 if (ffile != NULL) {
118 int len;
120 buffer = fc_malloc(stats.st_size + 1);
122 len = fread(buffer, 1, stats.st_size, ffile);
124 if (len == stats.st_size) {
125 buffer[len] = '\0';
127 *buf = buffer;
129 fclose(ffile);
132 return 1;
135 /*****************************************************************************
136 Parse and execute the script at filename.
137 *****************************************************************************/
138 bool script_server_do_file(struct connection *caller, const char *filename)
140 int status = 1;
141 struct connection *save_caller;
142 luascript_log_func_t save_output_fct;
144 /* Set a log callback function which allows to send the results of the
145 * command to the clients. */
146 save_caller = fcl_main->caller;
147 save_output_fct = fcl_main->output_fct;
148 fcl_main->output_fct = script_server_cmd_reply;
149 fcl_main->caller = caller;
151 status = luascript_do_file(fcl_main, filename);
153 /* Reset the changes. */
154 fcl_main->caller = save_caller;
155 fcl_main->output_fct = save_output_fct;
157 return (status == 0);
160 /*****************************************************************************
161 Mark any, if exported, full userdata representing 'object' in
162 the current script state as 'Nonexistent'.
163 This changes the type of the lua variable.
164 *****************************************************************************/
165 void script_server_remove_exported_object(void *object)
167 luascript_remove_exported_object(fcl_main, object);
170 /*****************************************************************************
171 Initialize the game script variables.
172 *****************************************************************************/
173 static void script_server_vars_init(void)
175 /* nothing */
178 /*****************************************************************************
179 Free the game script variables.
180 *****************************************************************************/
181 static void script_server_vars_free(void)
183 /* nothing */
186 /*****************************************************************************
187 Load the game script variables in file.
188 *****************************************************************************/
189 static void script_server_vars_load(struct section_file *file)
191 luascript_vars_load(fcl_main, file, "script.vars");
194 /*****************************************************************************
195 Save the game script variables to file.
196 *****************************************************************************/
197 static void script_server_vars_save(struct section_file *file)
199 luascript_vars_save(fcl_main, file, "script.vars");
202 /*****************************************************************************
203 Initialize the optional game script code (useful for scenarios).
204 *****************************************************************************/
205 static void script_server_code_init(void)
207 script_server_code = NULL;
210 /*****************************************************************************
211 Free the optional game script code (useful for scenarios).
212 *****************************************************************************/
213 static void script_server_code_free(void)
215 if (script_server_code) {
216 free(script_server_code);
217 script_server_code = NULL;
221 /*****************************************************************************
222 Load the optional game script code from file (useful for scenarios).
223 *****************************************************************************/
224 static void script_server_code_load(struct section_file *file)
226 if (!script_server_code) {
227 const char *code;
228 const char *section = "script.code";
230 code = secfile_lookup_str_default(file, "", "%s", section);
231 script_server_code = fc_strdup(code);
232 luascript_do_string(fcl_main, script_server_code, section);
236 /*****************************************************************************
237 Save the optional game script code to file (useful for scenarios).
238 *****************************************************************************/
239 static void script_server_code_save(struct section_file *file)
241 if (script_server_code) {
242 secfile_insert_str_noescape(file, script_server_code, "script.code");
246 /*****************************************************************************
247 Initialize the scripting state.
248 *****************************************************************************/
249 bool script_server_init(void)
251 if (fcl_main != NULL) {
252 fc_assert_ret_val(fcl_main->state != NULL, FALSE);
254 return TRUE;
257 fcl_main = luascript_new(NULL);
258 if (fcl_main == NULL) {
259 luascript_destroy(fcl_main);
260 fcl_main = NULL;
262 return FALSE;
265 tolua_common_a_open(fcl_main->state);
266 api_specenum_open(fcl_main->state);
267 tolua_game_open(fcl_main->state);
268 tolua_signal_open(fcl_main->state);
269 tolua_server_open(fcl_main->state);
270 tolua_common_z_open(fcl_main->state);
272 script_server_code_init();
273 script_server_vars_init();
275 luascript_signal_init(fcl_main);
276 script_server_signals_create();
278 luascript_func_init(fcl_main);
279 script_server_functions_define();
281 return TRUE;
284 /*****************************************************************************
285 Free the scripting data.
286 *****************************************************************************/
287 void script_server_free(void)
289 if (fcl_main != NULL) {
290 script_server_code_free();
291 script_server_vars_free();
293 /* luascript_signal_free() is called by luascript_destroy(). */
294 luascript_destroy(fcl_main);
295 fcl_main = NULL;
299 /*****************************************************************************
300 Load the scripting state from file.
301 *****************************************************************************/
302 void script_server_state_load(struct section_file *file)
304 script_server_code_load(file);
306 /* Variables must be loaded after code is loaded and executed,
307 * so we restore their saved state properly */
308 script_server_vars_load(file);
311 /*****************************************************************************
312 Save the scripting state to file.
313 *****************************************************************************/
314 void script_server_state_save(struct section_file *file)
316 script_server_code_save(file);
317 script_server_vars_save(file);
320 /*****************************************************************************
321 Invoke all the callback functions attached to a given signal.
322 *****************************************************************************/
323 void script_server_signal_emit(const char *signal_name, int nargs, ...)
325 va_list args;
327 va_start(args, nargs);
328 luascript_signal_emit_valist(fcl_main, signal_name, nargs, args);
329 va_end(args);
332 /*****************************************************************************
333 Declare any new signal types you need here.
334 *****************************************************************************/
335 static void script_server_signals_create(void)
337 signal_deprecator *depr;
339 luascript_signal_create(fcl_main, "turn_begin", 2,
340 API_TYPE_INT, API_TYPE_INT);
342 /* Deprecated form of the 'turn_begin' signal that counts real turns
343 * starting from 0. */
344 depr = luascript_signal_create(fcl_main, "turn_started", 2,
345 API_TYPE_INT, API_TYPE_INT);
346 deprecate_signal(depr, "turn_started", "turn_begin", "3.0");
348 luascript_signal_create(fcl_main, "unit_moved", 3,
349 API_TYPE_UNIT, API_TYPE_TILE, API_TYPE_TILE);
351 /* Includes all newly-built cities. */
352 luascript_signal_create(fcl_main, "city_built", 1,
353 API_TYPE_CITY);
355 luascript_signal_create(fcl_main, "city_size_change", 3,
356 API_TYPE_CITY, API_TYPE_INT, API_TYPE_STRING);
358 /* Deprecated form of the 'city_size_change' signal for the case of growth. */
359 depr = luascript_signal_create(fcl_main, "city_growth", 2,
360 API_TYPE_CITY, API_TYPE_INT);
361 deprecate_signal(depr, "city_growth", "city_size_change", "2.6");
363 /* Only includes units built in cities, for now. */
364 luascript_signal_create(fcl_main, "unit_built", 2,
365 API_TYPE_UNIT, API_TYPE_CITY);
366 luascript_signal_create(fcl_main, "building_built", 2,
367 API_TYPE_BUILDING_TYPE, API_TYPE_CITY);
369 /* These can happen for various reasons; the third argument gives the
370 * reason (a simple string identifier). Example identifiers:
371 * "pop_cost", "need_tech", "need_building", "need_special",
372 * "need_terrain", "need_government", "need_nation", "never",
373 * "unavailable". */
374 luascript_signal_create(fcl_main, "unit_cant_be_built", 3,
375 API_TYPE_UNIT_TYPE, API_TYPE_CITY, API_TYPE_STRING);
376 luascript_signal_create(fcl_main, "building_cant_be_built", 3,
377 API_TYPE_BUILDING_TYPE, API_TYPE_CITY,
378 API_TYPE_STRING);
380 /* The third argument contains the source: "researched", "traded",
381 * "stolen", "hut". */
382 luascript_signal_create(fcl_main, "tech_researched", 3,
383 API_TYPE_TECH_TYPE, API_TYPE_PLAYER,
384 API_TYPE_STRING);
386 /* First player is city owner, second is enemy. */
387 luascript_signal_create(fcl_main, "city_destroyed", 3,
388 API_TYPE_CITY, API_TYPE_PLAYER, API_TYPE_PLAYER);
390 /* First player is former owner, second new one. */
391 luascript_signal_create(fcl_main, "city_transferred", 4,
392 API_TYPE_CITY, API_TYPE_PLAYER, API_TYPE_PLAYER,
393 API_TYPE_STRING);
395 /* Deprecated form of the 'city_transferred' signal for the case of
396 * conquest. */
397 depr = luascript_signal_create(fcl_main, "city_lost", 3,
398 API_TYPE_CITY, API_TYPE_PLAYER, API_TYPE_PLAYER);
399 deprecate_signal(depr, "city_lost", "city_transferred", "2.6");
401 luascript_signal_create(fcl_main, "hut_enter", 1,
402 API_TYPE_UNIT);
404 luascript_signal_create(fcl_main, "unit_lost", 3,
405 API_TYPE_UNIT, API_TYPE_PLAYER, API_TYPE_STRING);
407 luascript_signal_create(fcl_main, "disaster_occurred", 3,
408 API_TYPE_DISASTER, API_TYPE_CITY, API_TYPE_BOOL);
410 /* Deprecated form of the 'disaster_occurred' signal without 'had_internal_effct'
411 * support. */
412 depr = luascript_signal_create(fcl_main, "disaster", 2,
413 API_TYPE_DISASTER, API_TYPE_CITY);
414 deprecate_signal(depr, "disaster", "disaster_occurred", "2.6");
416 luascript_signal_create(fcl_main, "achievement_gained", 3,
417 API_TYPE_ACHIEVEMENT, API_TYPE_PLAYER,
418 API_TYPE_BOOL);
420 luascript_signal_create(fcl_main, "map_generated", 0);
422 luascript_signal_create(fcl_main, "pulse", 0);
424 luascript_signal_create(fcl_main, "action_started_unit_unit", 3,
425 API_TYPE_ACTION,
426 API_TYPE_UNIT, API_TYPE_UNIT);
428 luascript_signal_create(fcl_main, "action_started_unit_units", 3,
429 API_TYPE_ACTION,
430 API_TYPE_UNIT, API_TYPE_TILE);
432 luascript_signal_create(fcl_main, "action_started_unit_city", 3,
433 API_TYPE_ACTION,
434 API_TYPE_UNIT, API_TYPE_CITY);
436 luascript_signal_create(fcl_main, "action_started_unit_tile", 3,
437 API_TYPE_ACTION,
438 API_TYPE_UNIT, API_TYPE_TILE);
440 luascript_signal_create(fcl_main, "action_started_unit_self", 2,
441 API_TYPE_ACTION,
442 API_TYPE_UNIT);
445 /*****************************************************************************
446 Add server callback functions; these must be defined in the lua script
447 '<rulesetdir>/script.lua':
449 respawn_callback (optional):
450 - callback lua function for the respawn command
451 *****************************************************************************/
452 static void script_server_functions_define(void)
454 luascript_func_add(fcl_main, "respawn_callback", FALSE, 1,
455 API_TYPE_PLAYER);
458 /*****************************************************************************
459 Call a lua function.
460 *****************************************************************************/
461 bool script_server_call(const char *func_name, int nargs, ...)
463 bool success;
464 int ret;
466 va_list args;
467 va_start(args, nargs);
468 success = luascript_func_call_valist(fcl_main, func_name, &ret, nargs, args);
469 va_end(args);
471 if (!success) {
472 log_error("Lua function '%s' not defined.", func_name);
473 return FALSE;
474 } else if (!ret) {
475 log_error("Error executing lua function '%s'.", func_name);
476 return FALSE;
479 return TRUE;
482 /*****************************************************************************
483 Send the message via cmd_reply().
484 *****************************************************************************/
485 static void script_server_cmd_reply(struct fc_lua *fcl, enum log_level level,
486 const char *format, ...)
488 va_list args;
489 enum rfc_status rfc_status = C_OK;
490 char buf[1024];
492 va_start(args, format);
493 fc_vsnprintf(buf, sizeof(buf), format, args);
494 va_end(args);
496 switch (level) {
497 case LOG_FATAL:
498 /* Special case - will quit the server. */
499 log_fatal("%s", buf);
500 break;
501 case LOG_ERROR:
502 case LOG_WARN:
503 rfc_status = C_WARNING;
504 break;
505 case LOG_NORMAL:
506 rfc_status = C_COMMENT;
507 break;
508 case LOG_VERBOSE:
509 rfc_status = C_LOG_BASE;
510 break;
511 case LOG_DEBUG:
512 rfc_status = C_DEBUG;
513 break;
516 cmd_reply(CMD_LUA, fcl->caller, rfc_status, "%s", buf);