Freeciv21
Develop your civilization from humble roots to a global empire
script_client.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
3  part of Freeciv21. Freeciv21 is free software: you can redistribute it
4  and/or modify it under the terms of the GNU General Public License as
5  published by the Free Software Foundation, either version 3 of the
6  License, or (at your option) any later version. You should have received
7  a copy of the GNU General Public License along with Freeciv21. If not,
8  see https://www.gnu.org/licenses/.
9  */
10 
11 #include <cstdarg>
12 #include <ctime>
13 
14 extern "C" {
15 /* dependencies/lua */
16 #include "lua.h"
17 
18 /* dependencies/tolua */
19 #include "tolua.h"
20 }
21 // utility
22 #include "log.h"
23 #include "section_file.h"
24 
25 // common
26 #include "featured_text.h"
27 
28 /* common/scriptcore */
29 #include "api_game_specenum.h"
30 #include "luascript.h"
31 
32 #include "tolua_game_gen.h"
33 #include "tolua_signal_gen.h"
34 
35 // client
36 #include "luaconsole_common.h"
37 
38 /* client/luascript */
39 #include "tolua_client_gen.h"
40 
41 #include "script_client.h"
42 
46 static struct fc_lua *main_fcl = nullptr;
47 
51 static char *script_client_code = nullptr;
52 
53 static void script_client_vars_init();
54 static void script_client_vars_free();
55 static void script_client_vars_load(struct section_file *file);
56 static void script_client_vars_save(struct section_file *file);
57 static void script_client_code_init();
58 static void script_client_code_free();
59 static void script_client_code_load(struct section_file *file);
60 static void script_client_code_save(struct section_file *file);
61 
62 static void script_client_output(struct fc_lua *fcl, QtMsgType level,
63  const char *format, ...)
64  fc__attribute((__format__(__printf__, 3, 4)));
65 
66 static void script_client_signal_create();
67 
71 bool script_client_do_string(const char *str)
72 {
73  int status = luascript_do_string(main_fcl, str, "cmd");
74 
75  return (status == 0);
76 }
77 
81 bool script_client_do_file(const char *filename)
82 {
83  int status = luascript_do_file(main_fcl, filename);
84 
85  return (status == 0);
86 }
87 
91 bool script_client_callback_invoke(const char *callback_name, int nargs,
92  enum api_types *parg_types, va_list args)
93 {
94  return luascript_callback_invoke(main_fcl, callback_name, nargs,
95  parg_types, args);
96 }
97 
102 { // nothing
103 }
104 
109 { // nothing
110 }
111 
115 static void script_client_vars_load(struct section_file *file)
116 {
117  luascript_vars_load(main_fcl, file, "script.vars");
118 }
119 
123 static void script_client_vars_save(struct section_file *file)
124 {
125  luascript_vars_save(main_fcl, file, "script.vars");
126 }
127 
131 static void script_client_code_init() { script_client_code = nullptr; }
132 
137 {
138  delete[] script_client_code;
139  script_client_code = nullptr;
140 }
141 
145 static void script_client_code_load(struct section_file *file)
146 {
147  if (!script_client_code) {
148  const char *code;
149  const char *section = "script.code";
150 
151  code = secfile_lookup_str_default(file, "", "%s", section);
154  }
155 }
156 
160 static void script_client_code_save(struct section_file *file)
161 {
162  if (script_client_code) {
163  secfile_insert_str_noescape(file, script_client_code, "script.code");
164  }
165 }
166 
171 {
172  if (main_fcl != nullptr) {
173  fc_assert_ret_val(main_fcl->state != nullptr, false);
174 
175  return true;
176  }
177 
179  if (main_fcl == nullptr) {
180  luascript_destroy(main_fcl); // TODO: main_fcl is nullptr here...
181  main_fcl = nullptr;
182 
183  return false;
184  }
185 
188  tolua_game_open(main_fcl->state);
189  tolua_signal_open(main_fcl->state);
190 
191 #ifdef MESON_BUILD
192  /* Tolua adds 'tolua_' prefix to _open() function names,
193  * and we can't pass it a basename where the original
194  * 'tolua_' has been stripped when generating from meson. */
195  tolua_tolua_client_open(main_fcl->state);
196 #else // MESON_BUILD
197  tolua_client_open(main_fcl->state);
198 #endif // MESON_BUILD
199 
201 
204 
207 
208  return true;
209 }
210 
214 static void script_client_output(struct fc_lua *fcl, QtMsgType level,
215  const char *format, ...)
216 {
217  Q_UNUSED(fcl)
218  va_list args;
219  struct ft_color ftc_luaconsole = ftc_luaconsole_error;
220 
221  switch (level) {
222  case LOG_FATAL:
223  // Special case - will quit the client.
224  {
225  char buf[1024];
226 
227  va_start(args, format);
228  fc_vsnprintf(buf, sizeof(buf), format, args);
229  va_end(args);
230 
231  qFatal("%s", buf);
232  }
233  break;
234  case LOG_ERROR:
235  ftc_luaconsole = ftc_luaconsole_error;
236  break;
237  case LOG_WARN:
238  ftc_luaconsole = ftc_luaconsole_warn;
239  break;
240  case LOG_NORMAL:
241  ftc_luaconsole = ftc_luaconsole_normal;
242  break;
243  case LOG_VERBOSE:
244  ftc_luaconsole = ftc_luaconsole_verbose;
245  break;
246  }
247 
248  va_start(args, format);
249  luaconsole_vprintf(ftc_luaconsole, format, args);
250  va_end(args);
251 }
252 
257 {
258  if (main_fcl != nullptr) {
261 
263 
265  main_fcl = nullptr;
266  }
267 }
268 
273 {
275 
276  /* Variables must be loaded after code is loaded and executed,
277  * so we restore their saved state properly */
279 }
280 
285 {
288 }
289 
293 void script_client_signal_emit(const char *signal_name, ...)
294 {
295  va_list args;
296 
297  va_start(args, signal_name);
298  luascript_signal_emit_valist(main_fcl, signal_name, args);
299  va_end(args);
300 }
301 
306 {
307  luascript_signal_create(main_fcl, "new_tech", 0);
308 }
int api_specenum_open(lua_State *L)
Define the __index function for each exported specenum type.
const struct ft_color ftc_luaconsole_verbose
const struct ft_color ftc_luaconsole_error
const struct ft_color ftc_luaconsole_normal
const struct ft_color ftc_luaconsole_warn
constexpr auto LOG_ERROR
Definition: log.h:23
constexpr auto LOG_VERBOSE
Definition: log.h:26
constexpr auto LOG_NORMAL
Definition: log.h:25
constexpr auto LOG_WARN
Definition: log.h:24
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
constexpr auto LOG_FATAL
Definition: log.h:22
void luaconsole_vprintf(const struct ft_color color, const char *format, va_list args)
Add a line of text to the output ("chatline") window.
bool luascript_callback_invoke(struct fc_lua *fcl, const char *callback_name, int nargs, enum api_types *parg_types, va_list args)
Invoke the 'callback_name' Lua function.
Definition: luascript.cpp:657
int luascript_do_string(struct fc_lua *fcl, const char *str, const char *name)
lua_dostring replacement with error message showing on errors.
Definition: luascript.cpp:618
int luascript_do_file(struct fc_lua *fcl, const char *filename)
Parse and execute the script at filename.
Definition: luascript.cpp:638
void luascript_vars_load(struct fc_lua *fcl, struct section_file *file, const char *section)
Load lua variables from file.
Definition: luascript.cpp:763
void luascript_common_z(lua_State *L)
Runs tolua_common_z.lua.
Definition: luascript.cpp:420
struct fc_lua * luascript_new(luascript_log_func_t output_fct, bool secured_environment)
Initialize the scripting state.
Definition: luascript.cpp:272
void luascript_vars_save(struct fc_lua *fcl, struct section_file *file, const char *section)
Save lua variables to file.
Definition: luascript.cpp:737
void luascript_common_a(lua_State *L)
Runs tolua_common_a.lua.
Definition: luascript.cpp:410
void luascript_destroy(struct fc_lua *fcl)
Free the scripting data.
Definition: luascript.cpp:335
void luascript_signal_free(struct fc_lua *fcl)
Free script signals and callbacks.
void luascript_signal_init(struct fc_lua *fcl)
Initialize script signals and callbacks.
signal_deprecator * luascript_signal_create(struct fc_lua *fcl, const char *signal_name, int nargs,...)
Create a new signal type.
void luascript_signal_emit_valist(struct fc_lua *fcl, const char *signal_name, va_list args)
Invoke all the callback functions attached to a given signal.
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
Lookup a string value in the secfile.
#define secfile_insert_str_noescape(secfile, string, path,...)
Definition: registry_ini.h:170
bool script_client_init()
Initialize the scripting state.
static void static void script_client_signal_create()
Declare any new signal types you need here.
static void script_client_code_load(struct section_file *file)
Load the optional game script code from file (useful for scenarios).
static char * script_client_code
Optional game script code (useful for scenarios).
static void script_client_vars_init()
Initialize the game script variables.
bool script_client_do_file(const char *filename)
Parse and execute the script at filename.
static void script_client_code_free()
Free the optional game script code (useful for scenarios).
void script_client_state_load(struct section_file *file)
Load the scripting state from file.
static void script_client_vars_save(struct section_file *file)
Save the game script variables to file.
static void script_client_vars_load(struct section_file *file)
Load the game script variables in file.
static void script_client_vars_free()
Free the game script variables.
bool script_client_do_string(const char *str)
Parse and execute the script in str.
static void script_client_code_init()
Initialize the optional game script code (useful for scenarios).
void script_client_state_save(struct section_file *file)
Save the scripting state to file.
static void script_client_output(struct fc_lua *fcl, QtMsgType level, const char *format,...) fc__attribute((__format__(__printf__
Ouput a message on the client lua console.
static void script_client_code_save(struct section_file *file)
Save the optional game script code to file (useful for scenarios).
bool script_client_callback_invoke(const char *callback_name, int nargs, enum api_types *parg_types, va_list args)
Invoke the 'callback_name' Lua function.
void script_client_signal_emit(const char *signal_name,...)
Invoke all the callback functions attached to a given signal.
void script_client_free()
Free the scripting data.
static struct fc_lua * main_fcl
Lua virtual machine state.
static void static sol::state * fcl
Lua virtual machine state.
Definition: script_fcdb.cpp:48
struct setting_list * level[OLEVELS_NUM]
Definition: settings.cpp:167
lua_State * state
Definition: luascript.h:38
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition: support.cpp:512
int fc__attribute((nonnull(1, 3)))
#define fc_strdup(str)
Definition: support.h:111