From 6bce0bd680119cfc0ca48be1762e70f16ce5a307 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Thu, 5 Jul 2012 09:38:48 -0300 Subject: [PATCH] Imrove lua engine * Allow bound C++ functions to return multiples values to lua with tuples --- modules/game_interface/gameinterface.lua | 2 +- modules/game_minimap/minimap.lua | 8 +- src/framework/luascript/luabinder.h | 4 +- src/framework/luascript/luainterface.h | 14 +-- src/framework/luascript/luaobject.h | 4 +- src/framework/luascript/luavaluecasts.cpp | 33 ++++-- src/framework/luascript/luavaluecasts.h | 129 ++++++++++++++-------- src/otclient/const.h | 8 ++ src/otclient/core/map.cpp | 34 ++++-- src/otclient/core/map.h | 2 +- src/otclient/luascript/luavaluecasts.cpp | 6 +- src/otclient/luascript/luavaluecasts.h | 4 +- 12 files changed, 164 insertions(+), 84 deletions(-) diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index fb6e930c..13a1c402 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -371,7 +371,7 @@ function GameInterface.processMouseAction(menuPosition, mouseButton, autoWalkPos end if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then - local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), autoWalkPos, 255) + local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), autoWalkPos, 127) if #dirs == 0 then TextMessage.displayStatus(tr('There is no way.')) return true diff --git a/modules/game_minimap/minimap.lua b/modules/game_minimap/minimap.lua index 2c7964d7..fb7542d5 100644 --- a/modules/game_minimap/minimap.lua +++ b/modules/game_minimap/minimap.lua @@ -11,7 +11,7 @@ minimapFirstLoad = true function onMinimapMouseRelease(self, mousePosition, mouseButton) local tile = self:getTile(mousePosition) if tile and mouseButton == MouseLeftButton and self:isPressed() then - local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), tile:getPosition(), 255) + local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), tile:getPosition(), 127) if #dirs == 0 then TextMessage.displayStatus(tr('There is no way.')) return true @@ -47,8 +47,8 @@ function Minimap.init() minimapWidget:setMultifloor(false) minimapWidget:setKeepAspectRatio(false) minimapWidget.onMouseRelease = onMinimapMouseRelease - minimapWidget.onMouseWheel = onMinimapMouseWheel - + minimapWidget.onMouseWheel = onMinimapMouseWheel + Minimap.reset() -- load only the first time (avoid load/save between reloads) @@ -127,7 +127,7 @@ function Minimap.compassClick(self, mousePos) break end end - + if center then local player = g_game.getLocalPlayer() if not player then return end diff --git a/src/framework/luascript/luabinder.h b/src/framework/luascript/luabinder.h index 58d1dc5f..6155e34b 100644 --- a/src/framework/luascript/luabinder.h +++ b/src/framework/luascript/luabinder.h @@ -63,8 +63,8 @@ namespace luabinder typename std::enable_if::value, int>::type call_fun_and_push_result(const F& f, LuaInterface* lua, const Args&... args) { Ret ret = f(args...); - lua->polymorphicPush(ret); - return 1; + int numRets = lua->polymorphicPush(ret); + return numRets; } /// C++ void function caller diff --git a/src/framework/luascript/luainterface.h b/src/framework/luascript/luainterface.h index bb4509c2..cc48edc2 100644 --- a/src/framework/luascript/luainterface.h +++ b/src/framework/luascript/luainterface.h @@ -316,8 +316,8 @@ public: /// Pushes any type onto the stack template - void polymorphicPush(T v, Args... args); - void polymorphicPush() { } + int polymorphicPush(T v, Args... args); + int polymorphicPush() { return 0; } /// Casts a value from stack to any type /// @exception LuaBadValueCastException thrown if the cast fails @@ -344,9 +344,9 @@ extern LuaInterface g_lua; #include "luavaluecasts.h" template -void LuaInterface::polymorphicPush(T v, Args... args) { - push_luavalue(v); - polymorphicPush(args...); +int LuaInterface::polymorphicPush(T v, Args... args) { + int r = push_luavalue(v); + return r + polymorphicPush(args...); } // next templates must be defined after above includes @@ -423,8 +423,8 @@ template int LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) { g_lua.getGlobalField(global, field); if(!g_lua.isNil()) { - g_lua.polymorphicPush(args...); - return g_lua.signalCall(sizeof...(args)); + int numArgs = g_lua.polymorphicPush(args...); + return g_lua.signalCall(numArgs); } else g_lua.pop(1); return 0; diff --git a/src/framework/luascript/luaobject.h b/src/framework/luascript/luaobject.h index ce974474..e7722dad 100644 --- a/src/framework/luascript/luaobject.h +++ b/src/framework/luascript/luaobject.h @@ -101,8 +101,8 @@ int LuaObject::luaCallField(const std::string& field, const T&... args) { if(!g_lua.isNil()) { // the first argument is always this object (self) g_lua.insert(-2); - g_lua.polymorphicPush(args...); - return g_lua.signalCall(1 + sizeof...(args)); + int numArgs = g_lua.polymorphicPush(args...); + return g_lua.signalCall(1 + numArgs); } else { g_lua.pop(2); } diff --git a/src/framework/luascript/luavaluecasts.cpp b/src/framework/luascript/luavaluecasts.cpp index f18a8045..cf1d0ad3 100644 --- a/src/framework/luascript/luavaluecasts.cpp +++ b/src/framework/luascript/luavaluecasts.cpp @@ -25,9 +25,10 @@ #include // bool -void push_luavalue(bool b) +int push_luavalue(bool b) { g_lua.pushBoolean(b); + return 1; } bool luavalue_cast(int index, bool& b) @@ -37,9 +38,10 @@ bool luavalue_cast(int index, bool& b) } // int -void push_luavalue(int i) +int push_luavalue(int i) { g_lua.pushInteger(i); + return 1; } bool luavalue_cast(int index, int& i) @@ -51,9 +53,10 @@ bool luavalue_cast(int index, int& i) } // double -void push_luavalue(double d) +int push_luavalue(double d) { g_lua.pushNumber(d); + return 1; } bool luavalue_cast(int index, double& d) @@ -65,14 +68,16 @@ bool luavalue_cast(int index, double& d) } // string -void push_luavalue(const char* cstr) +int push_luavalue(const char* cstr) { g_lua.pushCString(cstr); + return 1; } -void push_luavalue(const std::string& str) +int push_luavalue(const std::string& str) { g_lua.pushString(str); + return 1; } bool luavalue_cast(int index, std::string& str) @@ -82,13 +87,14 @@ bool luavalue_cast(int index, std::string& str) } // lua cpp function -void push_luavalue(const LuaCppFunction& func) +int push_luavalue(const LuaCppFunction& func) { g_lua.pushCppFunction(func); + return 1; } // color -void push_luavalue(const Color& color) +int push_luavalue(const Color& color) { g_lua.newTable(); g_lua.pushInteger(color.r()); @@ -99,6 +105,7 @@ void push_luavalue(const Color& color) g_lua.setField("b"); g_lua.pushInteger(color.a()); g_lua.setField("a"); + return 1; } bool luavalue_cast(int index, Color& color) @@ -123,7 +130,7 @@ bool luavalue_cast(int index, Color& color) } // rect -void push_luavalue(const Rect& rect) +int push_luavalue(const Rect& rect) { g_lua.newTable(); g_lua.pushInteger(rect.x()); @@ -134,6 +141,7 @@ void push_luavalue(const Rect& rect) g_lua.setField("width"); g_lua.pushInteger(rect.height()); g_lua.setField("height"); + return 1; } bool luavalue_cast(int index, Rect& rect) @@ -158,13 +166,14 @@ bool luavalue_cast(int index, Rect& rect) } // point -void push_luavalue(const Point& point) +int push_luavalue(const Point& point) { g_lua.newTable(); g_lua.pushInteger(point.x); g_lua.setField("x"); g_lua.pushInteger(point.y); g_lua.setField("y"); + return 1; } bool luavalue_cast(int index, Point& point) @@ -185,13 +194,14 @@ bool luavalue_cast(int index, Point& point) } // size -void push_luavalue(const Size& size) +int push_luavalue(const Size& size) { g_lua.newTable(); g_lua.pushInteger(size.width()); g_lua.setField("width"); g_lua.pushInteger(size.height()); g_lua.setField("height"); + return 1; } bool luavalue_cast(int index, Size& size) @@ -245,7 +255,7 @@ void push_otml_subnode_luavalue(const OTMLNodePtr& node) g_lua.pushNil(); } -void push_luavalue(const OTMLNodePtr& node) +int push_luavalue(const OTMLNodePtr& node) { if(node) { g_lua.newTable(); @@ -259,6 +269,7 @@ void push_luavalue(const OTMLNodePtr& node) } } else g_lua.pushNil(); + return 1; } bool luavalue_cast(int index, OTMLNodePtr& node) diff --git a/src/framework/luascript/luavaluecasts.h b/src/framework/luascript/luavaluecasts.h index afa13674..15377100 100644 --- a/src/framework/luascript/luavaluecasts.h +++ b/src/framework/luascript/luavaluecasts.h @@ -28,70 +28,73 @@ #include "declarations.h" #include +template +int push_internal_luavalue(T v); + // bool -void push_luavalue(bool b); +int push_luavalue(bool b); bool luavalue_cast(int index, bool& b); // int -void push_luavalue(int i); +int push_luavalue(int i); bool luavalue_cast(int index, int& i); // double -void push_luavalue(double d); +int push_luavalue(double d); bool luavalue_cast(int index, double& d); // float -inline void push_luavalue(float f) { push_luavalue((double)f); } +inline int push_luavalue(float f) { push_luavalue((double)f); return 1; } inline bool luavalue_cast(int index, float& f) { double d; bool r = luavalue_cast(index, d); f = d; return r; } // int8 -inline void push_luavalue(int8 v) { push_luavalue((int)v); } +inline int push_luavalue(int8 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, int8& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint8 -inline void push_luavalue(uint8 v) { push_luavalue((int)v); } +inline int push_luavalue(uint8 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, uint8& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // int16 -inline void push_luavalue(int16 v) { push_luavalue((int)v); } +inline int push_luavalue(int16 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, int16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint16 -inline void push_luavalue(uint16 v) { push_luavalue((int)v); } +inline int push_luavalue(uint16 v) { push_luavalue((int)v); return 1; } inline bool luavalue_cast(int index, uint16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; } // uint32 -inline void push_luavalue(uint32 v) { push_luavalue((double)v); } +inline int push_luavalue(uint32 v) { push_luavalue((double)v); return 1; } inline bool luavalue_cast(int index, uint32& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // int64 -inline void push_luavalue(int64 v) { push_luavalue((double)v); } +inline int push_luavalue(int64 v) { push_luavalue((double)v); return 1; } inline bool luavalue_cast(int index, int64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // uint64 -inline void push_luavalue(uint64 v) { push_luavalue((double)v); } +inline int push_luavalue(uint64 v) { push_luavalue((double)v); return 1; } inline bool luavalue_cast(int index, uint64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; } // string -void push_luavalue(const char* cstr); -void push_luavalue(const std::string& str); +int push_luavalue(const char* cstr); +int push_luavalue(const std::string& str); bool luavalue_cast(int index, std::string& str); // lua cpp function -void push_luavalue(const LuaCppFunction& func); +int push_luavalue(const LuaCppFunction& func); // color -void push_luavalue(const Color& color); +int push_luavalue(const Color& color); bool luavalue_cast(int index, Color& color); // rect -void push_luavalue(const Rect& rect); +int push_luavalue(const Rect& rect); bool luavalue_cast(int index, Rect& rect); // point -void push_luavalue(const Point& point); +int push_luavalue(const Point& point); bool luavalue_cast(int index, Point& point); // size -void push_luavalue(const Size& size); +int push_luavalue(const Size& size); bool luavalue_cast(int index, Size& size); // otml nodes -void push_luavalue(const OTMLNodePtr& node); +int push_luavalue(const OTMLNodePtr& node); bool luavalue_cast(int index, OTMLNodePtr& node); // enum @@ -101,7 +104,7 @@ luavalue_cast(int index, T& myenum); // LuaObject pointers template -typename std::enable_if::value, void>::type +typename std::enable_if::value, int>::type push_luavalue(const T& obj); bool luavalue_cast(int index, LuaObjectPtr& obj); @@ -112,7 +115,7 @@ luavalue_cast(int index, std::shared_ptr& ptr); // std::function template -void push_luavalue(const std::function& func); +int push_luavalue(const std::function& func); template bool luavalue_cast(int index, std::function& func); @@ -123,34 +126,43 @@ luavalue_cast(int index, std::function& func); // vector template -void push_luavalue(const std::vector& vec); +int push_luavalue(const std::vector& vec); template bool luavalue_cast(int index, std::vector& vec); // deque template -void push_luavalue(const std::deque& vec); +int push_luavalue(const std::deque& vec); template bool luavalue_cast(int index, std::deque& vec); // map template -void push_luavalue(const std::map& map); +int push_luavalue(const std::map& map); template bool luavalue_cast(int index, std::map& map); // tuple template -void push_luavalue(const std::tuple& tuple); +int push_luavalue(const std::tuple& tuple); + +template +int push_internal_luavalue(const std::tuple& tuple); // start definitions #include "luaexception.h" #include "luainterface.h" + +template +int push_internal_luavalue(T v) { + return push_luavalue(v); +} + template typename std::enable_if::value, bool>::type luavalue_cast(int index, T& myenum) { @@ -158,11 +170,13 @@ luavalue_cast(int index, T& myenum) { } template -typename std::enable_if::value, void>::type +typename std::enable_if::value, int>::type push_luavalue(const T& obj) { if(obj) - return g_lua.pushObject(obj); - return g_lua.pushNil(); + g_lua.pushObject(obj); + else + g_lua.pushNil(); + return 1; } template @@ -176,12 +190,13 @@ luavalue_cast(int index, std::shared_ptr& ptr) { } template -void push_luavalue(const std::function& func) { +int push_luavalue(const std::function& func) { if(func) { LuaCppFunction f = luabinder::bind_fun(func); g_lua.pushCppFunction(f); } else g_lua.pushNil(); + return 1; } template @@ -197,8 +212,8 @@ bool luavalue_cast(int index, std::function& func) { g_lua.getWeakRef(funcWeakRef); try { if(g_lua.isFunction()) { - g_lua.polymorphicPush(args...); - int rets = g_lua.safeCall(sizeof...(Args)); + int numArgs = g_lua.polymorphicPush(args...); + int rets = g_lua.safeCall(numArgs); g_lua.pop(rets); } else { throw LuaException("attempt to call an expired lua function from C++," @@ -230,8 +245,8 @@ luavalue_cast(int index, std::function& func) { try { g_lua.getWeakRef(funcWeakRef); if(g_lua.isFunction()) { - g_lua.polymorphicPush(args...); - if(g_lua.safeCall(sizeof...(Args)) != 1) + int numArgs = g_lua.polymorphicPush(args...); + if(g_lua.safeCall(numArgs) != 1) throw LuaException("a function from lua didn't retrieve the expected number of results", 0); return g_lua.polymorphicPop(); } else { @@ -253,14 +268,15 @@ luavalue_cast(int index, std::function& func) { template -void push_luavalue(const std::vector& vec) { +int push_luavalue(const std::vector& vec) { g_lua.newTable(); int i = 1; for(const T& v : vec) { - push_luavalue(v); + push_internal_luavalue(v); g_lua.rawSeti(i); i++; } + return 1; } template @@ -280,14 +296,15 @@ bool luavalue_cast(int index, std::vector& vec) } template -void push_luavalue(const std::deque& vec) { +int push_luavalue(const std::deque& vec) { g_lua.newTable(); int i = 1; for(const T& v : vec) { - push_luavalue(v); + push_internal_luavalue(v); g_lua.rawSeti(i); i++; } + return 1; } template @@ -307,14 +324,15 @@ bool luavalue_cast(int index, std::deque& vec) } template -void push_luavalue(const std::map& map) +int push_luavalue(const std::map& map) { g_lua.newTable(); for(auto& it : map) { - push_luavalue(it.first); - push_luavalue(it.second); + push_internal_luavalue(it.first); + push_internal_luavalue(it.second); g_lua.rawSet(); } + return 1; } template @@ -334,12 +352,35 @@ bool luavalue_cast(int index, std::map& map) return false; } + template -struct push_tuple_luavalue { +struct push_tuple_internal_luavalue { template static void call(const Tuple& tuple) { - push_luavalue(std::get(tuple)); + push_internal_luavalue(std::get(tuple)); g_lua.rawSeti(N); + push_tuple_internal_luavalue::call(tuple); + } +}; + +template<> +struct push_tuple_internal_luavalue<0> { + template + static void call(const Tuple& tuple) { } +}; + +template +int push_internal_luavalue(const std::tuple& tuple) { + g_lua.newTable(); + push_tuple_internal_luavalue::call(tuple); + return 1; +} + +template +struct push_tuple_luavalue { + template + static void call(const Tuple& tuple) { + push_internal_luavalue(std::get::value - N>(tuple)); push_tuple_luavalue::call(tuple); } }; @@ -351,9 +392,9 @@ struct push_tuple_luavalue<0> { }; template -void push_luavalue(const std::tuple& tuple) { - g_lua.newTable(); +int push_luavalue(const std::tuple& tuple) { push_tuple_luavalue::call(tuple); + return sizeof...(Args); } #endif diff --git a/src/otclient/const.h b/src/otclient/const.h index f403af58..c5053324 100644 --- a/src/otclient/const.h +++ b/src/otclient/const.h @@ -311,6 +311,14 @@ namespace Otc GameMagicEffectU16, LastGameFeature }; + + enum PathFindResult { + PATHFIND_OK = 0, + PATHFIND_SAME_POSITION, + PATHFIND_IMPOSSIBLE, + PATHFIND_TOO_FAR, + PATHFIND_NO_WAY, + }; } #endif diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index a227c0e7..42058e5e 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -758,10 +758,11 @@ int Map::getLastAwareFloor() return Otc::SEA_FLOOR; } -// pathfinding using A* search algorithm -// as described in http://en.wikipedia.org/wiki/A*_search_algorithm -std::vector Map::findPath(const Position& startPos, const Position& goalPos, int maxSteps) +std::tuple, Otc::PathFindResult> Map::findPath(const Position& startPos, const Position& goalPos, int maxSteps) { + // pathfinding using A* search algorithm + // as described in http://en.wikipedia.org/wiki/A*_search_algorithm + struct Node { Node(const Position& pos) : cost(0), totalCost(0), steps(0), pos(pos), prev(nullptr), dir(Otc::InvalidDirection), evaluated(false) { } bool operator<(const Node& other) const { return totalCost < other.totalCost; } @@ -780,10 +781,26 @@ std::vector Map::findPath(const Position& startPos, const Positi } }; - std::vector dirs; + std::tuple, Otc::PathFindResult> ret; + std::vector& dirs = std::get<0>(ret); + Otc::PathFindResult& result = std::get<1>(ret); + + result = Otc::PATHFIND_OK; + + if(startPos == goalPos) { + result = Otc::PATHFIND_SAME_POSITION; + return ret; + } + + if(startPos.z != goalPos.z) { + result = Otc::PATHFIND_IMPOSSIBLE; + return ret; + } - if(startPos == goalPos || startPos.z != goalPos.z || startPos.distance(goalPos) > maxSteps) - return dirs; + if(startPos.distance(goalPos) > maxSteps) { + result = Otc::PATHFIND_TOO_FAR; + return ret; + } std::unordered_map nodes; std::priority_queue, LessNode> searchList; @@ -857,10 +874,11 @@ std::vector Map::findPath(const Position& startPos, const Positi } dirs.pop_back(); std::reverse(dirs.begin(), dirs.end()); - } + } else + result = Otc::PATHFIND_NO_WAY; for(auto it : nodes) delete it.second; - return dirs; + return ret; } diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index c57cd445..029d6fe6 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -137,7 +137,7 @@ public: std::vector getAnimatedTexts() { return m_animatedTexts; } std::vector getStaticTexts() { return m_staticTexts; } - std::vector findPath(const Position& start, const Position& goal, int maxSteps); + std::tuple, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxSteps); private: std::unordered_map m_tiles; diff --git a/src/otclient/luascript/luavaluecasts.cpp b/src/otclient/luascript/luavaluecasts.cpp index 54f99ac0..4ed5bf0c 100644 --- a/src/otclient/luascript/luavaluecasts.cpp +++ b/src/otclient/luascript/luavaluecasts.cpp @@ -23,7 +23,7 @@ #include "luavaluecasts.h" #include -void push_luavalue(const Outfit& outfit) +int push_luavalue(const Outfit& outfit) { g_lua.newTable(); g_lua.pushInteger(outfit.getId()); @@ -38,6 +38,7 @@ void push_luavalue(const Outfit& outfit) g_lua.setField("legs"); g_lua.pushInteger(outfit.getFeet()); g_lua.setField("feet"); + return 1; } bool luavalue_cast(int index, Outfit& outfit) @@ -60,7 +61,7 @@ bool luavalue_cast(int index, Outfit& outfit) return false; } -void push_luavalue(const Position& pos) +int push_luavalue(const Position& pos) { if(pos.isValid()) { g_lua.newTable(); @@ -72,6 +73,7 @@ void push_luavalue(const Position& pos) g_lua.setField("z"); } else g_lua.pushNil(); + return 1; } bool luavalue_cast(int index, Position& pos) diff --git a/src/otclient/luascript/luavaluecasts.h b/src/otclient/luascript/luavaluecasts.h index 9b25870c..dfeb02d4 100644 --- a/src/otclient/luascript/luavaluecasts.h +++ b/src/otclient/luascript/luavaluecasts.h @@ -28,11 +28,11 @@ #include // outfit -void push_luavalue(const Outfit& outfit); +int push_luavalue(const Outfit& outfit); bool luavalue_cast(int index, Outfit& outfit); // position -void push_luavalue(const Position& pos); +int push_luavalue(const Position& pos); bool luavalue_cast(int index, Position& pos); #endif