The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
lua_api.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2016 by Guillaume Melquiond <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "lua_api.hpp"
16 #include "lua_types.hpp"
17 
18 #include "lua_jailbreak_exception.hpp" // for tlua_jailbreak_exception
19 
20 #include "chat_events.hpp" // for chat_handler, etc
21 #include "config.hpp"
22 #include "display_chat_manager.hpp"
23 #include "game_display.hpp"
24 #include "log.hpp"
25 #include "map/location.hpp" // for map_location
26 #include "resources.hpp"
27 #include "scripting/lua_common.hpp"
28 #include "tstring.hpp"
29 #include "units/unit.hpp"
30 #include "units/map.hpp"
31 #include "variable.hpp"
32 
33 #include <boost/variant/static_visitor.hpp>
34 #include <map> // for map<>::key_type
35 #include <new> // for operator new
36 #include <ostream> // for operator<<, basic_ostream, etc
37 #include <utility> // for pair
38 
39 #include <string>
40 
41 #include "lua/lauxlib.h"
42 #include "lua/lua.h" // for lua_State, lua_settop, etc
43 
44 static lg::log_domain log_scripting_lua("scripting/lua");
45 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
46 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
47 
48 void chat_message(std::string const &caption, std::string const &msg)
49 {
50  if (!resources::screen) return;
51  resources::screen->get_chat_manager().add_chat_message(time(nullptr), caption, 0, msg,
53 }
54 
55 #ifdef _MSC_VER
56 #pragma warning (push)
57 #pragma warning (disable: 4706)
58 #endif
60  , int nArgs, int nRets, bool allow_wml_error)
61 {
62  // Load the error handler before the function and its arguments.
64  , executeKey);
65 
67  lua_insert(L, -2 - nArgs);
68 
69  int error_handler_index = lua_gettop(L) - nArgs - 1;
70 
71  // Call the function.
72  int res = lua_pcall(L, nArgs, nRets, -2 - nArgs);
74 
75  if (res)
76  {
77  /*
78  * When an exception is thrown which doesn't derive from
79  * std::exception m will be nullptr pointer.
80  */
81  char const *m = lua_tostring(L, -1);
82  if(m) {
83  if (allow_wml_error && strncmp(m, "~wml:", 5) == 0) {
84  m += 5;
85  char const *e = strstr(m, "stack traceback");
86  lg::wml_error() << std::string(m, e ? e - m : strlen(m));
87  } else if (allow_wml_error && strncmp(m, "~lua:", 5) == 0) {
88  m += 5;
89  char const *e = nullptr, *em = m;
90  while (em[0] && ((em = strstr(em + 1, "stack traceback"))))
91 #ifdef _MSC_VER
92 #pragma warning (pop)
93 #endif
94  e = em;
95  chat_message("Lua error", std::string(m, e ? e - m : strlen(m)));
96  } else {
97  ERR_LUA << m << '\n';
98  chat_message("Lua error", m);
99  }
100  } else {
101  chat_message("Lua caught unknown exception", "");
102  }
103  lua_pop(L, 2);
104  return false;
105  }
106 
107  // Remove the error handler.
108  lua_remove(L, error_handler_index);
109 
110  return true;
111 }
112 
114 {
115 }
116 
118 {
119  if (ptr) return ptr.get();
120  if (c_ptr) return c_ptr;
121  if (side) {
122  return (*resources::teams)[side - 1].recall_list().find_if_matches_underlying_id(uid).get();
123  }
125  if (!ui.valid()) return nullptr;
126  return ui.get_shared_ptr().get(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
127 }
129 {
130  if (ptr) return ptr;
131  if (side) {
132  return (*resources::teams)[side - 1].recall_list().find_if_matches_underlying_id(uid);
133  }
135  if (!ui.valid()) return unit_ptr();
136  return ui.get_shared_ptr(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
137 }
138 
139 // Having this function here not only simplifies other code, it allows us to move
140 // pointers around from one structure to another.
141 // This makes bare pointer->map in particular about 2 orders of magnitude faster,
142 // as benchmarked from Lua code.
144 {
145  if (ptr) {
146  ptr->set_location(loc);
147  resources::units->erase(loc);
148  std::pair<unit_map::unit_iterator, bool> res = resources::units->insert(ptr);
149  if (res.second) {
150  ptr.reset();
151  uid = res.first->underlying_id();
152  } else {
153  ERR_LUA << "Could not move unit " << ptr->underlying_id() << " onto map location " << loc << '\n';
154  return false;
155  }
156  } else if (side) { // recall list
157  unit_ptr it = (*resources::teams)[side - 1].recall_list().extract_if_matches_underlying_id(uid);
158  if (it) {
159  side = 0;
160  // uid may be changed by unit_map on insertion
161  uid = resources::units->replace(loc, *it).first->underlying_id();
162  } else {
163  ERR_LUA << "Could not find unit " << uid << " on recall list of side " << side << '\n';
164  return false;
165  }
166  } else { // on map
168  if (ui != resources::units->end()) {
169  map_location from = ui->get_location();
170  if (from != loc) { // This check is redundant in current usage
171  resources::units->erase(loc);
172  resources::units->move(from, loc);
173  }
174  // No need to change our contents
175  } else {
176  ERR_LUA << "Could not find unit " << uid << " on the map" << std::endl;
177  return false;
178  }
179  }
180  return true;
181 }
182 
183 unit* luaW_tounit(lua_State *L, int index, bool only_on_map)
184 {
185  if (!luaW_hasmetatable(L, index, getunitKey)) return nullptr;
186  lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, index));
187  if (only_on_map && !lu->on_map()) return nullptr;
188  return lu->get();
189 }
190 
191 unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map)
192 {
193  if (!luaW_hasmetatable(L, index, getunitKey)) return unit_ptr();
194  lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, index));
195  if (only_on_map && !lu->on_map()) return unit_ptr();
196  return lu->get_shared();
197 }
198 
199 unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map)
200 {
201  unit_ptr u = luaW_tounit(L, index, only_on_map);
202  if (!u) luaL_typerror(L, index, "unit");
203  return u;
204 }
205 unit& luaW_checkunit(lua_State *L, int index, bool only_on_map)
206 {
207  unit* u = luaW_tounit(L, index, only_on_map);
208  if (!u) luaL_typerror(L, index, "unit");
209  return *u;
210 }
211 
213 {
214  lua_unit* res = new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u);
217  lua_setmetatable(L, -2);
218  return res;
219 }
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
Definition: lapi.cpp:579
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
Calls a Lua function stored below its nArgs arguments at the top of the stack.
Definition: lua_api.cpp:59
Definition: unit.hpp:95
~lua_unit()
Definition: lua_api.cpp:113
game_display * screen
Definition: resources.cpp:27
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:154
static lg::log_domain log_scripting_lua("scripting/lua")
unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map)
Definition: lua_api.cpp:199
luatypekey const getunitKey
Definition: lua_types.cpp:28
unit_ptr get_shared()
Definition: lua_api.cpp:128
Definitions for the interface to Wesnoth Markup Language (WML).
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1169
#define lua_pop(L, n)
Definition: lua.h:322
unit * luaW_tounit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_api.cpp:183
lua_unit * luaW_pushlocalunit(lua_State *L, unit &u)
Definition: lua_api.cpp:212
#define lua_pcall(L, n, r, f)
Definition: lua.h:258
GLuint GLuint end
Definition: glew.h:1221
std::vector< team > * teams
Definition: resources.cpp:29
pointer get_shared_ptr() const
Definition: map.hpp:180
std::pair< unit_iterator, bool > insert(unit_ptr p)
Adds the unit to the map.
Definition: map.cpp:126
unit * c_ptr
Definition: lua_api.hpp:67
unit & luaW_checkunit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_api.cpp:205
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:806
LUA_API void lua_remove(lua_State *L, int idx)
Definition: lapi.cpp:176
std::pair< unit_iterator, bool > replace(const map_location &l, const unit &u)
Works like unit_map::add; but l is emptied first, if needed.
Definition: map.cpp:207
Encapsulates the map of the game.
Definition: location.hpp:38
Storage for a unit, either owned by the Lua code (ptr != 0), a local variable unit (c_ptr != 0)...
Definition: lua_api.hpp:62
luatypekey const executeKey
Definition: lua_types.cpp:27
GLuint res
Definition: glew.h:9258
LUA_API void * lua_touserdata(lua_State *L, int idx)
Definition: lapi.cpp:421
bool luaW_hasmetatable(lua_State *L, int index, luatypekey key)
Returns true if the metatable of the object is the one found in the registry.
Definition: lua_common.cpp:524
static void rethrow()
Rethrows the stored exception.
unit * get()
Definition: lua_api.cpp:117
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:262
int side
Definition: lua_api.hpp:66
GLuint index
Definition: glew.h:1782
size_t uid
Definition: lua_api.hpp:64
#define lua_tostring(L, i)
Definition: lua.h:345
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:112
unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map)
Similar to luaW_checkunit/luaW_tounit but returns a unit_ptr, use this instead of luaW_checkunit/luaW...
Definition: lua_api.cpp:191
bool on_map() const
Definition: lua_api.hpp:76
LUA_API void lua_insert(lua_State *L, int idx)
Definition: lapi.cpp:187
std::pair< unit_iterator, bool > move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
Definition: map.cpp:79
size_t erase(const map_location &l)
Erases the unit at location l, if any.
Definition: map.cpp:277
display_chat_manager & get_chat_manager()
#define LUA_REGISTRYINDEX
Definition: lua.h:39
boost::intrusive_ptr< unit > unit_ptr
Definition: ptr.hpp:29
bool put_map(const map_location &loc)
Definition: lua_api.cpp:143
const GLdouble * m
Definition: glew.h:6968
#define ERR_LUA
Definition: lua_api.cpp:46
Standard logging facilities (interface).
unit_ptr ptr
Definition: lua_api.hpp:65
#define e
unit_iterator find(size_t id)
Definition: map.cpp:285
bool valid() const
Definition: map.hpp:229
void chat_message(std::string const &caption, std::string const &msg)
Displays a message in the chat window.
Definition: lua_api.cpp:48
void add_chat_message(const time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
LUALIB_API int luaL_typerror(lua_State *L, int narg, const char *tname)
Definition: lauxlib.cpp:176
LUA_API void lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:633
GLsizei const GLcharARB ** string
Definition: glew.h:4503
unit_map * units
Definition: resources.cpp:35