-
-
Notifications
You must be signed in to change notification settings - Fork 546
/
Copy pathusertype_advanced.cpp
145 lines (116 loc) · 2.92 KB
/
usertype_advanced.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
/*
#include "player.hpp"
*/
#include <iostream>
struct player {
public:
int bullets;
int speed;
player() : player(3, 100) {
}
player(int ammo) : player(ammo, 100) {
}
player(int ammo, int hitpoints)
: bullets(ammo), hp(hitpoints) {
}
void boost() {
speed += 10;
}
bool shoot() {
if (bullets < 1)
return false;
--bullets;
return true;
}
void set_hp(int value) {
hp = value;
}
int get_hp() const {
return hp;
}
private:
int hp;
};
int main() {
std::cout << "=== usertype_advanced ===" << std::endl;
sol::state lua;
lua.open_libraries(sol::lib::base);
// note that you can set a
// userdata before you register a usertype,
// and it will still carry
// the right metatable if you register it later
// set a variable "p2" of type "player" with 0 ammo
lua["p2"] = player(0);
// make usertype metatable
sol::usertype<player> player_type
= lua.new_usertype<player>("player",
// 3 constructors
sol::constructors<player(),
player(int),
player(int, int)>());
// typical member function that returns a variable
player_type["shoot"] = &player::shoot;
// typical member function
player_type["boost"] = &player::boost;
// gets or set the value using member variable syntax
player_type["hp"]
= sol::property(&player::get_hp, &player::set_hp);
// read and write variable
player_type["speed"] = &player::speed;
// can only read from, not write to
// .set(foo, bar) is the same as [foo] = bar;
player_type.set("bullets", sol::readonly(&player::bullets));
// You can also add members to the code, defined in Lua!
// This lets you have a high degree of flexibility in the
// code
std::string prelude_script = R"(
function player:brake ()
self.speed = 0
print("we hit the brakes!")
end
)";
std::string player_script = R"(
-- call single argument integer constructor
p1 = player.new(2)
-- p2 is still here from being
-- set with lua["p2"] = player(0); below
local p2shoots = p2:shoot()
assert(not p2shoots)
-- had 0 ammo
-- set variable property setter
p1.hp = 545
-- get variable through property unqualified_getter
print(p1.hp)
assert(p1.hp == 545)
local did_shoot_1 = p1:shoot()
print(did_shoot_1)
print(p1.bullets)
local did_shoot_2 = p1:shoot()
print(did_shoot_2)
print(p1.bullets)
local did_shoot_3 = p1:shoot()
print(did_shoot_3)
-- can read
print(p1.bullets)
-- would error: is a readonly variable, cannot write
-- p1.bullets = 20
p1:boost()
-- call the function we define at runtime from a Lua script
p1:brake()
)";
// Uncomment and use the file to try that out, too!
// Make sure it's in the local directory of the executable
// after you build, or adjust the filename path Or whatever
// else you like!
//
/*
lua.script_file("prelude_script.lua");
lua.script_file("player_script.lua");
*/
lua.script(prelude_script);
lua.script(player_script);
std::cout << std::endl;
return 0;
}