The Battle for Wesnoth  1.17.0-dev
lua_object.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2021
3  by Dmitry Kovalenko <nephro.wes@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Lua object(value) wrapper implementation
19  */
20 
21 #pragma once
22 
23 #include "config.hpp"
24 #include "lua/lua.h"
25 #include "map/location.hpp"
26 #include "resources.hpp"
27 #include "scripting/lua_common.hpp"
28 #include "terrain/filter.hpp"
29 #include "variable.hpp"
30 #include "ai/default/contexts.hpp"
32 
33 #include <iterator>
34 #include <string>
35 #include <vector>
36 
37 namespace ai {
38 
40 
41 public:
43  virtual ~lua_object_base() {}
44 
45  virtual void store(lua_State* L, int n) = 0;
46 };
47 
48 template <typename T>
50 {
51 
52 public:
53 
55  : value_()
56  {
57  // empty
58  }
59 
60  lua_object(const T& init)
61  : value_(std::make_shared<T>(init))
62  {
63  // empty
64  }
65 
66  std::shared_ptr<T> get()
67  {
68  return value_;
69  }
70 
71  void store(lua_State* L, int n)
72  {
73  this->value_ = to_type(L, lua_absindex(L, n));
74  }
75 
76  void push(lua_State* L)
77  {
78  from_type(L, this->value_);
79  }
80 
81 protected:
82 
83  // A group of functions that deal with the translation of the results to C++
84  std::shared_ptr<T> to_type(lua_State *, int)
85  {
86  return std::shared_ptr<T>();
87  }
88 
89  // A group of functions that deal with the translations of values back to Lua
90  void from_type(lua_State* L, std::shared_ptr<T>)
91  {
92  lua_pushliteral(L, "Unsupported AI aspect type for Lua!");
93  lua_error(L);
94  }
95 
96  std::shared_ptr<T> value_;
97 };
98 
99 template <>
100 inline std::shared_ptr<double> lua_object<double>::to_type(lua_State *L, int n)
101 {
102  return std::make_shared<double>(lua_tonumber(L, n));
103 }
104 
105 template <>
106 inline void lua_object<double>::from_type(lua_State *L, std::shared_ptr<double> value)
107 {
108  if(value) lua_pushnumber(L, *value);
109  else lua_pushnil(L);
110 }
111 
112 template <>
113 inline std::shared_ptr<std::string> lua_object<std::string>::to_type(lua_State *L, int n)
114 {
115  return std::make_shared<std::string>(lua_tostring(L, n));
116 }
117 
118 template <>
119 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)
120 {
121  if(value) {
122  // TODO: this is is duplicated as a helper function in ai/lua/core.cpp
123  utils::visit(
124  [L](const auto& v) {
125  if constexpr(utils::decayed_is_same<bool, decltype(v)>) {
126  lua_pushboolean(L, v);
127  } else {
128  lua_createtable(L, v.size(), 0);
129  for(const std::string& str : v) {
130  lua_pushlstring(L, str.c_str(), str.size());
131  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
132  }
133  }
134  },
135  *value);
136  } else lua_pushnil(L);
137 }
138 
139 template <>
140 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)
141 {
142  if (lua_isboolean(L, n)) {
143  return std::make_shared<utils::variant<bool, std::vector<std::string>>>(luaW_toboolean(L, n));
144  } else {
145  auto v = std::make_shared<std::vector<std::string>>();
146  int l = lua_rawlen(L, n);
147  for (int i = 1; i < l + 1; ++i)
148  {
149  lua_pushinteger(L, i);
150  lua_gettable(L, n);
151  std::string s = lua_tostring(L, -1);
152  lua_settop(L, n);
153  v->push_back(s);
154  }
155 
156  return std::make_shared<utils::variant<bool, std::vector<std::string>>>(*v);
157  }
158 }
159 
160 template <>
161 inline void lua_object<std::string>::from_type(lua_State *L, std::shared_ptr<std::string> value)
162 {
163  if(value) lua_pushlstring(L, value->c_str(), value->size());
164  else lua_pushnil(L);
165 }
166 
167 template <>
168 inline std::shared_ptr<bool> lua_object<bool>::to_type(lua_State *L, int n)
169 {
170  return std::make_shared<bool>(luaW_toboolean(L, n));
171 }
172 
173 template <>
174 inline void lua_object<bool>::from_type(lua_State *L, std::shared_ptr<bool> value)
175 {
176  if(value) lua_pushboolean(L, *value);
177  else lua_pushnil(L);
178 }
179 
180 template <>
181 inline std::shared_ptr<int> lua_object<int>::to_type(lua_State *L, int n)
182 {
183  return std::make_shared<int>(static_cast<int>(lua_tointeger(L, n)));
184 }
185 
186 template <>
187 inline void lua_object<int>::from_type(lua_State *L, std::shared_ptr<int> value)
188 {
189  if(value) lua_pushnumber(L, *value);
190  else lua_pushnil(L);
191 }
192 
193 template <>
194 inline std::shared_ptr< std::vector<std::string> > lua_object< std::vector<std::string> >::to_type(lua_State *L, int n)
195 {
196  auto v = std::make_shared<std::vector<std::string>>();
197  int l = lua_rawlen(L, n);
198  for (int i = 1; i < l + 1; ++i)
199  {
200  lua_pushinteger(L, i);
201  lua_gettable(L, n);
202  std::string s = lua_tostring(L, -1);
203  lua_settop(L, n);
204  v->push_back(s);
205  }
206 
207  return v;
208 }
209 
210 template <>
211 inline void lua_object< std::vector<std::string> >::from_type(lua_State *L, std::shared_ptr< std::vector<std::string> > value)
212 {
213  if(value) {
214  lua_createtable(L, value->size(), 0);
215  for(const std::string& str : *value) {
216  lua_pushlstring(L, str.c_str(), str.size());
217  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
218  }
219  } else lua_pushnil(L);
220 }
221 
222 template <>
223 inline std::shared_ptr<config> lua_object<config>::to_type(lua_State *L, int n)
224 {
225  auto cfg = std::make_shared<config>();
226  luaW_toconfig(L, n, *cfg);
227  return cfg;
228 }
229 
230 template <>
231 inline void lua_object<config>::from_type(lua_State *L, std::shared_ptr<config> value)
232 {
233  if(value) luaW_pushconfig(L, *value);
234  else lua_pushnil(L);
235 }
236 
237 template <>
238 inline std::shared_ptr<terrain_filter> lua_object<terrain_filter>::to_type(lua_State *L, int n)
239 {
240  auto cfg = std::make_shared<config>();
241  auto vcfg = std::make_shared<vconfig>(*cfg);
242  if (!luaW_tovconfig(L, n, *vcfg)) {
243  cfg->add_child("not");
244  }
245  vcfg->make_safe();
246  return std::make_shared<terrain_filter>(*vcfg, resources::filter_con, false);
247 }
248 
249 template <>
250 inline void lua_object<terrain_filter>::from_type(lua_State *L, std::shared_ptr<terrain_filter> value)
251 {
252  if(value) {
253  std::set<map_location> locs;
254  value->get_locations(locs);
255  lua_createtable(L, locs.size(), 0);
256  for(const map_location& loc : locs) {
257  luaW_pushlocation(L, loc);
258  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
259  }
260  } else lua_pushnil(L);
261 }
262 
263 template <>
264 inline std::shared_ptr<std::vector<target> > lua_object< std::vector<target> >::to_type(lua_State *L, int n)
265 {
266  auto targets = std::make_shared<std::vector<target>>();
267  int l = lua_rawlen(L, n);
268 
269  for (int i = 1; i <= l; ++i)
270  {
271  lua_rawgeti(L, n, i); // st n + 1 TABLE @ N table @ n + 1
272 
273  lua_pushstring(L, "loc"); // st n + 2
274  lua_rawget(L, -2); // st n + 2
275 
276  lua_pushstring(L, "x"); // st n + 3
277  lua_rawget(L, -2); // st n + 3
278  int x = static_cast<int>(lua_tointeger(L, -1)); // st n + 3
279  lua_pop(L, 1); // st n + 2
280 
281  lua_pushstring(L, "y"); // st n + 3
282  lua_rawget(L, -2); // st n + 3
283  int y = static_cast<int>(lua_tointeger(L, -1)); // st n + 3
284 
285  lua_pop(L, 2); // st n + 1
286 
287  lua_pushstring(L, "type"); // st n + 2
288  lua_rawget(L, -2); // st n + 2
289  target::TYPE type = target::TYPE::EXPLICIT;
290  if(lua_isnumber(L, -1)) {
291  type = target::TYPE::from_int(static_cast<int>(lua_tointeger(L, -1))); // st n + 2
292  } else if(lua_isstring(L, -1)) {
293  type = target::TYPE::string_to_enum(lua_tostring(L, -1)); // st n + 2
294  }
295  lua_pop(L, 1); // st n + 1
296 
297  lua_pushstring(L, "value");
298  lua_rawget(L, -2);
299  int value = static_cast<int>(lua_tointeger(L, -1));
300 
301  map_location ml(x, y, wml_loc());
302 
303  targets->emplace_back(ml, value, type);
304  }
305 
306  lua_settop(L, n);
307  return targets;
308 }
309 
310 template <>
311 inline std::shared_ptr<unit_advancements_aspect> lua_object<unit_advancements_aspect>::to_type(lua_State *L, int n)
312 {
313  return std::make_shared<unit_advancements_aspect>(L, n);
314 }
315 
316 // This one is too complex to define in the header.
318 template <>
319 std::shared_ptr<aspect_attacks_lua_filter> lua_object<aspect_attacks_lua_filter>::to_type(lua_State *L, int n);
320 } // end of namespace ai
TYPE
Used to specify the rendering format of images.
Definition: picture.hpp:229
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:60
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:918
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:812
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:96
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:43
#define lua_pop(L, n)
Definition: lua.h:364
std::shared_ptr< T > to_type(lua_State *, int)
Definition: lua_object.hpp:84
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:61
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:972
void store(lua_State *L, int n)
Definition: lua_object.hpp:71
filter_context * filter_con
Definition: resources.cpp:24
void push(lua_State *L)
Definition: lua_object.hpp:76
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 both types are passed throgh std::decay first.
Definition: general.hpp:33
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:38
#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:824
std::size_t i
Definition: function.cpp:967
static map_location::DIRECTION s
Default AI contexts.
void from_type(lua_State *L, std::shared_ptr< T >)
Definition: lua_object.hpp:90
#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:715
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