Imrove lua engine

* Allow bound C++ functions to return multiples values to lua with tuples
This commit is contained in:
Eduardo Bart 2012-07-05 09:38:48 -03:00
parent ea2967e1ad
commit 6bce0bd680
12 changed files with 164 additions and 84 deletions

View File

@ -371,7 +371,7 @@ function GameInterface.processMouseAction(menuPosition, mouseButton, autoWalkPos
end end
if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then 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 if #dirs == 0 then
TextMessage.displayStatus(tr('There is no way.')) TextMessage.displayStatus(tr('There is no way.'))
return true return true

View File

@ -11,7 +11,7 @@ minimapFirstLoad = true
function onMinimapMouseRelease(self, mousePosition, mouseButton) function onMinimapMouseRelease(self, mousePosition, mouseButton)
local tile = self:getTile(mousePosition) local tile = self:getTile(mousePosition)
if tile and mouseButton == MouseLeftButton and self:isPressed() then 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 if #dirs == 0 then
TextMessage.displayStatus(tr('There is no way.')) TextMessage.displayStatus(tr('There is no way.'))
return true return true
@ -47,8 +47,8 @@ function Minimap.init()
minimapWidget:setMultifloor(false) minimapWidget:setMultifloor(false)
minimapWidget:setKeepAspectRatio(false) minimapWidget:setKeepAspectRatio(false)
minimapWidget.onMouseRelease = onMinimapMouseRelease minimapWidget.onMouseRelease = onMinimapMouseRelease
minimapWidget.onMouseWheel = onMinimapMouseWheel minimapWidget.onMouseWheel = onMinimapMouseWheel
Minimap.reset() Minimap.reset()
-- load only the first time (avoid load/save between reloads) -- load only the first time (avoid load/save between reloads)
@ -127,7 +127,7 @@ function Minimap.compassClick(self, mousePos)
break break
end end
end end
if center then if center then
local player = g_game.getLocalPlayer() local player = g_game.getLocalPlayer()
if not player then return end if not player then return end

View File

@ -63,8 +63,8 @@ namespace luabinder
typename std::enable_if<!std::is_void<Ret>::value, int>::type typename std::enable_if<!std::is_void<Ret>::value, int>::type
call_fun_and_push_result(const F& f, LuaInterface* lua, const Args&... args) { call_fun_and_push_result(const F& f, LuaInterface* lua, const Args&... args) {
Ret ret = f(args...); Ret ret = f(args...);
lua->polymorphicPush(ret); int numRets = lua->polymorphicPush(ret);
return 1; return numRets;
} }
/// C++ void function caller /// C++ void function caller

View File

@ -316,8 +316,8 @@ public:
/// Pushes any type onto the stack /// Pushes any type onto the stack
template<typename T, typename... Args> template<typename T, typename... Args>
void polymorphicPush(T v, Args... args); int polymorphicPush(T v, Args... args);
void polymorphicPush() { } int polymorphicPush() { return 0; }
/// Casts a value from stack to any type /// Casts a value from stack to any type
/// @exception LuaBadValueCastException thrown if the cast fails /// @exception LuaBadValueCastException thrown if the cast fails
@ -344,9 +344,9 @@ extern LuaInterface g_lua;
#include "luavaluecasts.h" #include "luavaluecasts.h"
template<typename T, typename... Args> template<typename T, typename... Args>
void LuaInterface::polymorphicPush(T v, Args... args) { int LuaInterface::polymorphicPush(T v, Args... args) {
push_luavalue(v); int r = push_luavalue(v);
polymorphicPush(args...); return r + polymorphicPush(args...);
} }
// next templates must be defined after above includes // next templates must be defined after above includes
@ -423,8 +423,8 @@ template<typename... T>
int LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) { int LuaInterface::callGlobalField(const std::string& global, const std::string& field, const T&... args) {
g_lua.getGlobalField(global, field); g_lua.getGlobalField(global, field);
if(!g_lua.isNil()) { if(!g_lua.isNil()) {
g_lua.polymorphicPush(args...); int numArgs = g_lua.polymorphicPush(args...);
return g_lua.signalCall(sizeof...(args)); return g_lua.signalCall(numArgs);
} else } else
g_lua.pop(1); g_lua.pop(1);
return 0; return 0;

View File

@ -101,8 +101,8 @@ int LuaObject::luaCallField(const std::string& field, const T&... args) {
if(!g_lua.isNil()) { if(!g_lua.isNil()) {
// the first argument is always this object (self) // the first argument is always this object (self)
g_lua.insert(-2); g_lua.insert(-2);
g_lua.polymorphicPush(args...); int numArgs = g_lua.polymorphicPush(args...);
return g_lua.signalCall(1 + sizeof...(args)); return g_lua.signalCall(1 + numArgs);
} else { } else {
g_lua.pop(2); g_lua.pop(2);
} }

View File

@ -25,9 +25,10 @@
#include <framework/otml/otmlnode.h> #include <framework/otml/otmlnode.h>
// bool // bool
void push_luavalue(bool b) int push_luavalue(bool b)
{ {
g_lua.pushBoolean(b); g_lua.pushBoolean(b);
return 1;
} }
bool luavalue_cast(int index, bool& b) bool luavalue_cast(int index, bool& b)
@ -37,9 +38,10 @@ bool luavalue_cast(int index, bool& b)
} }
// int // int
void push_luavalue(int i) int push_luavalue(int i)
{ {
g_lua.pushInteger(i); g_lua.pushInteger(i);
return 1;
} }
bool luavalue_cast(int index, int& i) bool luavalue_cast(int index, int& i)
@ -51,9 +53,10 @@ bool luavalue_cast(int index, int& i)
} }
// double // double
void push_luavalue(double d) int push_luavalue(double d)
{ {
g_lua.pushNumber(d); g_lua.pushNumber(d);
return 1;
} }
bool luavalue_cast(int index, double& d) bool luavalue_cast(int index, double& d)
@ -65,14 +68,16 @@ bool luavalue_cast(int index, double& d)
} }
// string // string
void push_luavalue(const char* cstr) int push_luavalue(const char* cstr)
{ {
g_lua.pushCString(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); g_lua.pushString(str);
return 1;
} }
bool luavalue_cast(int index, std::string& str) bool luavalue_cast(int index, std::string& str)
@ -82,13 +87,14 @@ bool luavalue_cast(int index, std::string& str)
} }
// lua cpp function // lua cpp function
void push_luavalue(const LuaCppFunction& func) int push_luavalue(const LuaCppFunction& func)
{ {
g_lua.pushCppFunction(func); g_lua.pushCppFunction(func);
return 1;
} }
// color // color
void push_luavalue(const Color& color) int push_luavalue(const Color& color)
{ {
g_lua.newTable(); g_lua.newTable();
g_lua.pushInteger(color.r()); g_lua.pushInteger(color.r());
@ -99,6 +105,7 @@ void push_luavalue(const Color& color)
g_lua.setField("b"); g_lua.setField("b");
g_lua.pushInteger(color.a()); g_lua.pushInteger(color.a());
g_lua.setField("a"); g_lua.setField("a");
return 1;
} }
bool luavalue_cast(int index, Color& color) bool luavalue_cast(int index, Color& color)
@ -123,7 +130,7 @@ bool luavalue_cast(int index, Color& color)
} }
// rect // rect
void push_luavalue(const Rect& rect) int push_luavalue(const Rect& rect)
{ {
g_lua.newTable(); g_lua.newTable();
g_lua.pushInteger(rect.x()); g_lua.pushInteger(rect.x());
@ -134,6 +141,7 @@ void push_luavalue(const Rect& rect)
g_lua.setField("width"); g_lua.setField("width");
g_lua.pushInteger(rect.height()); g_lua.pushInteger(rect.height());
g_lua.setField("height"); g_lua.setField("height");
return 1;
} }
bool luavalue_cast(int index, Rect& rect) bool luavalue_cast(int index, Rect& rect)
@ -158,13 +166,14 @@ bool luavalue_cast(int index, Rect& rect)
} }
// point // point
void push_luavalue(const Point& point) int push_luavalue(const Point& point)
{ {
g_lua.newTable(); g_lua.newTable();
g_lua.pushInteger(point.x); g_lua.pushInteger(point.x);
g_lua.setField("x"); g_lua.setField("x");
g_lua.pushInteger(point.y); g_lua.pushInteger(point.y);
g_lua.setField("y"); g_lua.setField("y");
return 1;
} }
bool luavalue_cast(int index, Point& point) bool luavalue_cast(int index, Point& point)
@ -185,13 +194,14 @@ bool luavalue_cast(int index, Point& point)
} }
// size // size
void push_luavalue(const Size& size) int push_luavalue(const Size& size)
{ {
g_lua.newTable(); g_lua.newTable();
g_lua.pushInteger(size.width()); g_lua.pushInteger(size.width());
g_lua.setField("width"); g_lua.setField("width");
g_lua.pushInteger(size.height()); g_lua.pushInteger(size.height());
g_lua.setField("height"); g_lua.setField("height");
return 1;
} }
bool luavalue_cast(int index, Size& size) bool luavalue_cast(int index, Size& size)
@ -245,7 +255,7 @@ void push_otml_subnode_luavalue(const OTMLNodePtr& node)
g_lua.pushNil(); g_lua.pushNil();
} }
void push_luavalue(const OTMLNodePtr& node) int push_luavalue(const OTMLNodePtr& node)
{ {
if(node) { if(node) {
g_lua.newTable(); g_lua.newTable();
@ -259,6 +269,7 @@ void push_luavalue(const OTMLNodePtr& node)
} }
} else } else
g_lua.pushNil(); g_lua.pushNil();
return 1;
} }
bool luavalue_cast(int index, OTMLNodePtr& node) bool luavalue_cast(int index, OTMLNodePtr& node)

View File

@ -28,70 +28,73 @@
#include "declarations.h" #include "declarations.h"
#include <framework/otml/declarations.h> #include <framework/otml/declarations.h>
template<typename T>
int push_internal_luavalue(T v);
// bool // bool
void push_luavalue(bool b); int push_luavalue(bool b);
bool luavalue_cast(int index, bool& b); bool luavalue_cast(int index, bool& b);
// int // int
void push_luavalue(int i); int push_luavalue(int i);
bool luavalue_cast(int index, int& i); bool luavalue_cast(int index, int& i);
// double // double
void push_luavalue(double d); int push_luavalue(double d);
bool luavalue_cast(int index, double& d); bool luavalue_cast(int index, double& d);
// float // 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; } inline bool luavalue_cast(int index, float& f) { double d; bool r = luavalue_cast(index, d); f = d; return r; }
// int8 // 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; } inline bool luavalue_cast(int index, int8& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; }
// uint8 // 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; } inline bool luavalue_cast(int index, uint8& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; }
// int16 // 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; } inline bool luavalue_cast(int index, int16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; }
// uint16 // 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; } inline bool luavalue_cast(int index, uint16& v){ int i; bool r = luavalue_cast(index, i); v = i; return r; }
// uint32 // 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; } inline bool luavalue_cast(int index, uint32& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; }
// int64 // 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; } inline bool luavalue_cast(int index, int64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; }
// uint64 // 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; } inline bool luavalue_cast(int index, uint64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; }
// string // string
void push_luavalue(const char* cstr); int push_luavalue(const char* cstr);
void push_luavalue(const std::string& str); int push_luavalue(const std::string& str);
bool luavalue_cast(int index, std::string& str); bool luavalue_cast(int index, std::string& str);
// lua cpp function // lua cpp function
void push_luavalue(const LuaCppFunction& func); int push_luavalue(const LuaCppFunction& func);
// color // color
void push_luavalue(const Color& color); int push_luavalue(const Color& color);
bool luavalue_cast(int index, Color& color); bool luavalue_cast(int index, Color& color);
// rect // rect
void push_luavalue(const Rect& rect); int push_luavalue(const Rect& rect);
bool luavalue_cast(int index, Rect& rect); bool luavalue_cast(int index, Rect& rect);
// point // point
void push_luavalue(const Point& point); int push_luavalue(const Point& point);
bool luavalue_cast(int index, Point& point); bool luavalue_cast(int index, Point& point);
// size // size
void push_luavalue(const Size& size); int push_luavalue(const Size& size);
bool luavalue_cast(int index, Size& size); bool luavalue_cast(int index, Size& size);
// otml nodes // otml nodes
void push_luavalue(const OTMLNodePtr& node); int push_luavalue(const OTMLNodePtr& node);
bool luavalue_cast(int index, OTMLNodePtr& node); bool luavalue_cast(int index, OTMLNodePtr& node);
// enum // enum
@ -101,7 +104,7 @@ luavalue_cast(int index, T& myenum);
// LuaObject pointers // LuaObject pointers
template<class T> template<class T>
typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, void>::type typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, int>::type
push_luavalue(const T& obj); push_luavalue(const T& obj);
bool luavalue_cast(int index, LuaObjectPtr& obj); bool luavalue_cast(int index, LuaObjectPtr& obj);
@ -112,7 +115,7 @@ luavalue_cast(int index, std::shared_ptr<T>& ptr);
// std::function // std::function
template<typename Ret, typename... Args> template<typename Ret, typename... Args>
void push_luavalue(const std::function<Ret(Args...)>& func); int push_luavalue(const std::function<Ret(Args...)>& func);
template<typename... Args> template<typename... Args>
bool luavalue_cast(int index, std::function<void(Args...)>& func); bool luavalue_cast(int index, std::function<void(Args...)>& func);
@ -123,34 +126,43 @@ luavalue_cast(int index, std::function<Ret(Args...)>& func);
// vector // vector
template<typename T> template<typename T>
void push_luavalue(const std::vector<T>& vec); int push_luavalue(const std::vector<T>& vec);
template<typename T> template<typename T>
bool luavalue_cast(int index, std::vector<T>& vec); bool luavalue_cast(int index, std::vector<T>& vec);
// deque // deque
template<class T> template<class T>
void push_luavalue(const std::deque<T>& vec); int push_luavalue(const std::deque<T>& vec);
template<typename T> template<typename T>
bool luavalue_cast(int index, std::deque<T>& vec); bool luavalue_cast(int index, std::deque<T>& vec);
// map // map
template<class K, class V> template<class K, class V>
void push_luavalue(const std::map<K, V>& map); int push_luavalue(const std::map<K, V>& map);
template<class K, class V> template<class K, class V>
bool luavalue_cast(int index, std::map<K, V>& map); bool luavalue_cast(int index, std::map<K, V>& map);
// tuple // tuple
template<typename... Args> template<typename... Args>
void push_luavalue(const std::tuple<Args...>& tuple); int push_luavalue(const std::tuple<Args...>& tuple);
template<typename... Args>
int push_internal_luavalue(const std::tuple<Args...>& tuple);
// start definitions // start definitions
#include "luaexception.h" #include "luaexception.h"
#include "luainterface.h" #include "luainterface.h"
template<typename T>
int push_internal_luavalue(T v) {
return push_luavalue(v);
}
template<class T> template<class T>
typename std::enable_if<std::is_enum<T>::value, bool>::type typename std::enable_if<std::is_enum<T>::value, bool>::type
luavalue_cast(int index, T& myenum) { luavalue_cast(int index, T& myenum) {
@ -158,11 +170,13 @@ luavalue_cast(int index, T& myenum) {
} }
template<class T> template<class T>
typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, void>::type typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, int>::type
push_luavalue(const T& obj) { push_luavalue(const T& obj) {
if(obj) if(obj)
return g_lua.pushObject(obj); g_lua.pushObject(obj);
return g_lua.pushNil(); else
g_lua.pushNil();
return 1;
} }
template<class T> template<class T>
@ -176,12 +190,13 @@ luavalue_cast(int index, std::shared_ptr<T>& ptr) {
} }
template<typename Ret, typename... Args> template<typename Ret, typename... Args>
void push_luavalue(const std::function<Ret(Args...)>& func) { int push_luavalue(const std::function<Ret(Args...)>& func) {
if(func) { if(func) {
LuaCppFunction f = luabinder::bind_fun(func); LuaCppFunction f = luabinder::bind_fun(func);
g_lua.pushCppFunction(f); g_lua.pushCppFunction(f);
} else } else
g_lua.pushNil(); g_lua.pushNil();
return 1;
} }
template<typename... Args> template<typename... Args>
@ -197,8 +212,8 @@ bool luavalue_cast(int index, std::function<void(Args...)>& func) {
g_lua.getWeakRef(funcWeakRef); g_lua.getWeakRef(funcWeakRef);
try { try {
if(g_lua.isFunction()) { if(g_lua.isFunction()) {
g_lua.polymorphicPush(args...); int numArgs = g_lua.polymorphicPush(args...);
int rets = g_lua.safeCall(sizeof...(Args)); int rets = g_lua.safeCall(numArgs);
g_lua.pop(rets); g_lua.pop(rets);
} else { } else {
throw LuaException("attempt to call an expired lua function from C++," throw LuaException("attempt to call an expired lua function from C++,"
@ -230,8 +245,8 @@ luavalue_cast(int index, std::function<Ret(Args...)>& func) {
try { try {
g_lua.getWeakRef(funcWeakRef); g_lua.getWeakRef(funcWeakRef);
if(g_lua.isFunction()) { if(g_lua.isFunction()) {
g_lua.polymorphicPush(args...); int numArgs = g_lua.polymorphicPush(args...);
if(g_lua.safeCall(sizeof...(Args)) != 1) if(g_lua.safeCall(numArgs) != 1)
throw LuaException("a function from lua didn't retrieve the expected number of results", 0); throw LuaException("a function from lua didn't retrieve the expected number of results", 0);
return g_lua.polymorphicPop<Ret>(); return g_lua.polymorphicPop<Ret>();
} else { } else {
@ -253,14 +268,15 @@ luavalue_cast(int index, std::function<Ret(Args...)>& func) {
template<typename T> template<typename T>
void push_luavalue(const std::vector<T>& vec) { int push_luavalue(const std::vector<T>& vec) {
g_lua.newTable(); g_lua.newTable();
int i = 1; int i = 1;
for(const T& v : vec) { for(const T& v : vec) {
push_luavalue(v); push_internal_luavalue(v);
g_lua.rawSeti(i); g_lua.rawSeti(i);
i++; i++;
} }
return 1;
} }
template<typename T> template<typename T>
@ -280,14 +296,15 @@ bool luavalue_cast(int index, std::vector<T>& vec)
} }
template<typename T> template<typename T>
void push_luavalue(const std::deque<T>& vec) { int push_luavalue(const std::deque<T>& vec) {
g_lua.newTable(); g_lua.newTable();
int i = 1; int i = 1;
for(const T& v : vec) { for(const T& v : vec) {
push_luavalue(v); push_internal_luavalue(v);
g_lua.rawSeti(i); g_lua.rawSeti(i);
i++; i++;
} }
return 1;
} }
template<typename T> template<typename T>
@ -307,14 +324,15 @@ bool luavalue_cast(int index, std::deque<T>& vec)
} }
template<class K, class V> template<class K, class V>
void push_luavalue(const std::map<K, V>& map) int push_luavalue(const std::map<K, V>& map)
{ {
g_lua.newTable(); g_lua.newTable();
for(auto& it : map) { for(auto& it : map) {
push_luavalue(it.first); push_internal_luavalue(it.first);
push_luavalue(it.second); push_internal_luavalue(it.second);
g_lua.rawSet(); g_lua.rawSet();
} }
return 1;
} }
template<class K, class V> template<class K, class V>
@ -334,12 +352,35 @@ bool luavalue_cast(int index, std::map<K, V>& map)
return false; return false;
} }
template<int N>
struct push_tuple_internal_luavalue {
template<typename Tuple>
static void call(const Tuple& tuple) {
push_internal_luavalue(std::get<N-1>(tuple));
g_lua.rawSeti(N);
push_tuple_internal_luavalue<N-1>::call(tuple);
}
};
template<>
struct push_tuple_internal_luavalue<0> {
template<typename Tuple>
static void call(const Tuple& tuple) { }
};
template<typename... Args>
int push_internal_luavalue(const std::tuple<Args...>& tuple) {
g_lua.newTable();
push_tuple_internal_luavalue<sizeof...(Args)>::call(tuple);
return 1;
}
template<int N> template<int N>
struct push_tuple_luavalue { struct push_tuple_luavalue {
template<typename Tuple> template<typename Tuple>
static void call(const Tuple& tuple) { static void call(const Tuple& tuple) {
push_luavalue(std::get<N-1>(tuple)); push_internal_luavalue(std::get<std::tuple_size<Tuple>::value - N>(tuple));
g_lua.rawSeti(N);
push_tuple_luavalue<N-1>::call(tuple); push_tuple_luavalue<N-1>::call(tuple);
} }
}; };
@ -351,9 +392,9 @@ struct push_tuple_luavalue<0> {
}; };
template<typename... Args> template<typename... Args>
void push_luavalue(const std::tuple<Args...>& tuple) { int push_luavalue(const std::tuple<Args...>& tuple) {
g_lua.newTable();
push_tuple_luavalue<sizeof...(Args)>::call(tuple); push_tuple_luavalue<sizeof...(Args)>::call(tuple);
return sizeof...(Args);
} }
#endif #endif

View File

@ -311,6 +311,14 @@ namespace Otc
GameMagicEffectU16, GameMagicEffectU16,
LastGameFeature LastGameFeature
}; };
enum PathFindResult {
PATHFIND_OK = 0,
PATHFIND_SAME_POSITION,
PATHFIND_IMPOSSIBLE,
PATHFIND_TOO_FAR,
PATHFIND_NO_WAY,
};
} }
#endif #endif

View File

@ -758,10 +758,11 @@ int Map::getLastAwareFloor()
return Otc::SEA_FLOOR; return Otc::SEA_FLOOR;
} }
// pathfinding using A* search algorithm std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const Position& startPos, const Position& goalPos, int maxSteps)
// as described in http://en.wikipedia.org/wiki/A*_search_algorithm
std::vector<Otc::Direction> 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 { struct Node {
Node(const Position& pos) : cost(0), totalCost(0), steps(0), pos(pos), prev(nullptr), dir(Otc::InvalidDirection), evaluated(false) { } 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; } bool operator<(const Node& other) const { return totalCost < other.totalCost; }
@ -780,10 +781,26 @@ std::vector<Otc::Direction> Map::findPath(const Position& startPos, const Positi
} }
}; };
std::vector<Otc::Direction> dirs; std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> ret;
std::vector<Otc::Direction>& dirs = std::get<0>(ret);
Otc::PathFindResult& result = std::get<1>(ret);
if(startPos == goalPos || startPos.z != goalPos.z || startPos.distance(goalPos) > maxSteps) result = Otc::PATHFIND_OK;
return dirs;
if(startPos == goalPos) {
result = Otc::PATHFIND_SAME_POSITION;
return ret;
}
if(startPos.z != goalPos.z) {
result = Otc::PATHFIND_IMPOSSIBLE;
return ret;
}
if(startPos.distance(goalPos) > maxSteps) {
result = Otc::PATHFIND_TOO_FAR;
return ret;
}
std::unordered_map<Position, Node*, PositionHasher> nodes; std::unordered_map<Position, Node*, PositionHasher> nodes;
std::priority_queue<Node*, std::vector<Node*>, LessNode> searchList; std::priority_queue<Node*, std::vector<Node*>, LessNode> searchList;
@ -857,10 +874,11 @@ std::vector<Otc::Direction> Map::findPath(const Position& startPos, const Positi
} }
dirs.pop_back(); dirs.pop_back();
std::reverse(dirs.begin(), dirs.end()); std::reverse(dirs.begin(), dirs.end());
} } else
result = Otc::PATHFIND_NO_WAY;
for(auto it : nodes) for(auto it : nodes)
delete it.second; delete it.second;
return dirs; return ret;
} }

View File

@ -137,7 +137,7 @@ public:
std::vector<AnimatedTextPtr> getAnimatedTexts() { return m_animatedTexts; } std::vector<AnimatedTextPtr> getAnimatedTexts() { return m_animatedTexts; }
std::vector<StaticTextPtr> getStaticTexts() { return m_staticTexts; } std::vector<StaticTextPtr> getStaticTexts() { return m_staticTexts; }
std::vector<Otc::Direction> findPath(const Position& start, const Position& goal, int maxSteps); std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxSteps);
private: private:
std::unordered_map<Position, TilePtr, PositionHasher> m_tiles; std::unordered_map<Position, TilePtr, PositionHasher> m_tiles;

View File

@ -23,7 +23,7 @@
#include "luavaluecasts.h" #include "luavaluecasts.h"
#include <framework/luascript/luainterface.h> #include <framework/luascript/luainterface.h>
void push_luavalue(const Outfit& outfit) int push_luavalue(const Outfit& outfit)
{ {
g_lua.newTable(); g_lua.newTable();
g_lua.pushInteger(outfit.getId()); g_lua.pushInteger(outfit.getId());
@ -38,6 +38,7 @@ void push_luavalue(const Outfit& outfit)
g_lua.setField("legs"); g_lua.setField("legs");
g_lua.pushInteger(outfit.getFeet()); g_lua.pushInteger(outfit.getFeet());
g_lua.setField("feet"); g_lua.setField("feet");
return 1;
} }
bool luavalue_cast(int index, Outfit& outfit) bool luavalue_cast(int index, Outfit& outfit)
@ -60,7 +61,7 @@ bool luavalue_cast(int index, Outfit& outfit)
return false; return false;
} }
void push_luavalue(const Position& pos) int push_luavalue(const Position& pos)
{ {
if(pos.isValid()) { if(pos.isValid()) {
g_lua.newTable(); g_lua.newTable();
@ -72,6 +73,7 @@ void push_luavalue(const Position& pos)
g_lua.setField("z"); g_lua.setField("z");
} else } else
g_lua.pushNil(); g_lua.pushNil();
return 1;
} }
bool luavalue_cast(int index, Position& pos) bool luavalue_cast(int index, Position& pos)

View File

@ -28,11 +28,11 @@
#include <otclient/core/outfit.h> #include <otclient/core/outfit.h>
// outfit // outfit
void push_luavalue(const Outfit& outfit); int push_luavalue(const Outfit& outfit);
bool luavalue_cast(int index, Outfit& outfit); bool luavalue_cast(int index, Outfit& outfit);
// position // position
void push_luavalue(const Position& pos); int push_luavalue(const Position& pos);
bool luavalue_cast(int index, Position& pos); bool luavalue_cast(int index, Position& pos);
#endif #endif