1 /*
2 Copyright (C) 2009 - 2018 by Guillaume Melquiond <guillaume.melquiond@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 #pragma once
16
17 #include <cstddef>
18 #include <string>
19 #include "scripting/lua_common.hpp"
20 #include "units/ptr.hpp"
21
22 struct lua_State;
23 class lua_unit;
24 struct map_location;
25
26 /**
27 * Test if a Lua value is a unit
28 */
29 bool luaW_isunit(lua_State *, int index);
30
31 /**
32 * Converts a Lua value to a unit pointer.
33 */
34 unit* luaW_tounit(lua_State *L, int index, bool only_on_map = false);
35
36 /**
37 * Converts a Lua value to a unit pointer.
38 */
39 unit& luaW_checkunit(lua_State *L, int index, bool only_on_map = false);
40
41 /**
42 * Pushes a private unit on the stack.
43 */
44 lua_unit* luaW_pushlocalunit(lua_State *L, unit& u);
45
46 /**
47 * Similar to luaW_tounit but returns a unit_ptr; use this instead of
48 * luaW_tounit when using an api that needs unit_ptr.
49 */
50 unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map);
51
52 /**
53 * Similar to luaW_checkunit but returns a unit_ptr; use this instead of
54 * luaW_checkunit when using an api that needs unit_ptr.
55 */
56 unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map);
57
58 /**
59 * Similar to luaW_tounit but returns a lua_unit; use this if you need
60 * to handle map and recall units differently, for example.
61 *
62 * Note that this only returns null if the element on the stack was not a unit,
63 * so it may be an invalid unit.
64 */
65 lua_unit* luaW_tounit_ref(lua_State *L, int index);
66
67 /**
68 * Similar to luaW_checkunit but returns a lua_unit; use this if you need
69 * to handle map and recall units differently, for example.
70 */
71 lua_unit* luaW_checkunit_ref(lua_State *L, int index);
72
73
74 /**
75 * Storage for a unit, either owned by the Lua code (#ptr != 0), a
76 * local variable unit (c_ptr != 0), on a recall list (#side != 0), or on the map.
77 * Shared units are represented by their underlying ID (#uid).
78 */
79 class lua_unit
80 {
81 size_t uid;
82 unit_ptr ptr;
83 int side;
84 unit* c_ptr;
85 lua_unit(const lua_unit&) = delete;
86 lua_unit& operator=(const lua_unit&) = delete;
87
88 template<typename... Args>
89 friend lua_unit* luaW_pushunit(lua_State *L, Args... args);
90 friend lua_unit* luaW_pushlocalunit(lua_State *L, unit& u);
91 static void setmetatable(lua_State *L);
92 public:
lua_unit(size_t u)93 lua_unit(size_t u): uid(u), ptr(), side(0), c_ptr() {}
lua_unit(unit_ptr u)94 lua_unit(unit_ptr u): uid(0), ptr(u), side(0), c_ptr() {}
lua_unit(int s,size_t u)95 lua_unit(int s, size_t u): uid(u), ptr(), side(s), c_ptr() {}
lua_unit(unit & u)96 lua_unit(unit& u): uid(0), ptr(), side(0), c_ptr(&u) {}
97 ~lua_unit();
98
on_map() const99 bool on_map() const { return !ptr && side == 0; }
on_recall_list() const100 int on_recall_list() const { return side; }
101
102 unit* get();
103 unit_ptr get_shared();
104
operator ->()105 unit* operator->() {return get();}
operator *()106 unit& operator*() {return *get();}
107
clear_ref()108 void clear_ref() { uid = 0; ptr = unit_ptr(); side = 0; c_ptr = nullptr; }
109 // Clobbers loc
110 bool put_map(const map_location &loc);
111 };
112
113 template<typename... Args>
luaW_pushunit(lua_State * L,Args...args)114 inline lua_unit* luaW_pushunit(lua_State *L, Args... args) {
115 lua_unit* lu = new(L) lua_unit(args...);
116 lua_unit::setmetatable(L);
117 return lu;
118 }
119
120 namespace lua_units {
121 std::string register_metatables(lua_State *L);
122 }
123