Engine
Raylib based game framework
Loading...
Searching...
No Matches
MyLua.h
1#pragma once
2
3#define SOL_NO_EXCEPTIONS 1
4#include "sol/sol.hpp"
5
6#include "Log/Log.h"
7
8#include <cxxabi.h>
9#include <typeindex>
10
11template <typename T>
12std::string Demangle()
13{
14 std::string name = typeid(T).name();
15
16 int status = -4;
17
18 std::unique_ptr<char, void (*)(void*)> res{abi::__cxa_demangle(name.c_str(), NULL, NULL, &status), std::free};
19
20 return (status == 0) ? res.get() : name;
21}
22
23inline std::string Demangle(const std::type_index& type)
24{
25 const char* name = type.name();
26
27 int status = -4;
28
29 std::unique_ptr<char, void (*)(void*)> res{abi::__cxa_demangle(name, nullptr, nullptr, &status), std::free};
30
31 return (status == 0) ? res.get() : name;
32}
33
34template <typename T>
35std::string DemangleWithoutNamespace()
36{
37 std::string demangled = Demangle<T>();
38
39 size_t pos = demangled.find_last_of("::");
40 if (pos != std::string::npos)
41 {
42 return demangled.substr(pos + 1);
43 }
44
45 return demangled;
46}
47
48inline void SanitizeEnvironment(sol::state& lua, sol::environment& env)
49{
50 env["collectgarbage"] = sol::nil;
51 env["dofile"] = sol::nil;
52 env["loadfile"] = sol::nil;
53 env["module"] = sol::nil;
54 env["load"] = sol::nil;
55 // env["require"] = sol::nil;
56 // env["package"] = sol::nil;
57 env["getfenv"] = sol::nil;
58 env["setfenv"] = sol::nil;
59 env["newproxy"] = sol::nil;
60 env["rawset"] = sol::nil;
61 env["rawget"] = sol::nil;
62
63 sol::table metatable = lua.create_table();
64 metatable["__index"] = lua.globals();
65 metatable["__newindex"] = [](sol::table self, sol::object key, sol::object value)
66 {
67 self.raw_set(key, value);
68 };
69 metatable[sol::metatable_key] = sol::nil;
70 metatable["__metatable"] = "locked";
71
72 env[sol::metatable_key] = metatable;
73 env["_G"] = env;
74 env["_ENV"] = env;
75}
76
77namespace Lua
78{
79 inline sol::environment CreateEnvironment(sol::state& lua, const bool globals)
80 {
81 if (globals)
82 {
83 sol::environment env = sol::environment(lua, sol::create, lua.globals());
84
85 SanitizeEnvironment(lua, env);
86
87 return env;
88 }
89
90 sol::environment env(lua, sol::create);
91
92 SanitizeEnvironment(lua, env);
93
94 return env;
95 }
96
97 inline bool LoadFile(sol::state& lua, const char* name)
98 {
99 sol::protected_function_result result = lua.safe_script_file(name);
100
101 if (result.valid())
102 {
103 return true;
104 }
105
106 sol::error e = result;
107 LogColor(LOG_YELLOW, "Failed to load lua file ", name, " with error: ", e.what());
108
109 return false;
110 }
111
112 inline bool LoadFile(sol::state& lua, sol::environment& env, const char* name)
113 {
114 sol::protected_function_result result = lua.safe_script_file(name, env);
115
116 if (result.valid())
117 {
118 return true;
119 }
120
121 sol::error e = result;
122 LogColor(LOG_YELLOW, "Failed to load lua file ", name, " with error: ", e.what());
123
124 return false;
125 }
126
127 template <typename T>
128 std::optional<T> GetValue(sol::state& lua, const char* key)
129 {
130 sol::object object = lua[key];
131 if (object.is<T>())
132 {
133 return object.as<T>();
134 }
135
136 LogColor(LOG_YELLOW, "Type mismatch for: ", key, " expected ", Demangle<T>());
137
138 return std::nullopt;
139 }
140
141 template <typename T>
142 std::optional<T> GetValue(sol::environment& env, const char* key)
143 {
144 sol::object object = env[key];
145 if (object.is<T>())
146 {
147 return object.as<T>();
148 }
149
150 LogColor(LOG_YELLOW, "Type mismatch for: ", key, " expected ", Demangle<T>());
151
152 return std::nullopt;
153 }
154
155 template <typename O, typename T>
156 std::optional<T> GetValueObjectValue(sol::state& lua, const char* objectKey, const char* key)
157 {
158 sol::object object = lua[objectKey];
159 if (object.is<O>())
160 {
161 sol::object member = object.as<sol::table>()[key];
162 if (member.is<T>())
163 {
164 return member.as<T>();
165 }
166
167 LogColor(LOG_YELLOW, "Type mismatch for: ", key, " expected ", Demangle<T>());
168
169 return std::nullopt;
170 }
171
172 LogColor(LOG_YELLOW, "Type mismatch for: ", objectKey, " expected ", Demangle<O>());
173
174 return std::nullopt;
175 }
176
177 template <typename O, typename T>
178 std::optional<T> GetValueObjectValue(sol::environment& env, const char* objectKey, const char* key)
179 {
180 sol::object object = env[objectKey];
181 if (object.is<O>())
182 {
183 sol::object member = object.as<sol::table>()[key];
184 if (member.is<T>())
185 {
186 return member.as<T>();
187 }
188
189 LogColor(LOG_YELLOW, "Type mismatch for: ", key, " expected ", Demangle<T>());
190
191 return std::nullopt;
192 }
193
194 LogColor(LOG_YELLOW, "Type mismatch for: ", objectKey, " expected ", Demangle<O>());
195
196 return std::nullopt;
197 }
198
199 template <typename T>
200 bool TypeExists(sol::state& lua)
201 {
202 std::string typeName = DemangleWithoutNamespace<T>();
203
204 sol::object obj = lua[typeName];
205 return obj.valid();
206 }
207
208 template <typename T>
209 bool TypeExists(sol::environment& env)
210 {
211 std::string typeName = DemangleWithoutNamespace<T>();
212
213 sol::object obj = env[typeName];
214 return obj.valid();
215 }
216
217 inline bool ObjectExists(sol::state& lua, const char* key)
218 {
219 sol::object obj = lua[key];
220 return obj.valid();
221 }
222
223 inline bool ObjectExists(sol::environment& env, const char* key)
224 {
225 sol::object obj = env[key];
226 return obj.valid();
227 }
228
229 inline bool FunctionExists(sol::state& lua, const char* key)
230 {
231 sol::object obj = lua[key];
232 return obj.valid() && obj.is<sol::function>();
233 }
234
235 inline bool FunctionExists(sol::environment& env, const char* key)
236 {
237 sol::object obj = env[key];
238 return obj.valid() && obj.is<sol::function>();
239 }
240
241 template <bool log = true, typename... Args>
242 bool CallFunction(sol::state& lua, const char* key, Args&&... args)
243 {
244 sol::protected_function function = lua[key];
245 if (function)
246 {
247 sol::protected_function_result result = function(std::forward<Args>(args)...);
248 if (result.valid())
249 {
250 return true;
251 }
252
253 sol::error e = result;
254
255 LogColor(LOG_YELLOW, "Invalid call of function ", key, " with error: ", e.what());
256
257 return false;
258 }
259
260 if (log)
261 {
262 LogColor(LOG_YELLOW, "Function ", key, " does not exists");
263 }
264
265 return false;
266 }
267
268 template <bool log = true, typename... Args>
269 bool CallFunction(sol::environment& env, const char* key, Args&&... args)
270 {
271 sol::protected_function function = env[key];
272 if (function)
273 {
274 sol::protected_function_result result = function(std::forward<Args>(args)...);
275 if (result.valid())
276 {
277 return true;
278 }
279
280 sol::error e = result;
281
282 LogColor(LOG_YELLOW, "Invalid call of function ", key, " with error: ", e.what());
283
284 return false;
285 }
286
287 if (log)
288 {
289 LogColor(LOG_YELLOW, "Function ", key, " does not exists");
290 }
291
292 return false;
293 }
294
295 template <typename T, typename... Args>
296 std::optional<T> CallFunctionWithReturn(sol::state& lua, const char* key, Args&&... args)
297 {
298 sol::protected_function function = lua[key];
299 if (function)
300 {
301 sol::protected_function_result result = function(std::forward<Args>(args)...);
302 if (result.valid())
303 {
304 sol::object object = result.get<sol::object>();
305 if (object.is<T>())
306 {
307 return object.as<T>();
308 }
309
310 LogColor(LOG_YELLOW, "Type mismatch for: ", key, " expected: ", Demangle<T>());
311
312 return std::nullopt;
313 }
314
315 sol::error e = result;
316 LogColor(LOG_YELLOW, "Invalid call of function: ", key, " with error: ", e.what());
317
318 return std::nullopt;
319 }
320
321 LogColor(LOG_YELLOW, "Function ", key, " does not exists");
322
323 return std::nullopt;
324 }
325
326 template <typename T, typename... Args>
327 std::optional<T> CallFunctionWithReturn(sol::environment& env, const char* key, Args&&... args)
328 {
329 sol::protected_function function = env[key];
330 if (function)
331 {
332 sol::protected_function_result result = function(std::forward<Args>(args)...);
333 if (result.valid())
334 {
335 sol::object object = result.get<sol::object>();
336 if (object.is<T>())
337 {
338 return object.as<T>();
339 }
340
341 LogColor(LOG_YELLOW, "Type mismatch for: ", key, " expected: ", Demangle<T>());
342
343 return std::nullopt;
344 }
345
346 sol::error e = result;
347 LogColor(LOG_YELLOW, "Invalid call of function: ", key, " with error: ", e.what());
348
349 return std::nullopt;
350 }
351
352 LogColor(LOG_YELLOW, "Function ", key, " does not exists");
353
354 return std::nullopt;
355 }
356
357 template <typename T>
358 void RegisterFunction(sol::state& lua, const char* key, T function)
359 {
360 lua[key] = function;
361 }
362
363 template <typename T>
364 void RegisterFunction(sol::environment& env, const char* key, T function)
365 {
366 env[key] = function;
367 }
368
369 template <typename T, typename I, typename... Args>
370 void RegisterMethod(sol::state& lua, const char* key, I& instance, T (I::*method)(Args...))
371 {
372 lua.set_function(key, method, &instance);
373 }
374
375 template <typename T, typename I, typename... Args>
376 void RegisterMethod(sol::environment& env, const char* key, I& instance, T (I::*method)(Args...))
377 {
378 env.set_function(key, method, &instance);
379 }
380
381 template <typename T, typename... Args>
382 void RegisterType(sol::state& lua, const char* name, Args&&... args)
383 {
384 lua.new_usertype<T>(name, std::forward<Args>(args)...);
385 }
386
387 template <typename T, typename... Args>
388 void RegisterType(sol::environment& env, const char* name, Args&&... args)
389 {
390 env.new_usertype<T>(name, std::forward<Args>(args)...);
391 }
392
393 template <typename T>
394 void BindObject(sol::state& lua, const char* name, T object)
395 {
396 lua[name] = object;
397 }
398
399 template <typename T>
400 void BindObject(sol::environment& env, const char* name, T object)
401 {
402 env[name] = object;
403 }
404}