Etterna 0.74.4
Loading...
Searching...
No Matches
LuaManager.h
1#ifndef LUA_MANAGER_H
2#define LUA_MANAGER_H
3
4struct lua_State;
5using Lua = struct lua_State;
6using RegisterWithLuaFn = void (*)(struct lua_State*);
7class RageMutex;
8class XNode;
9class LuaReference;
10
11#include "lua.hpp"
12
13// For Dialog::Result
14#include "RageUtil/Utils/RageUtil.h"
15#include "arch/Dialog/Dialog.h"
16
18{
19 public:
20 // Every Actor should register its class at program initialization.
21 static void Register(RegisterWithLuaFn pfn);
22
23 LuaManager();
25
26 auto Get() -> Lua*;
27 void Release(Lua*& p);
28
29 /* Explicitly lock and unlock Lua access. This is done automatically by
30 * Get() and Release(). */
31 void YieldLua();
32 void UnyieldLua();
33
34 // Register all subscribing types.
35 // There's no harm in registering when already registered.
36 void RegisterTypes();
37
38 void SetGlobal(const std::string& sName, int val);
39 void SetGlobal(const std::string& sName, float val);
40 void SetGlobal(const std::string& sName, const std::string& val);
41 void UnsetGlobal(const std::string& sName);
42
43 private:
44 lua_State* m_pLuaMain;
45 // Swallow up warnings. If they must be used, define them.
46 auto operator=(const LuaManager& rhs) -> LuaManager&;
47 LuaManager(const LuaManager& rhs);
48};
49
50extern LuaManager* LUA;
51
53namespace LuaHelpers {
54/* Load the given script with the given name. On success, the resulting
55 * chunk will be on the stack. On error, the error is stored in sError
56 * and the stack is unchanged. */
57auto
58LoadScript(Lua* L,
59 const std::string& sScript,
60 const std::string& sName,
61 std::string& sError) -> bool;
62
63/* Report the error three ways: Broadcast message, Warn, and Dialog. */
64/* If UseAbort is true, reports the error through Dialog::AbortRetryIgnore
65 and returns the result. */
66/* If UseAbort is false, reports the error through Dialog::OK and returns
67 Dialog::ok. */
68auto
69ReportScriptError(std::string const& Error,
70 std::string ErrorType = "LUA_ERROR",
71 bool UseAbort = false) -> Dialog::Result;
72// Just the broadcast message part, for things that need to do the rest
73// differently.
74void
75ScriptErrorMessage(std::string const& Error);
76
78template<typename... Args>
79void
80ReportScriptErrorFmt(std::string const& msg, Args const&... args)
81{
82 std::string result = ssprintf(msg.c_str(), args...);
83 ReportScriptError(result);
84}
85
86/* Run the function with arguments at the top of the stack, with the given
87 * number of arguments. The specified number of return values are left on
88 * the Lua stack. On error, nils are left on the stack, sError is set and
89 * false is returned.
90 * If ReportError is true, Error should contain the string to prepend
91 * when reporting. The error is reported through LOG->Warn and
92 * SCREENMAN->SystemMessage.
93 */
94auto
95RunScriptOnStack(Lua* L,
96 std::string& Error,
97 int Args = 0,
98 int ReturnValues = 0,
99 bool ReportError = false,
100 bool blank_env = false) -> bool;
101
102/* LoadScript the given script, and RunScriptOnStack it.
103 * iArgs arguments are at the top of the stack. */
104auto
105RunScript(Lua* L,
106 const std::string& Script,
107 const std::string& Name,
108 std::string& Error,
109 int Args = 0,
110 int ReturnValues = 0,
111 bool ReportError = false,
112 bool blank_env = false) -> bool;
113
114/* Run the given expression, returning a single value, and leave the return
115 * value on the stack. On error, push nil. */
116auto
117RunExpression(Lua* L,
118 const std::string& sExpression,
119 const std::string& sName = "",
120 bool blank_env = false) -> bool;
121
122auto
123RunScriptFile(const std::string& sFile, bool blank_env = false) -> bool;
124
125auto
126run_script_file_in_state(lua_State* L,
127 std::string const& filename,
128 int return_values,
129 bool blank_env) -> bool;
130auto
131string_can_be_lua_identifier(lua_State* L, std::string const& str) -> bool;
132void
133push_lua_escaped_string(lua_State* L, std::string const& str);
134// save_lua_table_to_file will only save bools, strings, and numbers.
135// Nothing else in the lua table will be saved.
136void
137save_lua_table_to_file(lua_State* L,
138 int table_index,
139 std::string const& filename);
140
141/* Create a Lua array (a table with indices starting at 1) of the given vector,
142 * and push it on the stack. */
143void
144CreateTableFromArrayB(Lua* L, const std::vector<bool>& aIn);
145
146// Create a Lua table with contents set from this XNode, then push it on the
147// stack.
148void
149CreateTableFromXNode(Lua* L, const XNode* pNode);
150
151/* Recursively copy elements from the table at stack element -2 into the
152 * table at stack -1. Pop both elements from the stack. */
153void
154DeepCopy(lua_State* L);
155
156// Read the table at the top of the stack back into a vector.
157void
158ReadArrayFromTableB(Lua* L, std::vector<bool>& aOut);
159
160void
161rec_print_table(lua_State* L,
162 std::string const& name,
163 std::string const& indent);
164
165void
166ParseCommandList(lua_State* L,
167 const std::string& sCommands,
168 const std::string& sName,
169 bool bLegacy);
170
171auto
172GetLuaInformation() -> XNode*;
173
174/* Pops the last iArgs arguments from the stack, and return a function that
175 * returns those values. */
176void
177PushValueFunc(lua_State* L, int iArgs);
178
179template<class T>
180void
181Push(lua_State* L, const T& Object);
182
183template<class T>
184auto
185FromStack(lua_State* L, T& Object, int iOffset) -> bool;
186
187// Not using a template for the c style string: found it tricky to use.
188auto
189FromStack(lua_State* L, char const* Object, int iOffset) -> bool;
190
191template<class T>
192auto
193Pop(lua_State* L, T& val) -> bool
194{
195 bool bRet = LuaHelpers::FromStack(L, val, -1);
196 lua_pop(L, 1);
197 return bRet;
198}
199
200template<class T>
201void
202ReadArrayFromTable(std::vector<T>& aOut, lua_State* L)
203{
204 luaL_checktype(L, -1, LUA_TTABLE);
205
206 int i = 0;
207 while (lua_rawgeti(L, -1, ++i), !lua_isnil(L, -1)) {
208 T value = T();
209 LuaHelpers::Pop(L, value);
210 aOut.push_back(value);
211 }
212 lua_pop(L, 1); // pop nil
213}
214template<class T>
215void
216CreateTableFromArray(const std::vector<T>& aIn, lua_State* L)
217{
218 lua_newtable(L);
219 for (unsigned i = 0; i < aIn.size(); ++i) {
220 LuaHelpers::Push(L, aIn[i]);
221 lua_rawseti(L, -2, i + 1);
222 }
223}
224
225auto
226TypeError(Lua* L, int narg, std::string const& tname) -> int;
227inline auto
228AbsIndex(Lua* L, int i) -> int
229{
230 if (i > 0 || i <= LUA_REGISTRYINDEX) {
231 return i;
232 }
233 return lua_gettop(L) + i + 1;
234}
235} // namespace LuaHelpers
236
238{
239 public:
240 LuaThreadVariable(const std::string& sName, const std::string& sValue);
241 LuaThreadVariable(const std::string& sName, const LuaReference& Value);
242 LuaThreadVariable(lua_State* L); // name and value are on stack
244 static void GetThreadVariable(lua_State* L);
245
246 private:
247 LuaThreadVariable(const LuaThreadVariable& cpy); // not defined
248
249 void SetFromStack(lua_State* L);
250 auto AdjustCount(lua_State* L, int iAdd) -> int;
251 static auto PushThreadTable(lua_State* L, bool bCreate) -> bool;
252 static auto GetCurrentThreadIDString() -> std::string;
253
254 LuaReference* m_Name;
255 LuaReference* m_pOldValue;
256
257 // Swallow up warnings. If they must be used, define them.
258 auto operator=(const LuaThreadVariable& rhs) -> LuaThreadVariable&;
259};
260
270#define FOREACH_LUATABLE(L, index) \
271 \
272 for (const int SM_UNIQUE_NAME(tab) = LuaHelpers::AbsIndex(L, index), \
273 SM_UNIQUE_NAME(top) = (lua_pushnil(L), lua_gettop(L)); \
274 lua_next(L, SM_UNIQUE_NAME(tab)) && (lua_pushvalue(L, -2), true); \
275 lua_settop(L, SM_UNIQUE_NAME(top)))
276
278#define FOREACH_LUATABLEI(L, index, i) \
279 for (int SM_UNIQUE_NAME(tab) = LuaHelpers::AbsIndex(L, index), \
280 SM_UNIQUE_NAME(top) = lua_gettop(L), \
281 (i) = 1; \
282 lua_rawgeti(L, SM_UNIQUE_NAME(tab), i), \
283 lua_isnil(L, -1) \
284 ? (lua_pop(L, 1), false) \
285 : (true); /* if nil, pop the nil and stop traversal */ \
286 lua_settop(L, SM_UNIQUE_NAME(top)), ++(i))
287
289{
290 RegisterLuaFunction(RegisterWithLuaFn pfn) { LuaManager::Register(pfn); }
291};
292#define REGISTER_WITH_LUA_FUNCTION(Fn) \
293 static RegisterLuaFunction register##Fn(Fn);
294
295inline auto
296MyLua_checkboolean(lua_State* L, int numArg) -> bool
297{
298 luaL_checktype(L, numArg, LUA_TBOOLEAN);
299 return !(lua_toboolean(L, numArg) == 0);
300}
301
302/* BIArg is like BArg, except 1 is accepted as a true value and (as a special
303 * case) 0 is accepted as a false value. This is to help transitions where
304 * "cmd,0" is used to mean "cmd,false". */
305inline auto
306MyLua_checkintboolean(lua_State* L, int iArg) -> bool
307{
308 luaL_checkany(L, iArg);
309 int iType = lua_type(L, iArg);
310 if (iType == LUA_TNUMBER) {
311 int iValue = static_cast<int>(lua_tointeger(L, iArg));
312 return iValue != 0;
313 }
314
315 return MyLua_checkboolean(L, iArg);
316}
317
318// Checks the table at index to verify that it contains strings.
319inline auto
320TableContainsOnlyStrings(lua_State* L, int index) -> bool
321{
322 bool passed = true;
323 lua_pushnil(L);
324 while (lua_next(L, index) != 0) {
325 // `key' is at index -2 and `value' at index -1
326 const char* pValue = lua_tostring(L, -1);
327 if (pValue == nullptr) {
328 // Was going to print an error to the log with the key that failed,
329 // but didn't want to pull in RageLog. -Kyz
330 passed = false;
331 }
332 lua_pop(L, 1);
333 }
334 return passed;
335}
336
337auto
338GetFuncArg(int n, lua_State* L) -> LuaReference;
339#define SArg(n) (luaL_checkstring(L, (n)))
340#define BIArg(n) (MyLua_checkintboolean(L, (n)))
341#define IArg(n) (luaL_checkint(L, (n)))
342#define BArg(n) (MyLua_checkboolean(L, (n)))
343#define FArg(n) (static_cast<float>(luaL_checknumber(L, (n))))
344
345// SafeFArg is for places that need to get a number off the lua stack, but
346// can't risk an error being raised. IArg and luaL_optnumber would both raise
347// an error on a type mismatch. -Kyz
348inline auto
349SafeFArg(lua_State* L, int index, std::string const& err, int def) -> int
350{
351 if (lua_isnumber(L, index) != 0) {
352 return static_cast<int>(lua_tonumber(L, index));
353 }
354 LuaHelpers::ReportScriptError(err);
355 return def;
356}
357
358inline auto
359get_optional_double(lua_State* L, int index, char const* field, double def)
360 -> double
361{
362 double ret = def;
363 lua_getfield(L, index, field);
364 if (lua_isnumber(L, -1) != 0) {
365 ret = static_cast<double>(lua_tonumber(L, -1));
366 }
367 lua_pop(L, 1);
368 return ret;
369}
370
371inline auto
372get_optional_int(lua_State* L, int index, char const* field, int def) -> int
373{
374 int ret = def;
375 lua_getfield(L, index, field);
376 if (lua_isnumber(L, -1) != 0) {
377 ret = static_cast<int>(lua_tonumber(L, -1));
378 }
379 lua_pop(L, 1);
380 return ret;
381}
382
383inline auto
384get_optional_bool(lua_State* L, int index, char const* field) -> bool
385{
386 lua_getfield(L, index, field);
387 bool ret = lua_toboolean(L, -1) == 1;
388 lua_pop(L, 1);
389 return ret;
390}
391
392inline auto
393value_is_in_table(lua_State* L, int value_index, int table_index) -> bool
394{
395 lua_pushnil(L);
396 while (lua_next(L, table_index) != 0) {
397 if (lua_equal(L, value_index, -1) != 0) {
398 lua_pop(L, 2);
399 return true;
400 }
401 lua_pop(L, 1);
402 }
403 return false;
404}
405
406#define LuaFunction(func, expr) \
407 \
408 int LuaFunc_##func(lua_State* L); \
409 \
410 int LuaFunc_##func(lua_State* L) \
411 { \
412 LuaHelpers::Push(L, expr); \
413 return 1; \
414 } \
415 \
416 void LuaFunc_Register_##func(lua_State* L); \
417 \
418 void LuaFunc_Register_##func(lua_State* L) \
419 { \
420 lua_register(L, #func, LuaFunc_##func); \
421 } \
422 \
423 REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_##func);
424
425#define LUAFUNC_REGISTER_COMMON(func_name) \
426 \
427 void LuaFunc_Register_##func_name(lua_State* L); \
428 \
429 void LuaFunc_Register_##func_name(lua_State* L) \
430 { \
431 lua_register(L, #func_name, LuaFunc_##func_name); \
432 } \
433 \
434 REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_##func_name);
435
436#endif
Definition LuaManager.h:18
A self-cleaning Lua reference.
Definition LuaReference.h:10
Definition LuaManager.h:238
Definition RageThreads.h:232
Definition XmlFile.h:95
Utilities for working with Lua.
Definition LuaReference.cpp:172
Definition LuaManager.h:289