Client Upload Part 2

RD Core / Commit #5

Commit Client Upload Part 2

Alex Alex committed 19/10/2026 00:06 main Patch
1,244 files +271,215 -0
A RD_Client/src/framework/luaengine/luainterface.h +495-0 View file
@@ -0,0 +1,495 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#ifndef LUAINTERFACE_H
24+#define LUAINTERFACE_H
25+
26+#include "declarations.h"
27+
28+#include <framework/util/stats.h>
29+
30+
31+struct lua_State;
32+typedef int (*LuaCFunction) (lua_State *L);
33+
34+/// Class that manages LUA stuff
35+class LuaInterface
36+{
37+public:
38+ LuaInterface();
39+ ~LuaInterface();
40+
41+ void init();
42+ void terminate();
43+
44+ /// Register core script functions
45+ void registerFunctions();
46+
47+ // functions that will register all script stuff in lua global environment
48+ void registerSingletonClass(const std::string& className);
49+ void registerClass(const std::string& className, const std::string& baseClass = "LuaObject");
50+
51+ void registerClassStaticFunction(const std::string& className,
52+ const std::string& functionName,
53+ const LuaCppFunction& function);
54+
55+ void registerClassMemberFunction(const std::string& className,
56+ const std::string& functionName,
57+ const LuaCppFunction& function);
58+
59+ void registerClassMemberField(const std::string& className,
60+ const std::string& field,
61+ const LuaCppFunction& getFunction,
62+ const LuaCppFunction& setFunction);
63+
64+ void registerGlobalFunction(const std::string& functionName,
65+ const LuaCppFunction& function);
66+
67+ // register shortcuts using templates
68+ template<class C, class B = LuaObject>
69+ void registerClass() {
70+ registerClass(stdext::demangle_class<C>(), stdext::demangle_class<B>());
71+ }
72+
73+ template<class C>
74+ void registerClassStaticFunction(const std::string& functionName, const LuaCppFunction& function) {
75+ registerClassStaticFunction(stdext::demangle_class<C>(), functionName, function);
76+ }
77+
78+ template<class C>
79+ void registerClassMemberFunction(const std::string& functionName, const LuaCppFunction& function) {
80+ registerClassMemberFunction(stdext::demangle_class<C>(), functionName, function);
81+ }
82+
83+ template<class C>
84+ void registerClassMemberField(const std::string& field,
85+ const LuaCppFunction& getFunction,
86+ const LuaCppFunction& setFunction) {
87+ registerClassMemberField(stdext::demangle_class<C>(), field, getFunction, setFunction);
88+ }
89+
90+ // methods for binding functions
91+ template<class C, typename F>
92+ void bindSingletonFunction(const std::string& functionName, F C::*function, C *instance);
93+ template<class C, typename F>
94+ void bindSingletonFunction(const std::string& className, const std::string& functionName, F C::* function, C* instance);
95+ template<typename F>
96+ void bindSingletonFunction(const std::string& className, const std::string& functionName, const F& function);
97+
98+ template<class C, typename F>
99+ void bindClassStaticFunction(const std::string& functionName, const F& function);
100+ template<typename F>
101+ void bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function);
102+
103+ template<class C, typename F, class FC>
104+ void bindClassMemberFunction(const std::string& functionName, F FC::*function);
105+ template<class C, typename F, class FC>
106+ void bindClassMemberFunction(const std::string& className, const std::string& functionName, F FC::*function);
107+
108+ template<class C, typename F1, typename F2, class FC>
109+ void bindClassMemberField(const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction);
110+ template<class C, typename F1, typename F2, class FC>
111+ void bindClassMemberField(const std::string& className, const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction);
112+
113+ template<class C, typename F, class FC>
114+ void bindClassMemberGetField(const std::string& fieldName, F FC::*getFunction);
115+ template<class C, typename F, class FC>
116+ void bindClassMemberGetField(const std::string& className, const std::string& fieldName, F FC::*getFunction);
117+
118+ template<class C, typename F, class FC>
119+ void bindClassMemberSetField(const std::string& fieldName, F FC::*setFunction);
120+ template<class C, typename F, class FC>
121+ void bindClassMemberSetField(const std::string& className, const std::string& fieldName, F FC::*setFunction);
122+
123+ template<typename F>
124+ void bindGlobalFunction(const std::string& functionName, const F& function);
125+
126+private:
127+ /// Metamethod that will retrieve fields values (that include functions) from the object when using '.' or ':'
128+ static int luaObjectGetEvent(LuaInterface* lua);
129+ /// Metamethod that is called when setting a field of the object by using the keyword '='
130+ static int luaObjectSetEvent(LuaInterface* lua);
131+ /// Metamethod that will check equality of objects by using the keyword '=='
132+ static int luaObjectEqualEvent(LuaInterface* lua);
133+ /// Metamethod that is called every two lua garbage collections
134+ /// for any LuaObject that have no references left in lua environment
135+ /// anymore, thus this creates the possibility of holding an object
136+ /// existence by lua until it got no references left
137+ static int luaObjectCollectEvent(LuaInterface* lua);
138+
139+public:
140+ /// Loads and runs a script, any errors are printed to stdout and returns false
141+ bool safeRunScript(const std::string& fileName);
142+
143+ /// Loads and runs a script
144+ /// @exception LuaException is thrown on any lua error
145+ void runScript(const std::string& fileName);
146+
147+ /// Loads and runs the script from buffer
148+ /// @exception LuaException is thrown on any lua error
149+ void runBuffer(const std::string& buffer, const std::string& source);
150+
151+ /// Loads a script file and pushes it's main function onto stack,
152+ /// @exception LuaException is thrown on any lua error
153+ void loadScript(const std::string& fileName);
154+
155+ /// Loads a function from buffer and pushes it onto stack,
156+ /// @exception LuaException is thrown on any lua error
157+ void loadFunction(const std::string& buffer, const std::string& source = "lua function buffer");
158+
159+ /// Evaluates a lua expression and pushes the result value onto the stack
160+ /// @exception LuaException is thrown on any lua error
161+ void evaluateExpression(const std::string& expression, const std::string& source = "lua expression");
162+
163+ /// Generates a traceback message for the current call stack
164+ /// @param errorMessage is an additional error message
165+ /// @param level is the level of the traceback, 0 means trace from calling function
166+ /// @return the generated traceback message
167+ std::string traceback(const std::string& errorMessage = "", int level = 0);
168+
169+ /// Throw a lua error if inside a lua call or generates an C++ stdext::exception
170+ /// @param message is the error message wich will be displayed before the error traceback
171+ /// @exception stdext::exception is thrown with the error message if the error is not captured by lua
172+ void throwError(const std::string& message);
173+
174+ /// Searches for the source of the current running function
175+ std::string getCurrentSourcePath(int level = 0);
176+
177+ /// gets current function name
178+ std::string getCurrentFunction(int level = 0);
179+
180+ /// @brief Calls a function
181+ /// The function and arguments must be on top of the stack in order,
182+ /// results are pushed onto the stack.
183+ /// @exception LuaException is thrown on any lua error
184+ /// @return number of results
185+ int safeCall(int numArgs = 0, int numRets = -1, const std::shared_ptr<std::string>& error = nullptr);
186+
187+ /// Same as safeCall but catches exceptions and can also calls a table of functions,
188+ /// if any error occurs it will be reported to stdout and returns 0 results
189+ /// @param requestedResults is the number of results requested to pushes onto the stack,
190+ /// if supplied, the call will always pushes that number of results, even if it fails
191+ int signalCall(int numArgs = 0, int numRets = -1);
192+
193+ /// @brief Creates a new environment table
194+ /// The new environment table is redirected to the global environment (aka _G),
195+ /// this allows to access global variables from _G in the new environment and
196+ /// prevents new variables in this new environment to be set on the global environment
197+ int newSandboxEnv();
198+
199+ template<typename... T>
200+ int luaCallGlobalField(const std::string& global, const std::string& field, const T&... args);
201+
202+ template<typename... T>
203+ void callGlobalField(const std::string& global, const std::string& field, const T&... args);
204+
205+ template<typename R, typename... T>
206+ R callGlobalField(const std::string& global, const std::string& field, const T&... args);
207+
208+ bool isInCppCallback() { return m_cppCallbackDepth != 0; }
209+
210+private:
211+ /// Load scripts requested by lua 'require'
212+ static int luaScriptLoader(lua_State* L);
213+ /// Run scripts requested by lua 'dofile'
214+ static int lua_dofile(lua_State* L);
215+ /// Run scripts requested by lua 'dofiles'
216+ static int lua_dofiles(lua_State* L);
217+ /// Run scripts requested by lua 'dofiles'
218+ static int lua_loadfile(lua_State* L);
219+ /// Handle lua errors from safeCall
220+ static int luaErrorHandler(lua_State* L);
221+ /// Handle bound cpp functions callbacks
222+ static int luaCppFunctionCallback(lua_State* L);
223+ /// Collect bound cpp function pointers
224+ static int luaCollectCppFunction(lua_State* L);
225+
226+public:
227+ void createLuaState();
228+ void closeLuaState();
229+
230+ void collectGarbage();
231+
232+ void loadBuffer(const std::string& buffer, const std::string& source);
233+
234+ std::string generateByteCode(const std::string & buffer, std::string source);
235+
236+ int pcall(int numArgs = 0, int numRets = 0, int errorFuncIndex = 0);
237+ void call(int numArgs = 0, int numRets = 0);
238+ void error();
239+
240+ int ref();
241+ int weakRef();
242+ void unref(int ref);
243+ void useValue() { pushValue(); ref(); }
244+
245+ const char* typeName(int index = -1);
246+ std::string functionSourcePath();
247+ std::string functionSource();
248+
249+ void insert(int index);
250+ void remove(int index);
251+ bool next(int index = -2);
252+
253+ void checkStack() { VALIDATE(getTop() <= 20); }
254+ void getStackFunction(int level = 0);
255+
256+ void getRef(int ref);
257+ void getWeakRef(int weakRef);
258+
259+ int getGlobalEnvironment() { return m_globalEnv; }
260+ void setGlobalEnvironment(int env);
261+ void resetGlobalEnvironment() { setGlobalEnvironment(m_globalEnv); }
262+
263+ void setMetatable(int index = -2);
264+ void getMetatable(int index = -1);
265+
266+ void getField(const char* key, int index = -1);
267+ void getField(const std::string& key, int index = -1) { return getField(key.c_str(), index); }
268+ void setField(const char* key, int index = -2);
269+ void setField(const std::string& key, int index = -2) { return setField(key.c_str(), index); }
270+
271+ void getTable(int index = -2);
272+ void setTable(int index = -3);
273+ void clearTable(int index = -1);
274+
275+ void getEnv(int index = -1);
276+ void setEnv(int index = -2);
277+
278+ void getGlobal(const std::string& key);
279+ void getGlobalField(const std::string& globalKey, const std::string& fieldKey);
280+ void setGlobal(const std::string& key);
281+
282+ void rawGet(int index = -1);
283+ void rawGeti(int n, int index = -1);
284+ void rawSet(int index = -3);
285+ void rawSeti(int n, int index = -2);
286+
287+ void newTable();
288+ void createTable(int narr, int nrec);
289+ void* newUserdata(int size);
290+
291+ void pop(int n = 1);
292+ long popInteger();
293+ double popNumber();
294+ bool popBoolean();
295+ std::string popString();
296+ void* popUserdata();
297+ void* popUpvalueUserdata();
298+ LuaObjectPtr popObject();
299+
300+ void pushNil();
301+ void pushInteger(long v);
302+ void pushNumber(double v);
303+ void pushBoolean(bool v);
304+ void pushCString(const char* v);
305+ void pushString(const std::string& v);
306+ void pushLightUserdata(void* p);
307+ void pushThread();
308+ void pushValue(int index = -1);
309+ void pushObject(const LuaObjectPtr& obj);
310+ void pushCFunction(LuaCFunction func, int n = 0);
311+ void pushCppFunction(const LuaCppFunction& func);
312+
313+ bool isNil(int index = -1);
314+ bool isBoolean(int index = -1);
315+ bool isNumber(int index = -1);
316+ bool isString(int index = -1);
317+ bool isTable(int index = -1);
318+ bool isFunction(int index = -1);
319+ bool isCFunction(int index = -1);
320+ bool isLuaFunction(int index = -1) { return (isFunction() && !isCFunction()); }
321+ bool isUserdata(int index = -1);
322+
323+ bool toBoolean(int index = -1);
324+ int toInteger(int index = -1);
325+ double toNumber(int index = -1);
326+ const char* toCString(int index = -1);
327+ std::string toString(int index = -1);
328+ void* toUserdata(int index = -1);
329+ LuaObjectPtr toObject(int index = -1);
330+
331+ int getTop();
332+ int stackSize() { return getTop(); }
333+ void clearStack() { pop(stackSize()); }
334+ bool hasIndex(int index) { return (stackSize() >= (index < 0 ? -index : index) && index != 0); }
335+
336+ std::string getSource(int level = 2);
337+
338+ void loadFiles(std::string directory, bool recursive = false, std::string contains = "");
339+
340+ /// Pushes any type onto the stack
341+ template<typename T, typename... Args>
342+ int polymorphicPush(const T& v, const Args&... args);
343+ int polymorphicPush() { return 0; }
344+
345+ /// Casts a value from stack to any type
346+ /// @exception LuaBadValueCastException thrown if the cast fails
347+ template<class T>
348+ T castValue(int index = -1);
349+
350+ /// Same as castValue but also pops
351+ template<class T>
352+ T polymorphicPop() { T v = castValue<T>(); pop(1); return v; }
353+
354+private:
355+ lua_State* L;
356+ int m_weakTableRef;
357+ int m_cppCallbackDepth;
358+ int m_totalObjRefs;
359+ int m_totalFuncRefs;
360+ int m_globalEnv;
361+};
362+
363+extern LuaInterface g_lua;
364+
365+// must be included after, because they need LuaInterface fully declared
366+#include "luaexception.h"
367+#include "luabinder.h"
368+#include "luavaluecasts.h"
369+
370+template<typename T, typename... Args>
371+int LuaInterface::polymorphicPush(const T& v, const Args&... args) {
372+ int r = push_luavalue(v);
373+ return r + polymorphicPush(args...);
374+}
375+
376+// next templates must be defined after above includes
377+
378+template<class C, typename F>
379+void LuaInterface::bindSingletonFunction(const std::string& functionName, F C::*function, C *instance) {
380+ registerClassStaticFunction<C>(functionName, luabinder::bind_singleton_mem_fun(function, instance));
381+}
382+
383+template<class C, typename F>
384+void LuaInterface::bindSingletonFunction(const std::string& className, const std::string& functionName, F C::*function, C *instance) {
385+ registerClassStaticFunction(className, functionName, luabinder::bind_singleton_mem_fun(function, instance));
386+}
387+
388+template<typename F>
389+void LuaInterface::bindSingletonFunction(const std::string& className, const std::string& functionName, const F& function)
390+{
391+ registerClassStaticFunction(className, functionName, luabinder::bind_fun(function));
392+}
393+
394+template<class C, typename F>
395+void LuaInterface::bindClassStaticFunction(const std::string& functionName, const F& function) {
396+ registerClassStaticFunction<C>(functionName, luabinder::bind_fun(function));
397+}
398+template<typename F>
399+void LuaInterface::bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function) {
400+ registerClassStaticFunction(className, functionName, luabinder::bind_fun(function));
401+}
402+
403+template<class C, typename F, class FC>
404+void LuaInterface::bindClassMemberFunction(const std::string& functionName, F FC::*function) {
405+ registerClassMemberFunction<C>(functionName, luabinder::bind_mem_fun<C>(function));
406+}
407+template<class C, typename F, class FC>
408+void LuaInterface::bindClassMemberFunction(const std::string& className, const std::string& functionName, F FC::*function) {
409+ registerClassMemberFunction(className, functionName, luabinder::bind_mem_fun<C>(function));
410+}
411+
412+template<class C, typename F1, typename F2, class FC>
413+void LuaInterface::bindClassMemberField(const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction) {
414+ registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun<C>(getFunction), luabinder::bind_mem_fun<C>(setFunction));
415+}
416+template<class C, typename F1, typename F2, class FC>
417+void LuaInterface::bindClassMemberField(const std::string& className, const std::string& fieldName, F1 FC::*getFunction, F2 FC::*setFunction) {
418+ registerClassMemberField(className, fieldName, luabinder::bind_mem_fun<C>(getFunction), luabinder::bind_mem_fun<C>(setFunction));
419+}
420+
421+template<class C, typename F, class FC>
422+void LuaInterface::bindClassMemberGetField(const std::string& fieldName, F FC::*getFunction) {
423+ registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun<C>(getFunction), LuaCppFunction());
424+}
425+template<class C, typename F, class FC>
426+void LuaInterface::bindClassMemberGetField(const std::string& className, const std::string& fieldName, F FC::*getFunction) {
427+ registerClassMemberField(className, fieldName, luabinder::bind_mem_fun<C>(getFunction), LuaCppFunction());
428+}
429+
430+template<class C, typename F, class FC>
431+void LuaInterface::bindClassMemberSetField(const std::string& fieldName, F FC::*setFunction) {
432+ registerClassMemberField<C>(fieldName, LuaCppFunction(), luabinder::bind_mem_fun<C>(setFunction));
433+}
434+template<class C, typename F, class FC>
435+void LuaInterface::bindClassMemberSetField(const std::string& className, const std::string& fieldName, F FC::*setFunction) {
436+ registerClassMemberField(className, fieldName, LuaCppFunction(), luabinder::bind_mem_fun<C>(setFunction));
437+}
438+
439+template<typename F>
440+void LuaInterface::bindGlobalFunction(const std::string& functionName, const F& function) {
441+ registerGlobalFunction(functionName, luabinder::bind_fun(function));
442+}
443+
444+template<class T>
445+T LuaInterface::castValue(int index) {
446+ T o;
447+ if (!luavalue_cast(index, o))
448+ throw LuaBadValueCastException(typeName(index), stdext::demangle_type<T>());
449+ return o;
450+}
451+
452+bool luavalue_cast(int index, Size &value);
453+bool luavalue_cast(int index, Point &value);
454+bool luavalue_cast(int index, Rect &value);
455+bool luavalue_cast(int index, Color &value);
456+bool luavalue_cast(int index, std::string &value);
457+bool luavalue_cast(int index, uint64 &value);
458+
459+// Otras sobrecargas de luavalue_cast...
460+
461+template<typename... T>
462+int LuaInterface::luaCallGlobalField(const std::string& global, const std::string& field, const T&... args) {
463+ AutoStat s(STATS_LUA, std::string(global) + ":" + field);
464+
465+ g_lua.getGlobalField(global, field);
466+ int ret = 0;
467+
468+ if(!g_lua.isNil()) {
469+ int numArgs = g_lua.polymorphicPush(args...);
470+ ret = g_lua.signalCall(numArgs);
471+ } else
472+ g_lua.pop(1);
473+ return ret;
474+}
475+
476+template<typename... T>
477+void LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) {
478+ int rets = luaCallGlobalField(global, field, args...);
479+ if(rets > 0)
480+ pop(rets);
481+}
482+
483+template<typename R, typename... T>
484+R LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) {
485+ R result;
486+ int rets = luaCallGlobalField(global, field, args...);
487+ if(rets > 0) {
488+ VALIDATE(rets == 1);
489+ result = g_lua.polymorphicPop<R>();
490+ } else
491+ result = R();
492+ return result;
493+}
494+
495+#endif
A RD_Client/src/framework/luaengine/luaobject.cpp +123-0 View file
@@ -0,0 +1,123 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#include "luaobject.h"
24+#include "luainterface.h"
25+
26+#include <typeinfo>
27+#include <framework/core/application.h>
28+
29+LuaObject::LuaObject() :
30+ m_fieldsTableRef(-1)
31+{
32+}
33+
34+LuaObject::~LuaObject()
35+{
36+ VALIDATE(!g_app.isTerminated());
37+ releaseLuaFieldsTable();
38+}
39+
40+bool LuaObject::hasLuaField(const std::string& field)
41+{
42+ bool ret = false;
43+ if(m_fieldsTableRef != -1) {
44+ g_lua.getRef(m_fieldsTableRef);
45+ g_lua.getField(field); // push the field value
46+ ret = !g_lua.isNil();
47+ g_lua.pop(2);
48+ }
49+ return ret;
50+}
51+
52+void LuaObject::releaseLuaFieldsTable()
53+{
54+ if(m_fieldsTableRef != -1) {
55+ g_lua.unref(m_fieldsTableRef);
56+ m_fieldsTableRef = -1;
57+ }
58+}
59+
60+void LuaObject::luaSetField(const std::string& key)
61+{
62+ // create fields table on the fly
63+ if(m_fieldsTableRef == -1) {
64+ g_lua.newTable(); // create fields table
65+ m_fieldsTableRef = g_lua.ref(); // save a reference for it
66+ }
67+
68+ g_lua.getRef(m_fieldsTableRef); // push the table
69+ g_lua.insert(-2); // move the value to the top
70+ g_lua.setField(key); // set the field
71+ g_lua.pop(); // pop the fields table
72+}
73+
74+void LuaObject::luaGetField(const std::string& key)
75+{
76+ if(m_fieldsTableRef != -1) {
77+ g_lua.getRef(m_fieldsTableRef); // push the obj's fields table
78+ g_lua.getField(key); // push the field value
79+ g_lua.remove(-2); // remove the table
80+ } else {
81+ g_lua.pushNil();
82+ }
83+}
84+
85+void LuaObject::luaGetMetatable()
86+{
87+ static std::unordered_map<const std::type_info*, int> metatableMap;
88+ const std::type_info& tinfo = typeid(*this);
89+ auto it = metatableMap.find(&tinfo);
90+
91+ int metatableRef;
92+ if(it == metatableMap.end()) {
93+ g_lua.getGlobal(getClassName() + "_mt");
94+ metatableRef = g_lua.ref();
95+ metatableMap[&tinfo] = metatableRef;
96+ } else
97+ metatableRef = it->second;
98+
99+ g_lua.getRef(metatableRef);
100+}
101+
102+void LuaObject::luaGetFieldsTable()
103+{
104+ if(m_fieldsTableRef != -1)
105+ g_lua.getRef(m_fieldsTableRef);
106+ else
107+ g_lua.pushNil();
108+}
109+
110+int LuaObject::getUseCount()
111+{
112+ return ref_count();
113+}
114+
115+std::string LuaObject::getClassName()
116+{
117+ // TODO: this could be cached for more performance
118+#ifdef _MSC_VER
119+ return stdext::demangle_name(typeid(*this).name()) + 6;
120+#else
121+ return stdext::demangle_name(typeid(*this).name());
122+#endif
123+}
A RD_Client/src/framework/luaengine/luaobject.h +208-0 View file
@@ -0,0 +1,208 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#ifndef LUAOBJECT_H
24+#define LUAOBJECT_H
25+
26+#include <framework/util/stats.h>
27+#include "declarations.h"
28+
29+/// LuaObject, all script-able classes have it as base
30+// @bindclass
31+class LuaObject : public stdext::shared_object
32+{
33+public:
34+ LuaObject();
35+ virtual ~LuaObject();
36+
37+ template<typename T>
38+ void connectLuaField(const std::string& field, const std::function<T>& f, bool pushFront = false);
39+
40+ /// Calls a function or table of functions stored in a lua field, results are pushed onto the stack,
41+ /// if any lua error occurs, it will be reported to stdout and return 0 results
42+ /// @return the number of results
43+ template<typename... T>
44+ int luaCallLuaField(const std::string& field, const T&... args);
45+
46+ template<typename R, typename... T>
47+ R callLuaField(const std::string& field, const T&... args);
48+ template<typename... T>
49+ void callLuaField(const std::string& field, const T&... args);
50+
51+ /// Returns true if the lua field exists
52+ bool hasLuaField(const std::string& field);
53+
54+ /// Sets a field in this lua object
55+ template<typename T>
56+ void setLuaField(const std::string& key, const T& value);
57+
58+ /// Gets a field from this lua object
59+ template<typename T>
60+ T getLuaField(const std::string& key);
61+
62+ /// Release fields table reference
63+ void releaseLuaFieldsTable();
64+
65+ /// Sets a field from this lua object, the value must be on the stack
66+ void luaSetField(const std::string& key);
67+
68+ /// Gets a field from this lua object, the result is pushed onto the stack
69+ void luaGetField(const std::string& key);
70+
71+ /// Get object's metatable
72+ void luaGetMetatable();
73+
74+ /// Gets the table containing all stored fields of this lua object, the result is pushed onto the stack
75+ void luaGetFieldsTable();
76+
77+ /// Returns the number of references of this object
78+ /// @note each userdata of this object on lua counts as a reference
79+ int getUseCount();
80+
81+ /// Returns the derived class name, its the same name used in Lua
82+ std::string getClassName();
83+
84+ LuaObjectPtr asLuaObject() { return static_self_cast<LuaObject>(); }
85+
86+ void operator=(const LuaObject& other) { }
87+
88+private:
89+ int m_fieldsTableRef;
90+};
91+
92+template<typename F>
93+void connect(const LuaObjectPtr& obj, const std::string& field, const std::function<F>& f, bool pushFront = false);
94+
95+template<typename Lambda>
96+typename std::enable_if<std::is_constructible<decltype(&Lambda::operator())>::value, void>::type
97+connect(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront = false);
98+
99+#include "luainterface.h"
100+
101+template<typename T>
102+void LuaObject::connectLuaField(const std::string& field, const std::function<T>& f, bool pushFront)
103+{
104+ luaGetField(field);
105+ if(g_lua.isTable()) {
106+ if(pushFront)
107+ g_lua.pushInteger(1);
108+ push_luavalue(f);
109+ g_lua.callGlobalField("table","insert");
110+ } else {
111+ if(g_lua.isNil()) {
112+ push_luavalue(f);
113+ luaSetField(field);
114+ g_lua.pop();
115+ } else if(g_lua.isFunction()) {
116+ g_lua.newTable();
117+ g_lua.insert(-2);
118+ g_lua.rawSeti(1);
119+ push_luavalue(f);
120+ g_lua.rawSeti(2);
121+ luaSetField(field);
122+ }
123+ }
124+}
125+
126+// connect for std::function
127+template<typename F>
128+void connect(const LuaObjectPtr& obj, const std::string& field, const std::function<F>& f, bool pushFront) {
129+ obj->connectLuaField<F>(field, f, pushFront);
130+}
131+
132+namespace luabinder {
133+ template<typename F>
134+ struct connect_lambda;
135+
136+ template<typename Lambda, typename Ret, typename... Args>
137+ struct connect_lambda<Ret(Lambda::*)(Args...) const> {
138+ static void call(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront) {
139+ connect(obj, field, std::function<Ret(Args...)>(f), pushFront);
140+ }
141+ };
142+};
143+
144+// connect for lambdas
145+template<typename Lambda>
146+typename std::enable_if<std::is_constructible<decltype(&Lambda::operator())>::value, void>::type
147+connect(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront) {
148+ typedef decltype(&Lambda::operator()) F;
149+ luabinder::connect_lambda<F>::call(obj, field, f, pushFront);
150+}
151+
152+template<typename... T>
153+int LuaObject::luaCallLuaField(const std::string& field, const T&... args) {
154+ AutoStat s(STATS_LUA, getClassName() + ":" + field);
155+
156+ // note that the field must be retrieved from this object lua value
157+ // to force using the __index metamethod of it's metatable
158+ // so cannot use LuaObject::getField here
159+ // push field
160+ //AutoStat s(STATS_LUA, field);
161+ g_lua.pushObject(asLuaObject());
162+ g_lua.getField(field);
163+
164+ int ret = 0;
165+ if(!g_lua.isNil()) {
166+ // the first argument is always this object (self)
167+ g_lua.insert(-2);
168+ int numArgs = g_lua.polymorphicPush(args...);
169+ ret = g_lua.signalCall(1 + numArgs);
170+ } else {
171+ g_lua.pop(2);
172+ }
173+
174+ return ret;
175+}
176+
177+template<typename R, typename... T>
178+R LuaObject::callLuaField(const std::string& field, const T&... args) {
179+ R result;
180+ int rets = luaCallLuaField(field, args...);
181+ if(rets > 0) {
182+ VALIDATE(rets == 1);
183+ result = g_lua.polymorphicPop<R>();
184+ } else
185+ result = R();
186+ return result;
187+}
188+
189+template<typename... T>
190+void LuaObject::callLuaField(const std::string& field, const T&... args) {
191+ int rets = luaCallLuaField(field, args...);
192+ if(rets > 0)
193+ g_lua.pop(rets);
194+}
195+
196+template<typename T>
197+void LuaObject::setLuaField(const std::string& key, const T& value) {
198+ g_lua.polymorphicPush(value);
199+ luaSetField(key);
200+}
201+
202+template<typename T>
203+T LuaObject::getLuaField(const std::string& key) {
204+ luaGetField(key);
205+ return g_lua.polymorphicPop<T>();
206+}
207+
208+#endif
A RD_Client/src/framework/luaengine/luavaluecasts.cpp +335-0 View file
@@ -0,0 +1,335 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#include "luavaluecasts.h"
24+#include "luainterface.h"
25+#include <framework/otml/otmlnode.h>
26+
27+// bool
28+int push_luavalue(bool b)
29+{
30+ g_lua.pushBoolean(b);
31+ return 1;
32+}
33+
34+bool luavalue_cast(int index, bool& b)
35+{
36+ b = g_lua.toBoolean(index);
37+ return true;
38+}
39+
40+// int
41+int push_luavalue(int i)
42+{
43+ g_lua.pushInteger(i);
44+ return 1;
45+}
46+
47+bool luavalue_cast(int index, int& i)
48+{
49+ i = g_lua.toInteger(index);
50+ if(i == 0 && !g_lua.isNumber(index) && !g_lua.isNil())
51+ return false;
52+ return true;
53+}
54+
55+// double
56+int push_luavalue(double d)
57+{
58+ g_lua.pushNumber(d);
59+ return 1;
60+}
61+
62+bool luavalue_cast(int index, double& d)
63+{
64+ d = g_lua.toNumber(index);
65+ if(d == 0 && !g_lua.isNumber(index) && !g_lua.isNil())
66+ return false;
67+ return true;
68+}
69+
70+// string
71+int push_luavalue(const char* cstr)
72+{
73+ g_lua.pushCString(cstr);
74+ return 1;
75+}
76+
77+int push_luavalue(const std::string& str)
78+{
79+ g_lua.pushString(str);
80+ return 1;
81+}
82+
83+bool luavalue_cast(int index, std::string& str)
84+{
85+ str = g_lua.toString(index);
86+ return true;
87+}
88+
89+// lua cpp function
90+int push_luavalue(const LuaCppFunction& func)
91+{
92+ g_lua.pushCppFunction(func);
93+ return 1;
94+}
95+
96+// color
97+int push_luavalue(const Color& color)
98+{
99+ g_lua.createTable(0, 4);
100+ g_lua.pushInteger(color.r());
101+ g_lua.setField("r");
102+ g_lua.pushInteger(color.g());
103+ g_lua.setField("g");
104+ g_lua.pushInteger(color.b());
105+ g_lua.setField("b");
106+ g_lua.pushInteger(color.a());
107+ g_lua.setField("a");
108+ return 1;
109+}
110+
111+bool luavalue_cast(int index, Color& color)
112+{
113+ if(g_lua.isTable(index)) {
114+ g_lua.getField("r", index);
115+ color.setRed((int)g_lua.popInteger());
116+ g_lua.getField("g", index);
117+ color.setGreen((int)g_lua.popInteger());
118+ g_lua.getField("b", index);
119+ color.setBlue((int)g_lua.popInteger());
120+ g_lua.getField("a", index);
121+ color.setAlpha((int)g_lua.popInteger());
122+ return true;
123+ } else if(g_lua.isString()) {
124+ return stdext::cast(g_lua.toString(index), color);
125+ } else if(g_lua.isNil()) {
126+ color = Color::white;
127+ return true;
128+ }
129+ return false;
130+}
131+
132+// rect
133+int push_luavalue(const Rect& rect)
134+{
135+ g_lua.createTable(0, 4);
136+ g_lua.pushInteger(rect.x());
137+ g_lua.setField("x");
138+ g_lua.pushInteger(rect.y());
139+ g_lua.setField("y");
140+ g_lua.pushInteger(rect.width());
141+ g_lua.setField("width");
142+ g_lua.pushInteger(rect.height());
143+ g_lua.setField("height");
144+ return 1;
145+}
146+
147+bool luavalue_cast(int index, Rect& rect)
148+{
149+ if(g_lua.isTable(index)) {
150+ g_lua.getField("x", index);
151+ rect.setX(g_lua.popInteger());
152+ g_lua.getField("y", index);
153+ rect.setY(g_lua.popInteger());
154+ g_lua.getField("width", index);
155+ rect.setWidth(g_lua.popInteger());
156+ g_lua.getField("height", index);
157+ rect.setHeight(g_lua.popInteger());
158+ return true;
159+ } else if(g_lua.isString()) {
160+ return stdext::cast(g_lua.toString(index), rect);
161+ } else if(g_lua.isNil()) {
162+ rect = Rect();
163+ return true;
164+ }
165+ return false;
166+}
167+
168+// point
169+int push_luavalue(const Point& point)
170+{
171+ g_lua.createTable(0, 2);
172+ g_lua.pushInteger(point.x);
173+ g_lua.setField("x");
174+ g_lua.pushInteger(point.y);
175+ g_lua.setField("y");
176+ return 1;
177+}
178+
179+bool luavalue_cast(int index, Point& point)
180+{
181+ if(g_lua.isTable(index)) {
182+ g_lua.getField("x", index);
183+ point.x = g_lua.popInteger();
184+ g_lua.getField("y", index);
185+ point.y = g_lua.popInteger();
186+ return true;
187+ } else if(g_lua.isString()) {
188+ return stdext::cast(g_lua.toString(index), point);
189+ } else if(g_lua.isNil()) {
190+ point = Point();
191+ return true;
192+ }
193+ return false;
194+}
195+
196+// size
197+int push_luavalue(const Size& size)
198+{
199+ g_lua.createTable(0, 2);
200+ g_lua.pushInteger(size.width());
201+ g_lua.setField("width");
202+ g_lua.pushInteger(size.height());
203+ g_lua.setField("height");
204+ return 1;
205+}
206+
207+bool luavalue_cast(int index, Size& size)
208+{
209+ if(g_lua.isTable(index)) {
210+ g_lua.getField("width", index);
211+ size.setWidth(g_lua.popInteger());
212+ g_lua.getField("height", index);
213+ size.setHeight(g_lua.popInteger());
214+ return true;
215+ } else if(g_lua.isString()) {
216+ return stdext::cast(g_lua.toString(index), size);
217+ } else if(g_lua.isNil()) {
218+ size = Size();
219+ return true;
220+ }
221+ return false;
222+}
223+
224+// otml nodes
225+void push_otml_subnode_luavalue(const OTMLNodePtr& node)
226+{
227+ if(node->hasValue()) {
228+ union {
229+ bool b;
230+ double d;
231+ long l;
232+ };
233+ std::string value = node->rawValue();
234+ if(stdext::cast(value, b))
235+ g_lua.pushBoolean(b);
236+ else if(stdext::cast(value, l))
237+ g_lua.pushInteger(l);
238+ else if(stdext::cast(value, d))
239+ g_lua.pushNumber(d);
240+ else
241+ g_lua.pushString(value);
242+ } else if(node->hasChildren()) {
243+ g_lua.newTable();
244+ bool pushedChild = false;
245+ int currentIndex = 1;
246+ for(const OTMLNodePtr& cnode : node->children()) {
247+ push_otml_subnode_luavalue(cnode);
248+ if(!g_lua.isNil()) {
249+ if(cnode->isUnique()) {
250+ g_lua.pushString(cnode->tag());
251+ g_lua.insert(-2);
252+ g_lua.rawSet();
253+ } else
254+ g_lua.rawSeti(currentIndex++);
255+ pushedChild = true;
256+ } else
257+ g_lua.pop();
258+ }
259+ if(!pushedChild) {
260+ g_lua.pop();
261+ g_lua.pushNil();
262+ }
263+ } else
264+ g_lua.pushNil();
265+}
266+
267+int push_luavalue(const OTMLNodePtr& node)
268+{
269+ if(node) {
270+ g_lua.newTable();
271+ int currentIndex = 1;
272+ for(const OTMLNodePtr& cnode : node->children()) {
273+ push_otml_subnode_luavalue(cnode);
274+ if(cnode->isUnique() && !cnode->tag().empty()) {
275+ g_lua.setField(cnode->tag());
276+ } else
277+ g_lua.rawSeti(currentIndex++);
278+ }
279+ } else
280+ g_lua.pushNil();
281+ return 1;
282+}
283+
284+bool luavalue_cast(int index, OTMLNodePtr& node)
285+{
286+ node = OTMLNode::create();
287+ node->setUnique(true);
288+ if(g_lua.isTable(index)) {
289+ g_lua.pushNil();
290+ while(g_lua.next(index < 0 ? index-1 : index)) {
291+ std::string cnodeName;
292+ if(g_lua.isString(-2)) {
293+ g_lua.pushValue(-2);
294+ cnodeName = g_lua.toString();
295+ g_lua.pop();
296+ } else
297+ VALIDATE(g_lua.isNumber());
298+ if(g_lua.isTable()) {
299+ OTMLNodePtr cnode;
300+ if(luavalue_cast(-1, cnode)) {
301+ if(cnodeName.empty())
302+ cnode->setUnique(false);
303+ else
304+ cnode->setTag(cnodeName);
305+ node->addChild(cnode);
306+ }
307+ } else {
308+ std::string value;
309+ if(g_lua.isBoolean())
310+ value = stdext::unsafe_cast<std::string>(g_lua.toBoolean());
311+ else
312+ value = g_lua.toString();
313+ if(cnodeName.empty())
314+ node->writeIn(value);
315+ else
316+ node->writeAt(cnodeName, value);
317+ }
318+ g_lua.pop();
319+ }
320+ return true;
321+ }
322+ return false;
323+}
324+
325+// object ptr
326+bool luavalue_cast(int index, LuaObjectPtr& obj) {
327+ if(g_lua.isUserdata(index)) {
328+ obj = g_lua.toObject(index);
329+ return true;
330+ } else if(g_lua.isNil(index)) {
331+ obj = nullptr;
332+ return true;
333+ }
334+ return false;
335+}
Top