The Battle for Wesnoth  1.15.10+dev
lua_object.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2018 by Dmitry Kovalenko <nephro.wes@gmail.com>
3  Part of the Battle for Wesnoth Project https://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 /**
16  * @file
17  * Lua object(value) wrapper implementation
18  */
19 
20 #pragma once
21 
22 #include "config.hpp"
23 #include "lua/lua.h"
24 #include "map/location.hpp"
25 #include "resources.hpp"
26 #include "scripting/lua_common.hpp"
27 #include "terrain/filter.hpp"
28 #include "variable.hpp"
29 #include "ai/default/contexts.hpp"
31 
32 #include <iterator>
33 #include <string>
34 #include <vector>
35 
36 namespace ai {
37 
39 
40 public:
42  virtual ~lua_object_base() {}
43 
44  virtual void store(lua_State* L, int n) = 0;
45 };
46 
47 template <typename T>
49 {
50 
51 public:
52 
54  : value_()
55  {
56  // empty
57  }
58 
59  lua_object(const T& init)
60  : value_(std::make_shared<T>(init))
61  {
62  // empty
63  }
64 
65  std::shared_ptr<T> get()
66  {
67  return value_;
68  }
69 
70  void store(lua_State* L, int n)
71  {
72  this->value_ = to_type(L, lua_absindex(L, n));
73  }
74 
75  void push(lua_State* L)
76  {
77  from_type(L, this->value_);
78  }
79 
80 protected:
81 
82  // A group of functions that deal with the translation of the results to C++
83  std::shared_ptr<T> to_type(lua_State *, int)
84  {
85  return std::shared_ptr<T>();
86  }
87 
88  // A group of functions that deal with the translations of values back to Lua
89  void from_type(lua_State* L, std::shared_ptr<T>)
90  {
91  lua_pushliteral(L, "Unsupported AI aspect type for Lua!");
92  lua_error(L);
93  }
94 
95  std::shared_ptr<T> value_;
96 };
97 
98 template <>
99 inline std::shared_ptr<double> lua_object<double>::to_type(lua_State *L, int n)
100 {
101  return std::make_shared<double>(lua_tonumber(L, n));
102 }
103 
104 template <>
105 inline void lua_object<double>::from_type(lua_State *L, std::shared_ptr<double> value)
106 {
107  if(value) lua_pushnumber(L, *value);
108  else lua_pushnil(L);
109 }
110 
111 template <>
112 inline std::shared_ptr<std::string> lua_object<std::string>::to_type(lua_State *L, int n)
113 {
114  return std::make_shared<std::string>(lua_tostring(L, n));
115 }
116 
117 template <>
118 inline void lua_object<utils::variant<bool, std::vector<std::string>>>::from_type(lua_State *L, std::shared_ptr<utils::variant<bool, std::vector<std::string>>> value)
119 {
120  if(value) {
121  // TODO: this is is duplicated as a helper function in ai/lua/core.cpp
122  utils::visit(
123  [L](const auto& v) {
124  if constexpr(utils::decayed_is_same<bool, decltype(v)>) {
125  lua_pushboolean(L, v);
126  } else {
127  lua_createtable(L, v.size(), 0);
128  for(const std::string& str : v) {
129  lua_pushlstring(L, str.c_str(), str.size());
130  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
131  }
132  }
133  },
134  *value);
135  } else lua_pushnil(L);
136 }
137 
138 template <>
139 inline std::shared_ptr< utils::variant<bool, std::vector<std::string>> > lua_object< utils::variant<bool, std::vector<std::string>> >::to_type(lua_State *L, int n)
140 {
141  if (lua_isboolean(L, n)) {
142  return std::make_shared<utils::variant<bool, std::vector<std::string>>>(luaW_toboolean(L, n));
143  } else {
144  auto v = std::make_shared<std::vector<std::string>>();
145  int l = lua_rawlen(L, n);
146  for (int i = 1; i < l + 1; ++i)
147  {
148  lua_pushinteger(L, i);
149  lua_gettable(L, n);
150  std::string s = lua_tostring(L, -1);
151  lua_settop(L, n);
152  v->push_back(s);
153  }
154 
155  return std::make_shared<utils::variant<bool, std::vector<std::string>>>(*v);
156  }
157 }
158 
159 template <>
160 inline void lua_object<std::string>::from_type(lua_State *L, std::shared_ptr<std::string> value)
161 {
162  if(value) lua_pushlstring(L, value->c_str(), value->size());
163  else lua_pushnil(L);
164 }
165 
166 template <>
167 inline std::shared_ptr<bool> lua_object<bool>::to_type(lua_State *L, int n)
168 {
169  return std::make_shared<bool>(luaW_toboolean(L, n));
170 }
171 
172 template <>
173 inline void lua_object<bool>::from_type(lua_State *L, std::shared_ptr<bool> value)
174 {
175  if(value) lua_pushboolean(L, *value);
176  else lua_pushnil(L);
177 }
178 
179 template <>
180 inline std::shared_ptr<int> lua_object<int>::to_type(lua_State *L, int n)
181 {
182  return std::make_shared<int>(static_cast<int>(lua_tointeger(L, n)));
183 }
184 
185 template <>
186 inline void lua_object<int>::from_type(lua_State *L, std::shared_ptr<int> value)
187 {
188  if(value) lua_pushnumber(L, *value);
189  else lua_pushnil(L);
190 }
191 
192 template <>
193 inline std::shared_ptr< std::vector<std::string> > lua_object< std::vector<std::string> >::to_type(lua_State *L, int n)
194 {
195  auto v = std::make_shared<std::vector<std::string>>();
196  int l = lua_rawlen(L, n);
197  for (int i = 1; i < l + 1; ++i)
198  {
199  lua_pushinteger(L, i);
200  lua_gettable(L, n);
201  std::string s = lua_tostring(L, -1);
202  lua_settop(L, n);
203  v->push_back(s);
204  }
205 
206  return v;
207 }
208 
209 template <>
210 inline void lua_object< std::vector<std::string> >::from_type(lua_State *L, std::shared_ptr< std::vector<std::string> > value)
211 {
212  if(value) {
213  lua_createtable(L, value->size(), 0);
214  for(const std::string& str : *value) {
215  lua_pushlstring(L, str.c_str(), str.size());
216  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
217  }
218  } else lua_pushnil(L);
219 }
220 
221 template <>
222 inline std::shared_ptr<config> lua_object<config>::to_type(lua_State *L, int n)
223 {
224  auto cfg = std::make_shared<config>();
225  luaW_toconfig(L, n, *cfg);
226  return cfg;
227 }
228 
229 template <>
230 inline void lua_object<config>::from_type(lua_State *L, std::shared_ptr<config> value)
231 {
232  if(value) luaW_pushconfig(L, *value);
233  else lua_pushnil(L);
234 }
235 
236 template <>
237 inline std::shared_ptr<terrain_filter> lua_object<terrain_filter>::to_type(lua_State *L, int n)
238 {
239  auto cfg = std::make_shared<config>();
240  auto vcfg = std::make_shared<vconfig>(*cfg);
241  if (!luaW_tovconfig(L, n, *vcfg)) {
242  cfg->add_child("not");
243  }
244  vcfg->make_safe();
245  return std::make_shared<terrain_filter>(*vcfg, resources::filter_con, false);
246 }
247 
248 template <>
249 inline void lua_object<terrain_filter>::from_type(lua_State *L, std::shared_ptr<terrain_filter> value)
250 {
251  if(value) {
252  std::set<map_location> locs;
253  value->get_locations(locs);
254  lua_createtable(L, locs.size(), 0);
255  for(const map_location& loc : locs) {
256  luaW_pushlocation(L, loc);
257  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
258  }
259  } else lua_pushnil(L);
260 }
261 
262 template <>
263 inline std::shared_ptr<std::vector<target> > lua_object< std::vector<target> >::to_type(lua_State *L, int n)
264 {
265  auto targets = std::make_shared<std::vector<target>>();
266  int l = lua_rawlen(L, n);
267 
268  for (int i = 1; i <= l; ++i)
269  {
270  lua_rawgeti(L, n, i); // st n + 1 TABLE @ N table @ n + 1
271 
272  lua_pushstring(L, "loc"); // st n + 2
273  lua_rawget(L, -2); // st n + 2
274 
275  lua_pushstring(L, "x"); // st n + 3
276  lua_rawget(L, -2); // st n + 3
277  int x = static_cast<int>(lua_tointeger(L, -1)); // st n + 3
278  lua_pop(L, 1); // st n + 2
279 
280  lua_pushstring(L, "y"); // st n + 3
281  lua_rawget(L, -2); // st n + 3
282  int y = static_cast<int>(lua_tointeger(L, -1)); // st n + 3
283 
284  lua_pop(L, 2); // st n + 1
285 
286  lua_pushstring(L, "type"); // st n + 2
287  lua_rawget(L, -2); // st n + 2
288  target::TYPE type = target::TYPE::EXPLICIT;
289  if(lua_isnumber(L, -1)) {
290  type = target::TYPE::from_int(static_cast<int>(lua_tointeger(L, -1))); // st n + 2
291  } else if(lua_isstring(L, -1)) {
292  type = target::TYPE::string_to_enum(lua_tostring(L, -1)); // st n + 2
293  }
294  lua_pop(L, 1); // st n + 1
295 
296  lua_pushstring(L, "value");
297  lua_rawget(L, -2);
298  int value = static_cast<int>(lua_tointeger(L, -1));
299 
300  map_location ml(x, y, wml_loc());
301 
302  targets->emplace_back(ml, value, type);
303  }
304 
305  lua_settop(L, n);
306  return targets;
307 }
308 
309 template <>
310 inline std::shared_ptr<unit_advancements_aspect> lua_object<unit_advancements_aspect>::to_type(lua_State *L, int n)
311 {
312  return std::make_shared<unit_advancements_aspect>(L, n);
313 }
314 
315 // This one is too complex to define in the header.
317 template <>
318 std::shared_ptr<aspect_attacks_lua_filter> lua_object<aspect_attacks_lua_filter>::to_type(lua_State *L, int n);
319 } // end of namespace ai
TYPE
Used to specify the rendering format of images.
Definition: picture.hpp:228
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:728
lua_object(const T &init)
Definition: lua_object.hpp:59
bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
Gets an optional vconfig from either a table or a userdata.
Definition: lua_common.cpp:839
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:733
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:173
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:581
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:710
LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:889
std::shared_ptr< T > value_
Definition: lua_object.hpp:95
LUA_API int lua_gettable(lua_State *L, int idx)
Definition: lapi.cpp:640
#define lua_tointeger(L, i)
Definition: lua.h:362
LUA_API int lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:698
STL namespace.
#define lua_tonumber(L, i)
Definition: lua.h:361
Definitions for the interface to Wesnoth Markup Language (WML).
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:161
virtual ~lua_object_base()
Definition: lua_object.hpp:42
#define lua_pop(L, n)
Definition: lua.h:364
std::shared_ptr< T > to_type(lua_State *, int)
Definition: lua_object.hpp:83
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:59
virtual void store(lua_State *L, int n)=0
struct utils::detail::formula_initer init
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:292
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:893
void store(lua_State *L, int n)
Definition: lua_object.hpp:70
filter_context * filter_con
Definition: resources.cpp:23
void push(lua_State *L)
Definition: lua_object.hpp:75
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:502
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except it uses the decayed form of V.
Definition: general.hpp:32
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:473
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:481
#define lua_pushliteral(L, s)
Definition: lua.h:381
Encapsulates the map of the game.
Definition: location.hpp:37
#define lua_isboolean(L, n)
Definition: lua.h:376
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:745
std::size_t i
Definition: function.cpp:934
static map_location::DIRECTION s
Default AI contexts.
void from_type(lua_State *L, std::shared_ptr< T >)
Definition: lua_object.hpp:89
#define lua_tostring(L, i)
Definition: lua.h:386
LUA_API int lua_isnumber(lua_State *L, int idx)
Definition: lapi.cpp:285
LUA_API lua_Unsigned lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:402
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1205
void luaW_pushlocation(lua_State *L, const map_location &ml)
Converts a map location object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:665
static map_location::DIRECTION n
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:489
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:514