Rework stdext classes
Implement new classes: * stdext::any => ligher replacement for boost::any * stdext::packed_any => like any but optimized to use less memory * stdext::shared_object => ligher replacement for std::shared_ptr * stdext::shared_object_ptr => replacement for boost::intrusive_ptr * stdext::fast_storage => for storing dynamic data * stdext::packed_storage => same but with less memory * stdext::packed_vector => std::vector with less memory Compiling should be a little faster now because global boost including is not needed anymore
This commit is contained in:
parent
1dc7dc0cfc
commit
3bac3dcbb4
|
@ -34,18 +34,29 @@ set(framework_SOURCES ${framework_SOURCES}
|
|||
${CMAKE_CURRENT_LIST_DIR}/util/size.h
|
||||
|
||||
# stdext
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/any.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/boolean.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/cast.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/compiler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/demangle.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/demangle.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/dumper.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/dynamic_storage.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/exception.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/format.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/math.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/math.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/stdext.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/string.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/time.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/types.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/attrib_storage.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/packed_any.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/packed_storage.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/packed_vector.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/shared_object.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/stdext.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/string.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/string.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/time.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/time.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/traits.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/stdext/types.h
|
||||
|
||||
# core
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/application.cpp
|
||||
|
|
|
@ -33,11 +33,11 @@ class ScheduledEvent;
|
|||
class FileStream;
|
||||
class BinaryTree;
|
||||
|
||||
typedef boost::intrusive_ptr<Module> ModulePtr;
|
||||
typedef boost::intrusive_ptr<Event> EventPtr;
|
||||
typedef boost::intrusive_ptr<ScheduledEvent> ScheduledEventPtr;
|
||||
typedef boost::intrusive_ptr<FileStream> FileStreamPtr;
|
||||
typedef boost::intrusive_ptr<BinaryTree> BinaryTreePtr;
|
||||
typedef stdext::shared_object_ptr<Module> ModulePtr;
|
||||
typedef stdext::shared_object_ptr<Event> EventPtr;
|
||||
typedef stdext::shared_object_ptr<ScheduledEvent> ScheduledEventPtr;
|
||||
typedef stdext::shared_object_ptr<FileStream> FileStreamPtr;
|
||||
typedef stdext::shared_object_ptr<BinaryTree> BinaryTreePtr;
|
||||
|
||||
typedef std::vector<BinaryTreePtr> BinaryTreeVec;
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "clock.h"
|
||||
#include "scheduledevent.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
// @bindsingleton g_dispatcher
|
||||
class EventDispatcher
|
||||
{
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
void addString(const std::string& v);
|
||||
BinaryTreePtr makeTree();
|
||||
|
||||
FileStreamPtr asFileStream() { return self_cast<FileStream>(); }
|
||||
FileStreamPtr asFileStream() { return static_self_cast<FileStream>(); }
|
||||
|
||||
private:
|
||||
void checkWrite();
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "../global.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
struct LogMessage {
|
||||
LogMessage(Fw::LogLevel level, const std::string& message, std::size_t when) : level(level), message(message), when(when) { }
|
||||
Fw::LogLevel level;
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
int getAutoLoadPriority() { return m_autoLoadPriority; }
|
||||
|
||||
// @dontbind
|
||||
ModulePtr asModule() { return self_cast<Module>(); }
|
||||
ModulePtr asModule() { return static_self_cast<Module>(); }
|
||||
|
||||
protected:
|
||||
void discover(const OTMLNodePtr& moduleNode);
|
||||
|
|
|
@ -43,7 +43,7 @@ void ModuleManager::discoverModules()
|
|||
for(const std::string& moduleDir : moduleDirs) {
|
||||
auto moduleFiles = g_resources.listDirectoryFiles("/" + moduleDir);
|
||||
for(const std::string& moduleFile : moduleFiles) {
|
||||
if(boost::ends_with(moduleFile, ".otmod")) {
|
||||
if(stdext::ends_with(moduleFile, ".otmod")) {
|
||||
ModulePtr module = discoverModule("/" + moduleDir + "/" + moduleFile);
|
||||
if(module && module->isAutoLoad())
|
||||
m_autoLoadModules.insert(std::make_pair(module->getAutoLoadPriority(), module));
|
||||
|
|
|
@ -125,7 +125,7 @@ void ResourceManager::searchAndAddPackages(const std::string& packagesDir, const
|
|||
auto files = listDirectoryFiles(packagesDir);
|
||||
for(auto it = files.rbegin(); it != files.rend(); ++it) {
|
||||
const std::string& file = *it;
|
||||
if(!boost::ends_with(file, packageExt))
|
||||
if(!stdext::ends_with(file, packageExt))
|
||||
continue;
|
||||
std::string package = getRealDir(packagesDir) + "/" + file;
|
||||
if(!addSearchPath(package, true))
|
||||
|
@ -262,7 +262,7 @@ std::list<std::string> ResourceManager::listDirectoryFiles(const std::string& di
|
|||
std::string ResourceManager::resolvePath(const std::string& path)
|
||||
{
|
||||
std::string fullPath;
|
||||
if(boost::starts_with(path, "/"))
|
||||
if(stdext::starts_with(path, "/"))
|
||||
fullPath = path;
|
||||
else {
|
||||
std::string scriptPath = "/" + g_lua.getCurrentSourcePath();
|
||||
|
@ -270,9 +270,9 @@ std::string ResourceManager::resolvePath(const std::string& path)
|
|||
fullPath += scriptPath + "/";
|
||||
fullPath += path;
|
||||
}
|
||||
if(!(boost::starts_with(fullPath, "/")))
|
||||
if(!(stdext::starts_with(fullPath, "/")))
|
||||
g_logger.traceWarning(stdext::format("the following file path is not fully resolved: %s", path));
|
||||
boost::replace_all(fullPath, "//", "/");
|
||||
stdext::replace_all(fullPath, "//", "/");
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
void enableBilinearFilter();
|
||||
void processAnimation();
|
||||
|
||||
AnimatedTexturePtr asAnimatedTexture() { return self_cast<AnimatedTexture>(); }
|
||||
AnimatedTexturePtr asAnimatedTexture() { return static_self_cast<AnimatedTexture>(); }
|
||||
|
||||
private:
|
||||
std::vector<uint> m_framesTextureId;
|
||||
|
|
|
@ -44,21 +44,21 @@ class ParticleSystem;
|
|||
class ParticleEffect;
|
||||
class ParticleEffectType;
|
||||
|
||||
typedef boost::intrusive_ptr<Image> ImagePtr;
|
||||
typedef boost::intrusive_ptr<Texture> TexturePtr;
|
||||
typedef boost::intrusive_ptr<AnimatedTexture> AnimatedTexturePtr;
|
||||
typedef boost::intrusive_ptr<BitmapFont> BitmapFontPtr;
|
||||
typedef boost::intrusive_ptr<CachedText> CachedTextPtr;
|
||||
typedef boost::intrusive_ptr<FrameBuffer> FrameBufferPtr;
|
||||
typedef boost::intrusive_ptr<Shader> ShaderPtr;
|
||||
typedef boost::intrusive_ptr<ShaderProgram> ShaderProgramPtr;
|
||||
typedef boost::intrusive_ptr<PainterShaderProgram> PainterShaderProgramPtr;
|
||||
typedef boost::intrusive_ptr<Particle> ParticlePtr;
|
||||
typedef boost::intrusive_ptr<ParticleEmitter> ParticleEmitterPtr;
|
||||
typedef boost::intrusive_ptr<ParticleAffector> ParticleAffectorPtr;
|
||||
typedef boost::intrusive_ptr<ParticleSystem> ParticleSystemPtr;
|
||||
typedef boost::intrusive_ptr<ParticleEffect> ParticleEffectPtr;
|
||||
typedef boost::intrusive_ptr<ParticleEffectType> ParticleEffectTypePtr;
|
||||
typedef stdext::shared_object_ptr<Image> ImagePtr;
|
||||
typedef stdext::shared_object_ptr<Texture> TexturePtr;
|
||||
typedef stdext::shared_object_ptr<AnimatedTexture> AnimatedTexturePtr;
|
||||
typedef stdext::shared_object_ptr<BitmapFont> BitmapFontPtr;
|
||||
typedef stdext::shared_object_ptr<CachedText> CachedTextPtr;
|
||||
typedef stdext::shared_object_ptr<FrameBuffer> FrameBufferPtr;
|
||||
typedef stdext::shared_object_ptr<Shader> ShaderPtr;
|
||||
typedef stdext::shared_object_ptr<ShaderProgram> ShaderProgramPtr;
|
||||
typedef stdext::shared_object_ptr<PainterShaderProgram> PainterShaderProgramPtr;
|
||||
typedef stdext::shared_object_ptr<Particle> ParticlePtr;
|
||||
typedef stdext::shared_object_ptr<ParticleEmitter> ParticleEmitterPtr;
|
||||
typedef stdext::shared_object_ptr<ParticleAffector> ParticleAffectorPtr;
|
||||
typedef stdext::shared_object_ptr<ParticleSystem> ParticleSystemPtr;
|
||||
typedef stdext::shared_object_ptr<ParticleEffect> ParticleEffectPtr;
|
||||
typedef stdext::shared_object_ptr<ParticleEffectType> ParticleEffectTypePtr;
|
||||
typedef std::vector<ShaderPtr> ShaderList;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,7 @@ void FontManager::clearFonts()
|
|||
bool FontManager::importFont(std::string fontFile)
|
||||
{
|
||||
try {
|
||||
if(!boost::ends_with(fontFile, ".otfont"))
|
||||
if(!stdext::ends_with(fontFile, ".otfont"))
|
||||
fontFile += ".otfont";
|
||||
|
||||
OTMLDocumentPtr doc = OTMLDocument::parse(fontFile);
|
||||
|
|
|
@ -40,7 +40,7 @@ ImagePtr Image::load(const std::string& file)
|
|||
ImagePtr image;
|
||||
try {
|
||||
// currently only png images are supported
|
||||
if(!boost::ends_with(file, ".png"))
|
||||
if(!stdext::ends_with(file, ".png"))
|
||||
stdext::throw_exception("image file format no supported");
|
||||
|
||||
// load image file data
|
||||
|
|
|
@ -84,7 +84,7 @@ void ParticleSystem::update()
|
|||
return;
|
||||
m_lastUpdateTime = g_clock.seconds() - std::fmod(elapsedTime, delay);
|
||||
|
||||
auto self = self_cast<ParticleSystem>();
|
||||
auto self = static_self_cast<ParticleSystem>();
|
||||
for(int i = 0; i < elapsedTime / delay; ++i) {
|
||||
|
||||
// update emitters
|
||||
|
|
|
@ -63,7 +63,7 @@ TexturePtr TextureManager::getTexture(const std::string& fileName)
|
|||
if(!texture) {
|
||||
try {
|
||||
// currently only png textures are supported
|
||||
if(!boost::ends_with(filePath, ".png"))
|
||||
if(!stdext::ends_with(filePath, ".png"))
|
||||
stdext::throw_exception("texture file format no supported");
|
||||
|
||||
// load texture file data
|
||||
|
|
|
@ -25,11 +25,13 @@
|
|||
|
||||
#include <framework/global.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class LuaInterface;
|
||||
class LuaObject;
|
||||
|
||||
typedef std::function<int(LuaInterface*)> LuaCppFunction;
|
||||
typedef std::unique_ptr<LuaCppFunction> LuaCppFunctionPtr;
|
||||
typedef boost::intrusive_ptr<LuaObject> LuaObjectPtr;
|
||||
typedef stdext::shared_object_ptr<LuaObject> LuaObjectPtr;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "luainterface.h"
|
||||
#include "luaexception.h"
|
||||
|
||||
#include <framework/stdext/traits.h>
|
||||
#include <tuple>
|
||||
|
||||
/// This namespace contains some dirty metaprogamming that uses a lot of C++0x features
|
||||
/// The purpose here is to create templates that can bind any function from C++
|
||||
/// and expose in lua environment. This is done combining variadic templates,
|
||||
|
@ -36,12 +39,6 @@
|
|||
/// pushes the result to lua.
|
||||
namespace luabinder
|
||||
{
|
||||
/// Removes const references, transforming 'const T&' into 'T'
|
||||
template<typename T>
|
||||
struct remove_const_ref {
|
||||
typedef typename std::remove_const<typename std::remove_reference<T>::type>::type type;
|
||||
};
|
||||
|
||||
/// Pack arguments from lua stack into a tuple recursively
|
||||
template<int N>
|
||||
struct pack_values_into_tuple {
|
||||
|
@ -117,8 +114,8 @@ namespace luabinder
|
|||
/// Bind a std::function
|
||||
template<typename Ret, typename... Args>
|
||||
LuaCppFunction bind_fun(const std::function<Ret(Args...)>& f) {
|
||||
typedef typename std::tuple<typename remove_const_ref<Args>::type...> Tuple;
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
typedef typename std::tuple<typename stdext::remove_const_ref<Args>::type...> Tuple;
|
||||
return bind_fun_specializer<typename stdext::remove_const_ref<Ret>::type,
|
||||
decltype(f),
|
||||
Tuple>(f);
|
||||
}
|
||||
|
@ -130,8 +127,8 @@ namespace luabinder
|
|||
template<typename Lambda, typename Ret, typename... Args>
|
||||
struct bind_lambda_fun<Ret(Lambda::*)(Args...) const> {
|
||||
static LuaCppFunction call(const Lambda& f) {
|
||||
typedef typename std::tuple<typename remove_const_ref<Args>::type...> Tuple;
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
typedef typename std::tuple<typename stdext::remove_const_ref<Args>::type...> Tuple;
|
||||
return bind_fun_specializer<typename stdext::remove_const_ref<Ret>::type,
|
||||
decltype(f),
|
||||
Tuple>(f);
|
||||
|
||||
|
@ -152,18 +149,18 @@ namespace luabinder
|
|||
|
||||
/// Create member function lambdas
|
||||
template<typename Ret, typename C, typename... Args>
|
||||
std::function<Ret(const boost::intrusive_ptr<C>&, const Args&...)> make_mem_func(Ret (C::* f)(Args...)) {
|
||||
std::function<Ret(const stdext::shared_object_ptr<C>&, const Args&...)> make_mem_func(Ret (C::* f)(Args...)) {
|
||||
auto mf = std::mem_fn(f);
|
||||
return [=](const boost::intrusive_ptr<C>& obj, const Args&... args) mutable -> Ret {
|
||||
return [=](const stdext::shared_object_ptr<C>& obj, const Args&... args) mutable -> Ret {
|
||||
if(!obj)
|
||||
throw LuaException("failed to call a member function because the passed object is nil");
|
||||
return mf(obj.get(), args...);
|
||||
};
|
||||
}
|
||||
template<typename C, typename... Args>
|
||||
std::function<void(const boost::intrusive_ptr<C>&, const Args&...)> make_mem_func(void (C::* f)(Args...)) {
|
||||
std::function<void(const stdext::shared_object_ptr<C>&, const Args&...)> make_mem_func(void (C::* f)(Args...)) {
|
||||
auto mf = std::mem_fn(f);
|
||||
return [=](const boost::intrusive_ptr<C>& obj, const Args&... args) mutable -> void {
|
||||
return [=](const stdext::shared_object_ptr<C>& obj, const Args&... args) mutable -> void {
|
||||
if(!obj)
|
||||
throw LuaException("failed to call a member function because the passed object is nil");
|
||||
mf(obj.get(), args...);
|
||||
|
@ -186,9 +183,9 @@ namespace luabinder
|
|||
/// Bind member functions
|
||||
template<typename C, typename Ret, class FC, typename... Args>
|
||||
LuaCppFunction bind_mem_fun(Ret (FC::* f)(Args...)) {
|
||||
typedef typename std::tuple<boost::intrusive_ptr<FC>, typename remove_const_ref<Args>::type...> Tuple;
|
||||
typedef typename std::tuple<stdext::shared_object_ptr<FC>, typename stdext::remove_const_ref<Args>::type...> Tuple;
|
||||
auto lambda = make_mem_func<Ret,FC>(f);
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
return bind_fun_specializer<typename stdext::remove_const_ref<Ret>::type,
|
||||
decltype(lambda),
|
||||
Tuple>(lambda);
|
||||
}
|
||||
|
@ -196,10 +193,10 @@ namespace luabinder
|
|||
/// Bind singleton member functions
|
||||
template<typename C, typename Ret, class FC, typename... Args>
|
||||
LuaCppFunction bind_singleton_mem_fun(Ret (FC::*f)(Args...), C *instance) {
|
||||
typedef typename std::tuple<typename remove_const_ref<Args>::type...> Tuple;
|
||||
typedef typename std::tuple<typename stdext::remove_const_ref<Args>::type...> Tuple;
|
||||
assert(instance);
|
||||
auto lambda = make_mem_func_singleton<Ret,FC>(f, static_cast<FC*>(instance));
|
||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||
return bind_fun_specializer<typename stdext::remove_const_ref<Ret>::type,
|
||||
decltype(lambda),
|
||||
Tuple>(lambda);
|
||||
}
|
||||
|
@ -209,7 +206,7 @@ namespace luabinder
|
|||
LuaCppFunction bind_mem_fun(int (C::*f)(LuaInterface*)) {
|
||||
auto mf = std::mem_fn(f);
|
||||
return [=](LuaInterface* lua) -> int {
|
||||
auto obj = lua->castValue<boost::intrusive_ptr<C>>(1);
|
||||
auto obj = lua->castValue<stdext::shared_object_ptr<C>>(1);
|
||||
lua->remove(1);
|
||||
return mf(obj, lua);
|
||||
};
|
||||
|
|
|
@ -325,7 +325,7 @@ void LuaInterface::loadScript(const std::string& fileName)
|
|||
{
|
||||
// resolve file full path
|
||||
std::string filePath = fileName;
|
||||
if(!boost::starts_with(fileName, "/"))
|
||||
if(!stdext::starts_with(fileName, "/"))
|
||||
filePath = getCurrentSourcePath() + "/" + filePath;
|
||||
|
||||
std::string buffer = g_resources.loadFile(fileName);
|
||||
|
@ -341,7 +341,7 @@ void LuaInterface::loadFunction(const std::string& buffer, const std::string& so
|
|||
}
|
||||
|
||||
std::string buf;
|
||||
if(boost::starts_with(buffer, "function"))
|
||||
if(stdext::starts_with(buffer, "function"))
|
||||
buf = stdext::format("__func = %s", buffer);
|
||||
else
|
||||
buf = stdext::format("__func = function(self)\n%s\nend", buffer);
|
||||
|
@ -553,7 +553,7 @@ int LuaInterface::luaScriptLoader(lua_State* L)
|
|||
g_lua.loadScript(fileName);
|
||||
return 1;
|
||||
} catch(stdext::exception& e) {
|
||||
g_lua.pushString(stdext::mkstr("\n\t", e.what()));
|
||||
g_lua.pushString(std::string("\n\t") + e.what());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ int LuaInterface::luaScriptLoader(lua_State* L)
|
|||
int LuaInterface::lua_dofile(lua_State* L)
|
||||
{
|
||||
std::string fileName = g_lua.popString();
|
||||
if(!boost::ends_with(fileName, ".lua"))
|
||||
if(!stdext::ends_with(fileName, ".lua"))
|
||||
fileName += ".lua";
|
||||
|
||||
try {
|
||||
|
@ -580,7 +580,7 @@ int LuaInterface::lua_dofiles(lua_State* L)
|
|||
std::string directory = g_lua.popString();
|
||||
|
||||
for(const std::string& fileName : g_resources.listDirectoryFiles(directory)) {
|
||||
if(!boost::ends_with(fileName, ".lua"))
|
||||
if(!stdext::ends_with(fileName, ".lua"))
|
||||
continue;
|
||||
|
||||
try {
|
||||
|
@ -597,7 +597,7 @@ int LuaInterface::lua_dofiles(lua_State* L)
|
|||
int LuaInterface::lua_loadfile(lua_State* L)
|
||||
{
|
||||
std::string fileName = g_lua.popString();
|
||||
if(!boost::ends_with(fileName, ".lua"))
|
||||
if(!stdext::ends_with(fileName, ".lua"))
|
||||
fileName += ".lua";
|
||||
|
||||
try {
|
||||
|
|
|
@ -320,7 +320,7 @@ public:
|
|||
|
||||
/// Pushes any type onto the stack
|
||||
template<typename T, typename... Args>
|
||||
int polymorphicPush(T v, Args... args);
|
||||
int polymorphicPush(const T& v, const Args&... args);
|
||||
int polymorphicPush() { return 0; }
|
||||
|
||||
/// Casts a value from stack to any type
|
||||
|
@ -349,7 +349,7 @@ extern LuaInterface g_lua;
|
|||
#include "luavaluecasts.h"
|
||||
|
||||
template<typename T, typename... Args>
|
||||
int LuaInterface::polymorphicPush(T v, Args... args) {
|
||||
int LuaInterface::polymorphicPush(const T& v, const Args&... args) {
|
||||
int r = push_luavalue(v);
|
||||
return r + polymorphicPush(args...);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define LUAOBJECT_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <typeinfo>
|
||||
|
||||
/// LuaObject, all script-able classes have it as base
|
||||
// @bindclass
|
||||
|
@ -80,7 +81,7 @@ public:
|
|||
return stdext::demangle_name(typeid(*this).name());
|
||||
}
|
||||
|
||||
LuaObjectPtr asLuaObject() { return self_cast<LuaObject>(); }
|
||||
LuaObjectPtr asLuaObject() { return static_self_cast<LuaObject>(); }
|
||||
|
||||
void operator=(const LuaObject& other) { }
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ bool luavalue_cast(int index, LuaObjectPtr& obj);
|
|||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_base_of<LuaObject, T>::value, bool>::type
|
||||
luavalue_cast(int index, boost::intrusive_ptr<T>& ptr);
|
||||
luavalue_cast(int index, stdext::shared_object_ptr<T>& ptr);
|
||||
|
||||
// std::function
|
||||
template<typename Ret, typename... Args>
|
||||
|
@ -186,7 +186,7 @@ push_luavalue(const T& obj) {
|
|||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_base_of<LuaObject, T>::value, bool>::type
|
||||
luavalue_cast(int index, boost::intrusive_ptr<T>& ptr) {
|
||||
luavalue_cast(int index, stdext::shared_object_ptr<T>& ptr) {
|
||||
LuaObjectPtr obj;
|
||||
if(!luavalue_cast(index, obj))
|
||||
return false;
|
||||
|
|
|
@ -69,7 +69,7 @@ void Connection::connect(const std::string& host, uint16 port, const std::functi
|
|||
|
||||
auto self = asConnection();
|
||||
m_resolver.async_resolve(query, [=](const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator) {
|
||||
if(self->is_unique_ref())
|
||||
if(self.is_unique())
|
||||
return;
|
||||
m_readTimer.cancel();
|
||||
|
||||
|
@ -130,7 +130,7 @@ void Connection::write(uint8* buffer, uint16 size)
|
|||
|
||||
// wait 1 ms to do the real send
|
||||
m_sendEvent = g_dispatcher.scheduleEvent([=] {
|
||||
if(self->is_unique_ref())
|
||||
if(self.is_unique())
|
||||
return;
|
||||
//m_writeTimer.cancel();
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
bool isConnecting() { return m_connecting; }
|
||||
bool isConnected() { return m_connected; }
|
||||
|
||||
ConnectionPtr asConnection() { return self_cast<Connection>(); }
|
||||
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
||||
protected:
|
||||
void onConnect(const boost::system::error_code& error);
|
||||
void onWrite(const boost::system::error_code& error, size_t);
|
||||
|
|
|
@ -34,10 +34,10 @@ class Connection;
|
|||
class Protocol;
|
||||
class Server;
|
||||
|
||||
typedef boost::intrusive_ptr<InputMessage> InputMessagePtr;
|
||||
typedef boost::intrusive_ptr<OutputMessage> OutputMessagePtr;
|
||||
typedef boost::intrusive_ptr<Connection> ConnectionPtr;
|
||||
typedef boost::intrusive_ptr<Protocol> ProtocolPtr;
|
||||
typedef boost::intrusive_ptr<Server> ServerPtr;
|
||||
typedef stdext::shared_object_ptr<InputMessage> InputMessagePtr;
|
||||
typedef stdext::shared_object_ptr<OutputMessage> OutputMessagePtr;
|
||||
typedef stdext::shared_object_ptr<Connection> ConnectionPtr;
|
||||
typedef stdext::shared_object_ptr<Protocol> ProtocolPtr;
|
||||
typedef stdext::shared_object_ptr<Server> ServerPtr;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
virtual void send(const OutputMessagePtr& outputMessage);
|
||||
void recv();
|
||||
|
||||
ProtocolPtr asProtocol() { return self_cast<Protocol>(); }
|
||||
ProtocolPtr asProtocol() { return static_self_cast<Protocol>(); }
|
||||
|
||||
protected:
|
||||
virtual void onConnect();
|
||||
|
|
|
@ -30,8 +30,8 @@ class OTMLDocument;
|
|||
class OTMLParser;
|
||||
class OTMLEmitter;
|
||||
|
||||
typedef boost::intrusive_ptr<OTMLNode> OTMLNodePtr;
|
||||
typedef boost::intrusive_ptr<OTMLDocument> OTMLDocumentPtr;
|
||||
typedef stdext::shared_object_ptr<OTMLNode> OTMLNodePtr;
|
||||
typedef stdext::shared_object_ptr<OTMLDocument> OTMLDocumentPtr;
|
||||
typedef std::vector<OTMLNodePtr> OTMLNodeList;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -84,7 +84,7 @@ OTMLNodePtr OTMLNode::at(const std::string& childTag)
|
|||
OTMLNodePtr OTMLNode::atIndex(int childIndex)
|
||||
{
|
||||
if(childIndex >= size() || childIndex < 0)
|
||||
throw OTMLException(asOTMLNode(), stdext::mkstr("child node with index '%d' not found", childIndex));
|
||||
throw OTMLException(asOTMLNode(), stdext::format("child node with index '%d' not found", childIndex));
|
||||
return m_children[childIndex];
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
|
||||
virtual std::string emit();
|
||||
|
||||
OTMLNodePtr asOTMLNode() { return self_cast<OTMLNode>(); }
|
||||
OTMLNodePtr asOTMLNode() { return static_self_cast<OTMLNode>(); }
|
||||
|
||||
protected:
|
||||
OTMLNode() : m_unique(false), m_null(false) { }
|
||||
|
@ -107,13 +107,13 @@ protected:
|
|||
template<>
|
||||
inline std::string OTMLNode::value<std::string>() {
|
||||
std::string value = m_value;
|
||||
if(boost::starts_with(value, "\"") && boost::ends_with(value, "\"")) {
|
||||
if(stdext::starts_with(value, "\"") && stdext::ends_with(value, "\"")) {
|
||||
value = value.substr(1, value.length()-2);
|
||||
boost::replace_all(value, "\\\\", "\\");
|
||||
boost::replace_all(value, "\\\"", "\"");
|
||||
boost::replace_all(value, "\\t", "\t");
|
||||
boost::replace_all(value, "\\n", "\n");
|
||||
boost::replace_all(value, "\\'", "\'");
|
||||
stdext::replace_all(value, "\\\\", "\\");
|
||||
stdext::replace_all(value, "\\\"", "\"");
|
||||
stdext::replace_all(value, "\\t", "\t");
|
||||
stdext::replace_all(value, "\\n", "\n");
|
||||
stdext::replace_all(value, "\\'", "\'");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -80,14 +80,14 @@ void OTMLParser::parseLine(std::string line)
|
|||
return;
|
||||
|
||||
// remove line sides spaces
|
||||
boost::trim(line);
|
||||
stdext::trim(line);
|
||||
|
||||
// skip empty lines
|
||||
if(line.empty())
|
||||
return;
|
||||
|
||||
// skip comments
|
||||
if(boost::starts_with(line, "//"))
|
||||
if(stdext::starts_with(line, "//"))
|
||||
return;
|
||||
|
||||
// a depth above, change current parent to the previous added node
|
||||
|
@ -119,7 +119,7 @@ void OTMLParser::parseNode(const std::string& data)
|
|||
// node that has no tag and may have a value
|
||||
if(!data.empty() && data[0] == '-') {
|
||||
value = data.substr(1);
|
||||
boost::trim(value);
|
||||
stdext::trim(value);
|
||||
// node that has tag and possible a value
|
||||
} else if(dotsPos != std::string::npos) {
|
||||
tag = data.substr(0, dotsPos);
|
||||
|
@ -130,8 +130,8 @@ void OTMLParser::parseNode(const std::string& data)
|
|||
tag = data;
|
||||
}
|
||||
|
||||
boost::trim(tag);
|
||||
boost::trim(value);
|
||||
stdext::trim(tag);
|
||||
stdext::trim(value);
|
||||
|
||||
// process multitine values
|
||||
if(value == "|" || value == "|-" || value == "|+") {
|
||||
|
@ -148,7 +148,7 @@ void OTMLParser::parseNode(const std::string& data)
|
|||
// it has contents below the current depth
|
||||
} else {
|
||||
// if not empty, its a node
|
||||
boost::trim(line);
|
||||
stdext::trim(line);
|
||||
if(!line.empty()) {
|
||||
// rewind and break
|
||||
in.seekg(lastPos, std::ios::beg);
|
||||
|
@ -188,11 +188,13 @@ void OTMLParser::parseNode(const std::string& data)
|
|||
if(value == "~")
|
||||
node->setNull(true);
|
||||
else {
|
||||
if(boost::starts_with(value, "[") && boost::ends_with(value, "]")) {
|
||||
if(stdext::starts_with(value, "[") && stdext::ends_with(value, "]")) {
|
||||
std::string tmp = value.substr(1, value.length()-2);
|
||||
boost::tokenizer<boost::escaped_list_separator<char>> tokens(tmp);
|
||||
for(std::string v : tokens)
|
||||
node->writeIn(stdext::trim(v));
|
||||
for(std::string v : tokens) {
|
||||
stdext::trim(v);
|
||||
node->writeIn(v);
|
||||
}
|
||||
} else
|
||||
node->setValue(value);
|
||||
}
|
||||
|
|
|
@ -28,40 +28,19 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
#include <csignal>
|
||||
|
||||
// common STL headers
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <bitset>
|
||||
#include <queue>
|
||||
#include <deque>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
#include <typeinfo>
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
#include <unordered_map>
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
// boost utilities
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -948,7 +948,7 @@ std::string WIN32Window::getClipboardText()
|
|||
if(hglb) {
|
||||
LPTSTR lptstr = (LPTSTR)GlobalLock(hglb);
|
||||
if(lptstr) {
|
||||
text = stdext::utf8StringToLatin1((uchar*)lptstr);
|
||||
text = stdext::utf8_to_latin1((uchar*)lptstr);
|
||||
GlobalUnlock(hglb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1037,7 +1037,7 @@ std::string X11Window::getClipboardText()
|
|||
|
||||
// hack to wait SelectioNotify event, otherwise we will get wrong clipboard pastes
|
||||
// TODO: fix this in a correct way
|
||||
usleep(100 * 1000);
|
||||
stdext::millisleep(100);
|
||||
|
||||
// check for data
|
||||
Atom type;
|
||||
|
@ -1052,7 +1052,7 @@ std::string X11Window::getClipboardText()
|
|||
&bytesLeft,
|
||||
&data);
|
||||
if(len > 0) {
|
||||
clipboardText = stdext::utf8StringToLatin1(data);
|
||||
clipboardText = stdext::utf8_to_latin1(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,11 +38,11 @@ class StreamSoundSource;
|
|||
class CombinedSoundSource;
|
||||
class OggSoundFile;
|
||||
|
||||
typedef boost::intrusive_ptr<SoundSource> SoundSourcePtr;
|
||||
typedef boost::intrusive_ptr<SoundFile> SoundFilePtr;
|
||||
typedef boost::intrusive_ptr<SoundBuffer> SoundBufferPtr;
|
||||
typedef boost::intrusive_ptr<StreamSoundSource> StreamSoundSourcePtr;
|
||||
typedef boost::intrusive_ptr<CombinedSoundSource> CombinedSoundSourcePtr;
|
||||
typedef boost::intrusive_ptr<OggSoundFile> OggSoundFilePtr;
|
||||
typedef stdext::shared_object_ptr<SoundSource> SoundSourcePtr;
|
||||
typedef stdext::shared_object_ptr<SoundFile> SoundFilePtr;
|
||||
typedef stdext::shared_object_ptr<SoundBuffer> SoundBufferPtr;
|
||||
typedef stdext::shared_object_ptr<StreamSoundSource> StreamSoundSourcePtr;
|
||||
typedef stdext::shared_object_ptr<CombinedSoundSource> CombinedSoundSourcePtr;
|
||||
typedef stdext::shared_object_ptr<OggSoundFile> OggSoundFilePtr;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STDEXT_ANY_H
|
||||
#define STDEXT_ANY_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
class any {
|
||||
public:
|
||||
struct placeholder {
|
||||
virtual ~placeholder() { }
|
||||
virtual const std::type_info& type() const = 0;
|
||||
virtual placeholder* clone() const = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct holder : public placeholder {
|
||||
holder(const T& value) : held(value) { }
|
||||
const std::type_info& type() const { return typeid(T); }
|
||||
placeholder* clone() const { return new holder(held); }
|
||||
T held;
|
||||
private:
|
||||
holder& operator=(const holder &);
|
||||
};
|
||||
|
||||
placeholder* content;
|
||||
|
||||
any() : content(nullptr) { }
|
||||
any(const any& other) : content(other.content ? other.content->clone() : nullptr) { }
|
||||
template<typename T> any(const T& value) : content(new holder<T>(value)) { }
|
||||
~any() { if(content) delete content; }
|
||||
|
||||
any& swap(any& rhs) { std::swap(content, rhs.content); return *this; }
|
||||
|
||||
template<typename T> any& operator=(const T& rhs) { any(rhs).swap(*this); return *this; }
|
||||
any& operator=(any rhs) { rhs.swap(*this); return *this; }
|
||||
|
||||
bool empty() const { return !content; }
|
||||
template<typename T> const T& cast() const;
|
||||
const std::type_info & type() const { return content ? content->type() : typeid(void); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
const T& any_cast(const any& operand) {
|
||||
assert(operand.type() == typeid(T));
|
||||
return static_cast<any::holder<T>*>(operand.content)->held;
|
||||
}
|
||||
|
||||
template<typename T> const T& any::cast() const { return any_cast<T>(*this); }
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -23,15 +23,13 @@
|
|||
#ifndef STDEXT_CAST_H
|
||||
#define STDEXT_CAST_H
|
||||
|
||||
namespace stdext {
|
||||
template<typename R, typename T> R safe_cast(const T& t);
|
||||
template<typename R, typename T> R unsafe_cast(const T& t, R def = R());
|
||||
}
|
||||
|
||||
#include "string.h"
|
||||
#include "exception.h"
|
||||
#include "demangle.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
// cast a type to another type
|
||||
|
@ -142,7 +140,9 @@ public:
|
|||
virtual ~cast_exception() throw() { }
|
||||
template<class T, class R>
|
||||
void update_what() {
|
||||
m_what = format("failed to cast value of type '%s' to type '%s'", demangle_type<T>(), demangle_type<R>());
|
||||
std::stringstream ss;
|
||||
ss << "failed to cast value of type '" << demangle_type<T>() << "' to type '" << demangle_type<R>() << "'";
|
||||
m_what = ss.str();
|
||||
}
|
||||
virtual const char* what() const throw() { return m_what.c_str(); }
|
||||
private:
|
||||
|
@ -163,14 +163,15 @@ R safe_cast(const T& t) {
|
|||
|
||||
// cast a type to another type, cast errors are ignored
|
||||
template<typename R, typename T>
|
||||
R unsafe_cast(const T& t, R def) {
|
||||
R unsafe_cast(const T& t, R def = R()) {
|
||||
try {
|
||||
return safe_cast<R,T>(t);
|
||||
} catch(cast_exception& e) {
|
||||
std::cout << "CAST ERROR: " << e.what() << std::endl;
|
||||
std::cerr << "CAST ERROR: " << e.what() << std::endl;
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#ifdef __clang__
|
||||
// clang is supported
|
||||
#undef _GLIBCXX_USE_FLOAT128
|
||||
#elif defined(__GNUC__)
|
||||
#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||
#error "Sorry, you need gcc 4.6 or greater to compile."
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "demangle.h"
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
const char* demangle_name(const char* name)
|
||||
{
|
||||
size_t len;
|
||||
int status;
|
||||
static char buffer[1024];
|
||||
char* demangled = abi::__cxa_demangle(name, 0, &len, &status);
|
||||
if(demangled) {
|
||||
strcpy(buffer, demangled);
|
||||
free(demangled);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,29 +23,16 @@
|
|||
#ifndef STDEXT_DEMANGLE_H
|
||||
#define STDEXT_DEMANGLE_H
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
/// Demangle names for GNU g++ compiler
|
||||
inline std::string demangle_name(const char* name) {
|
||||
size_t len;
|
||||
int status;
|
||||
std::string ret;
|
||||
char* demangled = abi::__cxa_demangle(name, 0, &len, &status);
|
||||
if(demangled) {
|
||||
ret = demangled;
|
||||
free(demangled);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
const char* demangle_name(const char* name);
|
||||
|
||||
/// Returns the name of a type
|
||||
template<typename T>
|
||||
std::string demangle_type() {
|
||||
return demangle_name(typeid(T).name());
|
||||
}
|
||||
template<typename T> std::string demangle_type() { return demangle_name(typeid(T).name()); }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -27,30 +27,13 @@
|
|||
|
||||
namespace stdext {
|
||||
|
||||
namespace dumper {
|
||||
|
||||
struct dumper_dummy {
|
||||
static struct {
|
||||
struct dumper_dummy {
|
||||
~dumper_dummy() { std::cout << std::endl; }
|
||||
template<class T>
|
||||
dumper_dummy& operator<<(const T& v) {
|
||||
std::cout << v << " ";
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct dumper_util {
|
||||
dumper_util() { }
|
||||
template<class T>
|
||||
dumper_dummy operator<<(const T& v) const {
|
||||
dumper_dummy d;
|
||||
d << v;
|
||||
return d;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const static dumper::dumper_util dump;
|
||||
template<class T> dumper_dummy& operator<<(const T& v) { std::cout << v << " "; return *this; }
|
||||
};
|
||||
template<class T> dumper_dummy operator<<(const T& v) const { dumper_dummy d; d << v; return d; }
|
||||
} dump;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STDEXT_DYNAMICSTORAGE_H
|
||||
#define STDEXT_DYNAMICSTORAGE_H
|
||||
|
||||
#include "types.h"
|
||||
#include "any.h"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
template<typename Key>
|
||||
class dynamic_storage {
|
||||
public:
|
||||
template<typename T> void set(const Key& k, const T& value) { m_map[k] = value; }
|
||||
template<typename T> T get(const Key& k) const {
|
||||
auto it = m_map.find(k);
|
||||
if(it != m_map.end())
|
||||
return any_cast<T>(it->second);
|
||||
return T();
|
||||
}
|
||||
bool has(const Key& k) const { return m_map.find(k) != m_map.end(); }
|
||||
|
||||
std::size_t size() const { return m_map.size(); }
|
||||
void clear() { m_map.clear(); }
|
||||
|
||||
private:
|
||||
std::unordered_map<Key, any> m_map;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -34,9 +34,7 @@ public:
|
|||
exception() { }
|
||||
exception(const std::string& what) : m_what(what) { }
|
||||
virtual ~exception() throw() { };
|
||||
|
||||
virtual const char* what() const throw() { return m_what.c_str(); }
|
||||
|
||||
protected:
|
||||
std::string m_what;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STDEXT_FORMAT_H
|
||||
#define STDEXT_FORMAT_H
|
||||
|
||||
#include "traits.h"
|
||||
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <tuple>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
template<class T> void print_ostream(std::ostringstream& stream, const T& last) { stream << last; }
|
||||
template<class T, class... Args>
|
||||
void print_ostream(std::ostringstream& stream, const T& first, const Args&... rest) { stream << "\t" << first; print_ostream(stream, rest...); }
|
||||
template<class... T>
|
||||
|
||||
/// Utility for printing variables just like lua
|
||||
void print(const T&... args) { std::ostringstream buf; print_ostream(buf, args...); std::cout << buf.str() << std::endl; }
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value ||
|
||||
std::is_pointer<T>::value ||
|
||||
std::is_floating_point<T>::value ||
|
||||
std::is_enum<T>::value, T>::type sprintf_cast(const T& t) { return t; }
|
||||
inline const char *sprintf_cast(const std::string& s) { return s.c_str(); }
|
||||
|
||||
template<int N> struct expand_snprintf {
|
||||
template<typename Tuple, typename... Args> static int call(char *s, size_t maxlen, const char *format, const Tuple& tuple, const Args&... args) {
|
||||
return expand_snprintf<N-1>::call(s, maxlen, format, tuple, sprintf_cast(std::get<N-1>(tuple)), args...); }};
|
||||
template<> struct expand_snprintf<0> {
|
||||
template<typename Tuple, typename... Args> static int call(char *s, size_t maxlen, const char *format, const Tuple& tuple, const Args&... args) {
|
||||
return snprintf(s, maxlen, format, args...); }};
|
||||
|
||||
/// Improved snprintf that accepts std::string and other types
|
||||
template<typename... Args>
|
||||
int snprintf(char *s, size_t maxlen, const char *format, const Args&... args) {
|
||||
std::tuple<typename replace_extent<Args>::type...> tuple(args...);
|
||||
return expand_snprintf<std::tuple_size<decltype(tuple)>::value>::call(s, maxlen, format, tuple);
|
||||
}
|
||||
|
||||
/// Format strings with the sprintf style, accepting std::string and string convertible types for %s
|
||||
template<typename... Args>
|
||||
std::string format(const std::string& format, const Args&... args) {
|
||||
int n, size = 1024;
|
||||
std::string str;
|
||||
while(true) {
|
||||
str.resize(size);
|
||||
n = snprintf(&str[0], size, format.c_str(), args...);
|
||||
assert(n != -1);
|
||||
if(n < size) {
|
||||
str.resize(n);
|
||||
return str;
|
||||
}
|
||||
size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include <random>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
uint32_t adler32(const uint8_t *buffer, size_t size) {
|
||||
register size_t a = 1, b = 0, tlen;
|
||||
while(size > 0) {
|
||||
tlen = size > 5552 ? 5552 : size;
|
||||
size -= tlen;
|
||||
do {
|
||||
a += *buffer++;
|
||||
b += a;
|
||||
} while (--tlen);
|
||||
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
}
|
||||
return (b << 16) | a;
|
||||
}
|
||||
|
||||
long random_range(long min, long max)
|
||||
{
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static std::uniform_int_distribution<long> dis(0, 2147483647);
|
||||
return min + (dis(gen) % (max - min + 1));
|
||||
}
|
||||
|
||||
float random_range(float min, float max)
|
||||
{
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static std::uniform_real_distribution<float> dis(0.0, 1.0);
|
||||
return min + (max - min)*dis(gen);
|
||||
}
|
||||
|
||||
}
|
|
@ -24,65 +24,24 @@
|
|||
#define STDEXT_MATH_H
|
||||
|
||||
#include "types.h"
|
||||
#include <random>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
inline uint32 adler32(const uint8 *buffer, uint16 size) {
|
||||
register uint32 a = 1, b = 0, tlen;
|
||||
while(size > 0) {
|
||||
tlen = size > 5552 ? 5552 : size;
|
||||
size -= tlen;
|
||||
do {
|
||||
a += *buffer++;
|
||||
b += a;
|
||||
} while (--tlen);
|
||||
inline bool is_power_of_two(size_t v) { return ((v != 0) && !(v & (v - 1))); }
|
||||
inline size_t to_power_of_two(size_t v) { if(v == 0) return 0; size_t r = 1; while(r < v && r != 0xffffffff) r <<= 1; return r; }
|
||||
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
}
|
||||
return (b << 16) | a;
|
||||
}
|
||||
inline uint16_t readLE16(const uchar *addr) { return (uint16_t)addr[1] << 8 | addr[0]; }
|
||||
inline uint32_t readLE32(const uchar *addr) { return (uint32_t)readLE16(addr + 2) << 16 | readLE16(addr); }
|
||||
inline uint64_t readLE64(const uchar *addr) { return (uint64_t)readLE32(addr + 4) << 32 | readLE32(addr); }
|
||||
|
||||
inline bool is_power_of_two(uint32 v) {
|
||||
return ((v != 0) && !(v & (v - 1)));
|
||||
}
|
||||
inline void writeLE16(uchar *addr, uint16_t value) { addr[1] = value >> 8; addr[0] = (uint8_t)value; }
|
||||
inline void writeLE32(uchar *addr, uint32_t value) { writeLE16(addr + 2, value >> 16); writeLE16(addr, (uint16_t)value); }
|
||||
inline void writeLE64(uchar *addr, uint64_t value) { writeLE32(addr + 4, value >> 32); writeLE32(addr, (uint32_t)value); }
|
||||
|
||||
inline uint32 to_power_of_two(uint32 v) {
|
||||
if(v == 0)
|
||||
return 0;
|
||||
uint32 r = 1;
|
||||
while(r < v && r != 0xffffffff)
|
||||
r <<= 1;
|
||||
return r;
|
||||
}
|
||||
uint32_t adler32(const uint8_t *buffer, size_t size);
|
||||
|
||||
inline uint16 readLE16(const uchar *addr) { return (uint16)addr[1] << 8 | addr[0]; }
|
||||
inline uint32 readLE32(const uchar *addr) { return (uint32)readLE16(addr + 2) << 16 | readLE16(addr); }
|
||||
inline uint64 readLE64(const uchar *addr) { return (uint64)readLE32(addr + 4) << 32 | readLE32(addr); }
|
||||
|
||||
inline void writeLE16(uchar *addr, uint16 value) { addr[1] = value >> 8; addr[0] = (uint8)value; }
|
||||
inline void writeLE32(uchar *addr, uint32 value) { writeLE16(addr + 2, value >> 16); writeLE16(addr, (uint16)value); }
|
||||
inline void writeLE64(uchar *addr, uint64 value) { writeLE32(addr + 4, value >> 32); writeLE32(addr, (uint32)value); }
|
||||
|
||||
template<typename T>
|
||||
T random_range(T min, T max);
|
||||
|
||||
template<>
|
||||
inline int random_range<int>(int min, int max) {
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static std::uniform_int_distribution<int> dis(0, 2147483647);
|
||||
return min + (dis(gen) % (max - min + 1));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float random_range<float>(float min, float max) {
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static std::uniform_real_distribution<float> dis(0.0, 1.0);
|
||||
return min + (max - min)*dis(gen);
|
||||
}
|
||||
long random_range(long min, long max);
|
||||
float random_range(float min, float max);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STDEXT_PACKEDANY_H
|
||||
#define STDEXT_PACKEDANY_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
// disable memory alignment
|
||||
#pragma pack(push,1)
|
||||
|
||||
template<typename T>
|
||||
struct can_pack_in_any : std::integral_constant<bool,
|
||||
(sizeof(T) <= sizeof(void*) && std::is_trivial<T>::value)> {};
|
||||
|
||||
// improved to use less memory
|
||||
class packed_any {
|
||||
public:
|
||||
struct placeholder {
|
||||
virtual ~placeholder() { }
|
||||
virtual const std::type_info& type() const = 0;
|
||||
virtual placeholder* clone() const = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct holder : public placeholder {
|
||||
holder(const T& value) : held(value) { }
|
||||
const std::type_info& type() const { return typeid(T); }
|
||||
placeholder* clone() const { return new holder(held); }
|
||||
T held;
|
||||
private:
|
||||
holder& operator=(const holder &);
|
||||
};
|
||||
|
||||
placeholder* content;
|
||||
bool scalar;
|
||||
|
||||
packed_any() :
|
||||
content(nullptr), scalar(false) { }
|
||||
packed_any(const packed_any& other) :
|
||||
content(!other.scalar && other.content ? other.content->clone() : other.content),
|
||||
scalar(other.scalar) { }
|
||||
template<typename T>
|
||||
packed_any(const T& value, typename std::enable_if<(can_pack_in_any<T>::value)>::type* = nullptr) :
|
||||
content(reinterpret_cast<placeholder*>(static_cast<std::size_t>(value))), scalar(true) { }
|
||||
template<typename T>
|
||||
packed_any(const T& value, typename std::enable_if<!(can_pack_in_any<T>::value)>::type* = nullptr) :
|
||||
content(new holder<T>(value)), scalar(false) { }
|
||||
~packed_any()
|
||||
{ if(!scalar && content) delete content; }
|
||||
|
||||
packed_any& swap(packed_any& rhs) { std::swap(content, rhs.content); std::swap(scalar, rhs.scalar); return *this; }
|
||||
|
||||
template<typename T> packed_any& operator=(const T& rhs) { packed_any(rhs).swap(*this); return *this; }
|
||||
packed_any& operator=(packed_any rhs) { rhs.swap(*this); return *this; }
|
||||
|
||||
bool empty() const { return !scalar && !content; }
|
||||
template<typename T> T cast() const;
|
||||
const std::type_info& type() const {
|
||||
if(scalar)
|
||||
return content ? content->type() : typeid(void);
|
||||
else
|
||||
return typeid(std::size_t);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T packed_any_cast(const packed_any& operand) {
|
||||
if(operand.scalar) {
|
||||
union {
|
||||
T v;
|
||||
packed_any::placeholder* content;
|
||||
};
|
||||
content = operand.content;
|
||||
return v;
|
||||
} else {
|
||||
assert(operand.type() == typeid(T));
|
||||
return static_cast<packed_any::holder<T>*>(operand.content)->held;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> T packed_any::cast() const { return packed_any_cast<T>(*this); }
|
||||
|
||||
// restore memory alignment
|
||||
#pragma pack(pop)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -20,63 +20,73 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STDEXT_ATTRIBSTORAGE_H
|
||||
#define STDEXT_ATTRIBSTORAGE_H
|
||||
#ifndef STDEXT_PACKEDSTORAGE_H
|
||||
#define STDEXT_PACKEDSTORAGE_H
|
||||
|
||||
#include "types.h"
|
||||
#include <tuple>
|
||||
#include <boost/any.hpp>
|
||||
#include "packed_any.h"
|
||||
|
||||
namespace stdext {
|
||||
|
||||
// disable memory alignment
|
||||
#pragma pack(push,1)
|
||||
|
||||
// this class was designed to use less memory as possible
|
||||
namespace stdext {
|
||||
class attrib_storage {
|
||||
template<typename Key, typename SizeType = uint8>
|
||||
class packed_storage {
|
||||
struct value_pair {
|
||||
Key id;
|
||||
packed_any value;
|
||||
};
|
||||
|
||||
public:
|
||||
attrib_storage() : m_attribs(nullptr), m_size(0) { }
|
||||
~attrib_storage() { if(m_attribs) delete[] m_attribs; }
|
||||
packed_storage() : m_values(nullptr), m_size(0) { }
|
||||
~packed_storage() { if(m_values) delete[] m_values; }
|
||||
|
||||
template<typename T>
|
||||
void set(uint8 id, T value) {
|
||||
bool done = false;
|
||||
for(int i=0;i<m_size;++i) {
|
||||
if(std::get<0>(m_attribs[i]) == id) {
|
||||
std::get<1>(m_attribs[i]) = value;
|
||||
done = true;
|
||||
break;
|
||||
void set(Key id, T value) {
|
||||
for(SizeType i=0;i<m_size;++i) {
|
||||
if(m_values[i].id == id) {
|
||||
m_values[i].value = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!done) {
|
||||
auto attribs = new std::tuple<uint8, boost::any>[m_size+1];
|
||||
auto tmp = new value_pair[m_size+1];
|
||||
if(m_size > 0) {
|
||||
for(int i=0;i<m_size;++i)
|
||||
attribs[i] = m_attribs[i];
|
||||
delete[] m_attribs;
|
||||
}
|
||||
m_attribs = attribs;
|
||||
m_attribs[m_size++] = std::make_tuple(id, value);
|
||||
std::copy(m_values, m_values + m_size, tmp);
|
||||
delete[] m_values;
|
||||
}
|
||||
m_values = tmp;
|
||||
m_values[m_size++] = { id, packed_any(value) };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get(uint8 id) const {
|
||||
for(int i=0;i<m_size;++i)
|
||||
if(std::get<0>(m_attribs[i]) == id)
|
||||
return boost::any_cast<T>(std::get<1>(m_attribs[i]));
|
||||
T get(Key id) const {
|
||||
for(SizeType i=0;i<m_size;++i)
|
||||
if(m_values[i].id == id)
|
||||
return packed_any_cast<T>(m_values[i].value);
|
||||
return T();
|
||||
}
|
||||
|
||||
bool has(uint8 id) const {
|
||||
for(int i=0;i<m_size;++i)
|
||||
if(std::get<0>(m_attribs[i]) == id)
|
||||
bool has(Key id) const {
|
||||
for(SizeType i=0;i<m_size;++i)
|
||||
if(m_values[i].id == id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if(m_values)
|
||||
delete [] m_values;
|
||||
m_values = nullptr;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
std::size_t size() { return m_size; }
|
||||
|
||||
private:
|
||||
std::tuple<uint8, boost::any>* m_attribs;
|
||||
uint8 m_size;
|
||||
value_pair *m_values;
|
||||
SizeType m_size;
|
||||
};
|
||||
|
||||
// restore memory alignment
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STDEXT_PACKEDVECTOR_H
|
||||
#define STDEXT_PACKEDVECTOR_H
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
// disable memory alignment
|
||||
#pragma pack(push,1)
|
||||
|
||||
template<class T, class U = uint8_t>
|
||||
class packed_vector
|
||||
{
|
||||
public:
|
||||
typedef U size_type;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
packed_vector() : m_size(0), m_data(nullptr) { }
|
||||
packed_vector(size_type size) : m_size(size), m_data(new T[size]) { }
|
||||
packed_vector(size_type size, const T& value) : m_size(size), m_data(new T[size](value)) { }
|
||||
template <class InputIterator>
|
||||
packed_vector(InputIterator first, InputIterator last) : m_size(last - first), m_data(new T[m_size]) { std::copy(first, last, m_data); }
|
||||
packed_vector(const packed_vector<T>& other) : m_size(other.m_size), m_data(new T[other.m_size]) { std::copy(other.begin(), other.end(), m_data); }
|
||||
~packed_vector() { if(m_data) delete[] m_data; }
|
||||
|
||||
packed_vector<T,U>& operator=(packed_vector<T,U> other) { other.swap(*this); return *this; }
|
||||
|
||||
iterator begin() { return m_data; }
|
||||
const_iterator begin() const { return m_data; }
|
||||
const_iterator cbegin() const { return m_data; }
|
||||
iterator end() { return m_data + m_size; }
|
||||
const_iterator end() const { return m_data + m_size; }
|
||||
const_iterator cend() const { return m_data + m_size; }
|
||||
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rbegin() const { return reverse_iterator(end()); }
|
||||
const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator rend() const { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
|
||||
|
||||
size_type size() const { return m_size; }
|
||||
bool empty() const { return m_size == 0; }
|
||||
|
||||
T& operator[](size_type i) { return m_data[i]; }
|
||||
const T& operator[](size_type i) const { return m_data[i]; }
|
||||
T& at(size_type i) { return m_data[i]; }
|
||||
const T& at(size_type i) const { return m_data[i]; }
|
||||
|
||||
T& front() { return m_data[0]; }
|
||||
const T& front() const { return m_data[0]; }
|
||||
T& back() { return m_data[m_size-1]; }
|
||||
const T& back() const { return m_data[m_size-1]; }
|
||||
|
||||
T *data() { return m_data; }
|
||||
const T *data() const { return m_data; }
|
||||
|
||||
void clear() {
|
||||
if(m_data) {
|
||||
delete[] m_data;
|
||||
m_data = nullptr;
|
||||
}
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void resize(size_type size) {
|
||||
clear();
|
||||
if(size > 0) {
|
||||
m_data = new T[size];
|
||||
m_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(const T& x) {
|
||||
T *tmp = new T[m_size+1];
|
||||
std::copy(m_data, m_data + m_size, tmp);
|
||||
tmp[m_size] = x;
|
||||
delete[] m_data;
|
||||
m_data = tmp;
|
||||
m_size++;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
T *tmp = new T[m_size-1];
|
||||
std::copy(m_data, m_data + m_size - 1, tmp);
|
||||
delete[] m_data;
|
||||
m_data = tmp;
|
||||
m_size--;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator position, const T& x) {
|
||||
T *tmp = new T[m_size+1];
|
||||
size_type i = position - m_data;
|
||||
std::copy(m_data, m_data + i, tmp);
|
||||
tmp[i] = x;
|
||||
std::copy(m_data + i, m_data + m_size, tmp + i + 1);
|
||||
delete[] m_data;
|
||||
m_data = tmp;
|
||||
m_size++;
|
||||
return tmp + i;
|
||||
}
|
||||
|
||||
iterator erase(const_iterator position) {
|
||||
T *tmp = new T[m_size-1];
|
||||
size_type i = position - m_data;
|
||||
std::copy(m_data, m_data + i, tmp);
|
||||
std::copy(m_data + i + 1, m_data + m_size, tmp + i);
|
||||
delete[] m_data;
|
||||
m_data = tmp;
|
||||
m_size--;
|
||||
return tmp + i;
|
||||
}
|
||||
|
||||
void swap(packed_vector<T,U>& other) { std::swap(m_size, other.m_size); std::swap(m_data, other.m_data); return *this; }
|
||||
|
||||
operator std::vector<T>() const { return std::vector<T>(begin(), end()); }
|
||||
|
||||
private:
|
||||
size_type m_size;
|
||||
T* m_data;
|
||||
};
|
||||
|
||||
// restore memory alignment
|
||||
#pragma pack(pop)
|
||||
|
||||
namespace std {
|
||||
template<class T, class U> void swap(stdext::packed_vector<T,U>& lhs, stdext::packed_vector<T,U>& rhs) { lhs.swap(rhs); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -23,55 +23,107 @@
|
|||
#ifndef STDEXT_SHARED_OBJECT_H
|
||||
#define STDEXT_SHARED_OBJECT_H
|
||||
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <cassert>
|
||||
#include <ostream>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
template<class T>
|
||||
class shared_object_ptr;
|
||||
|
||||
typedef unsigned int refcount_t;
|
||||
|
||||
class shared_object
|
||||
{
|
||||
public:
|
||||
shared_object() : m_refs(0) { }
|
||||
virtual ~shared_object() { }
|
||||
void add_ref() { ++m_refs; assert(m_refs != 0xffffffff); }
|
||||
void dec_ref() {
|
||||
if(--m_refs == 0)
|
||||
boost::checked_delete(this);
|
||||
}
|
||||
bool is_unique_ref() { return m_refs == 1; }
|
||||
unsigned long ref_count() { return m_refs; }
|
||||
template<typename T>
|
||||
boost::intrusive_ptr<T> self_cast() { return boost::intrusive_ptr<T>(static_cast<T*>(this)); }
|
||||
template<typename T>
|
||||
boost::intrusive_ptr<T> dynamic_self_cast() { return boost::intrusive_ptr<T>(dynamic_cast<T*>(this)); }
|
||||
void dec_ref() { if(--m_refs == 0) delete this; }
|
||||
refcount_t ref_count() { return m_refs; }
|
||||
|
||||
template<typename T> stdext::shared_object_ptr<T> static_self_cast() { return stdext::shared_object_ptr<T>(static_cast<T*>(this)); }
|
||||
template<typename T> stdext::shared_object_ptr<T> dynamic_self_cast() { return stdext::shared_object_ptr<T>(dynamic_cast<T*>(this)); }
|
||||
template<typename T> stdext::shared_object_ptr<T> const_self_cast() { return stdext::shared_object_ptr<T>(const_cast<T*>(this)); }
|
||||
|
||||
private:
|
||||
unsigned int m_refs;
|
||||
refcount_t m_refs;
|
||||
};
|
||||
|
||||
template<class T, typename... Args>
|
||||
boost::intrusive_ptr<T> make_shared_object(Args... args) { return boost::intrusive_ptr<T>(new T(args...)); }
|
||||
template<class T>
|
||||
class shared_object_ptr
|
||||
{
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
shared_object_ptr(): px(nullptr) { }
|
||||
shared_object_ptr(T* p, bool add_ref = true) : px(p) { if(px != nullptr && add_ref) this->add_ref(); }
|
||||
shared_object_ptr(shared_object_ptr const& rhs): px(rhs.px) { if(px != nullptr) add_ref(); }
|
||||
template<class U>
|
||||
shared_object_ptr(shared_object_ptr<U> const& rhs, typename std::is_convertible<U,T>::type* = nullptr) : px(rhs.get()) { if(px != nullptr) add_ref(); }
|
||||
~shared_object_ptr() { if(px != nullptr) dec_ref(); }
|
||||
|
||||
void reset() { shared_object_ptr().swap(*this); }
|
||||
void reset(T* rhs) { shared_object_ptr( rhs ).swap(*this); }
|
||||
void swap(shared_object_ptr& rhs) { std::swap(px, rhs.px); }
|
||||
T* get() const { return px; }
|
||||
|
||||
refcount_t use_count() const { return ((shared_object*)px)->ref_count(); }
|
||||
bool is_unique() const { return use_count() == 1; }
|
||||
|
||||
template<class U> shared_object_ptr& operator=(shared_object_ptr<U> const& rhs) { shared_object_ptr(rhs).swap(*this); return *this; }
|
||||
|
||||
T& operator*() const { assert(px != nullptr); return *px; }
|
||||
T* operator->() const { assert(px != nullptr); return px; }
|
||||
|
||||
shared_object_ptr& operator=(shared_object_ptr const& rhs) { shared_object_ptr(rhs).swap(*this); return *this; }
|
||||
shared_object_ptr& operator=(T* rhs) { shared_object_ptr(rhs).swap(*this); return *this; }
|
||||
|
||||
// implicit conversion to bool
|
||||
typedef T* shared_object_ptr::*unspecified_bool_type;
|
||||
operator unspecified_bool_type() const { return px == nullptr ? nullptr : &shared_object_ptr::px; }
|
||||
bool operator!() const { return px == nullptr; }
|
||||
|
||||
// std::move support
|
||||
shared_object_ptr(shared_object_ptr&& rhs): px(rhs.px) { rhs.px = nullptr; }
|
||||
shared_object_ptr& operator=(shared_object_ptr&& rhs) { shared_object_ptr(static_cast<shared_object_ptr&&>(rhs)).swap(*this); return *this; }
|
||||
|
||||
private:
|
||||
void add_ref() { ((shared_object*)px)->add_ref(); }
|
||||
void dec_ref() { ((shared_object*)px)->dec_ref(); }
|
||||
|
||||
T* px;
|
||||
};
|
||||
|
||||
template<class T, class U> bool operator==(shared_object_ptr<T> const& a, shared_object_ptr<U> const& b) { return a.get() == b.get(); }
|
||||
template<class T, class U> bool operator!=(shared_object_ptr<T> const& a, shared_object_ptr<U> const& b) { return a.get() != b.get(); }
|
||||
template<class T, class U> bool operator==(shared_object_ptr<T> const& a, U* b) { return a.get() == b; }
|
||||
template<class T, class U> bool operator!=(shared_object_ptr<T> const& a, U* b) { return a.get() != b; }
|
||||
template<class T, class U> bool operator==(T * a, shared_object_ptr<U> const& b) { return a == b.get(); }
|
||||
template<class T, class U> bool operator!=(T * a, shared_object_ptr<U> const& b) { return a != b.get(); }
|
||||
template<class T> bool operator<(shared_object_ptr<T> const& a, shared_object_ptr<T> const& b) { return std::less<T*>()(a.get(), b.get()); }
|
||||
|
||||
template<class T> T* get_pointer(shared_object_ptr<T> const& p) { return p.get(); }
|
||||
template<class T, class U> shared_object_ptr<T> static_pointer_cast(shared_object_ptr<U> const& p) { return static_cast<T*>(p.get()); }
|
||||
template<class T, class U> shared_object_ptr<T> const_pointer_cast(shared_object_ptr<U> const& p) { return const_cast<T*>(p.get()); }
|
||||
template<class T, class U> shared_object_ptr<T> dynamic_pointer_cast(shared_object_ptr<U> const& p) { return dynamic_cast<T*>(p.get()); }
|
||||
template<class T, typename... Args> stdext::shared_object_ptr<T> make_shared_object(Args... args) { return stdext::shared_object_ptr<T>(new T(args...)); }
|
||||
|
||||
// operator<< support
|
||||
template<class E, class T, class Y> std::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& os, shared_object_ptr<Y> const& p) { os << p.get(); return os; }
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
struct hash<boost::intrusive_ptr<T>> : public __hash_base<size_t, boost::intrusive_ptr<T>> {
|
||||
size_t operator()(const boost::intrusive_ptr<T>& p) const noexcept { return std::hash<T*>()(p.get()); }
|
||||
};
|
||||
|
||||
// hash, for unordered_map support
|
||||
template<typename T> struct hash<stdext::shared_object_ptr<T>> { size_t operator()(const stdext::shared_object_ptr<T>& p) const { return std::hash<T*>()(p.get()); } };
|
||||
|
||||
// swap support
|
||||
template<class T> void swap(stdext::shared_object_ptr<T>& lhs, stdext::shared_object_ptr<T>& rhs) { lhs.swap(rhs); }
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct remove_const_ref {
|
||||
typedef typename std::remove_const<typename std::remove_reference<T>::type>::type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void intrusive_ptr_add_ref(T* p) { (static_cast<stdext::shared_object*>(p))->add_ref(); }
|
||||
|
||||
template<typename T>
|
||||
void intrusive_ptr_release(T* p) { (static_cast<stdext::shared_object*>(p))->dec_ref(); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -24,16 +24,21 @@
|
|||
#define STDEXT_H
|
||||
|
||||
#include "compiler.h"
|
||||
#include "dumper.h"
|
||||
#include "types.h"
|
||||
#include "exception.h"
|
||||
#include "demangle.h"
|
||||
#include "cast.h"
|
||||
#include "math.h"
|
||||
#include "string.h"
|
||||
#include "dumper.h"
|
||||
#include "time.h"
|
||||
#include "shared_object.h"
|
||||
#include "attrib_storage.h"
|
||||
#include "boolean.h"
|
||||
#include "shared_object.h"
|
||||
#include "any.h"
|
||||
#include "packed_any.h"
|
||||
#include "dynamic_storage.h"
|
||||
#include "packed_storage.h"
|
||||
#include "format.h"
|
||||
#include "packed_vector.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "string.h"
|
||||
#include "format.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
std::string resolve_path(const std::string& filePath, std::string sourcePath)
|
||||
{
|
||||
if(stdext::starts_with(filePath, "/"))
|
||||
return filePath;
|
||||
if(!stdext::ends_with(sourcePath, "/")) {
|
||||
std::size_t slashPos = sourcePath.find_last_of("/");
|
||||
if(slashPos == std::string::npos)
|
||||
throw_exception(format("invalid source path '%s', for file '%s'", sourcePath, filePath));
|
||||
sourcePath = sourcePath.substr(0, slashPos + 1);
|
||||
}
|
||||
return sourcePath + filePath;
|
||||
}
|
||||
|
||||
std::string date_time_string()
|
||||
{
|
||||
char date[32];
|
||||
std::time_t tnow;
|
||||
std::time(&tnow);
|
||||
std::tm *ts = std::localtime(&tnow);
|
||||
std::strftime(date, 32, "%b %d %Y %H:%M:%S", ts);
|
||||
return std::string(date);
|
||||
}
|
||||
|
||||
std::string dec_to_hex(uint64_t num)
|
||||
{
|
||||
std::string str;
|
||||
std::ostringstream o;
|
||||
o << std::hex << num;
|
||||
str = o.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
uint64_t hex_to_dec(const std::string& str)
|
||||
{
|
||||
uint64_t num;
|
||||
std::istringstream i(str);
|
||||
i >> std::hex >> num;
|
||||
return num;
|
||||
}
|
||||
|
||||
std::string ip_to_string(uint32_t ip)
|
||||
{
|
||||
char host[16];
|
||||
sprintf(host, "%d.%d.%d.%d", (uint8_t)ip, (uint8_t)(ip >> 8), (uint8_t)(ip >> 16), (uint8_t)(ip >> 24));
|
||||
return std::string(host);
|
||||
}
|
||||
|
||||
std::string utf8_to_latin1(uchar *utf8)
|
||||
{
|
||||
auto utf8CharToLatin1 = [](uchar *utf8, int *read) -> char {
|
||||
char c = '?';
|
||||
uchar opt1 = utf8[0];
|
||||
*read = 1;
|
||||
if(opt1 == 0xc3) {
|
||||
*read = 2;
|
||||
uchar opt2 = utf8[1];
|
||||
c = 64 + opt2;
|
||||
} else if(opt1 == 0xc2) {
|
||||
*read = 2;
|
||||
uchar opt2 = utf8[1];
|
||||
if(opt2 > 0xa1 && opt2 < 0xbb)
|
||||
c = opt2;
|
||||
} else if(opt1 < 0xc2) {
|
||||
c = opt1;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
|
||||
std::string out;
|
||||
int len = strlen((char*)utf8);
|
||||
for(int i=0; i<len;) {
|
||||
int read = 0;
|
||||
uchar *utf8char = &utf8[i];
|
||||
out += utf8CharToLatin1(utf8char, &read);
|
||||
i += read;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void tolower(std::string& str)
|
||||
{
|
||||
boost::to_lower(str);
|
||||
}
|
||||
|
||||
void toupper(std::string& str)
|
||||
{
|
||||
boost::to_upper(str);
|
||||
}
|
||||
|
||||
void trim(std::string& str)
|
||||
{
|
||||
boost::trim(str);
|
||||
}
|
||||
|
||||
bool ends_with(const std::string& str, const std::string& test)
|
||||
{
|
||||
return boost::ends_with(str, test);
|
||||
}
|
||||
|
||||
bool starts_with(const std::string& str, const std::string& test)
|
||||
{
|
||||
return boost::starts_with(str, test);
|
||||
}
|
||||
|
||||
void replace_all(std::string& str, const std::string& search, const std::string& replacement)
|
||||
{
|
||||
return boost::replace_all(str, search, replacement);
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string& str, const std::string& separators)
|
||||
{
|
||||
std::vector<std::string> splitted;
|
||||
boost::split(splitted, str, boost::is_any_of(std::string(separators)));
|
||||
return splitted;
|
||||
}
|
||||
|
||||
}
|
|
@ -25,234 +25,41 @@
|
|||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "types.h"
|
||||
#include "cast.h"
|
||||
#include "exception.h"
|
||||
|
||||
namespace stdext {
|
||||
|
||||
/// Convert any type to std::string
|
||||
template<typename T>
|
||||
std::string to_string(const T& t) { return unsafe_cast<std::string, T>(t); }
|
||||
template<typename T> std::string to_string(const T& t) { return unsafe_cast<std::string, T>(t); }
|
||||
template<typename T> T from_string(const std::string& str, T def = T()) { return unsafe_cast<T, std::string>(str, def); }
|
||||
|
||||
/// Convert any type from std::string
|
||||
template<typename T>
|
||||
T from_string(const std::string& str, T def = T()) { return unsafe_cast<T, std::string>(str, def); }
|
||||
/// Resolve a file path by combining sourcePath with filePath
|
||||
std::string resolve_path(const std::string& filePath, std::string sourcePath);
|
||||
/// Get current date and time in a std::string
|
||||
std::string date_time_string();
|
||||
|
||||
/// Cast non-class types like int, char, float, double and pointers
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value ||
|
||||
std::is_pointer<T>::value ||
|
||||
std::is_floating_point<T>::value ||
|
||||
std::is_enum<T>::value, T>::type sprintf_cast(const T& t) { return t; }
|
||||
std::string dec_to_hex(uint64_t num);
|
||||
uint64_t hex_to_dec(const std::string& str);
|
||||
std::string ip_to_string(uint32_t ip);
|
||||
std::string utf8_to_latin1(uchar *utf8);
|
||||
void tolower(std::string& str);
|
||||
void toupper(std::string& str);
|
||||
void trim(std::string& str);
|
||||
bool ends_with(const std::string& str, const std::string& test);
|
||||
bool starts_with(const std::string& str, const std::string& test);
|
||||
void replace_all(std::string& str, const std::string& search, const std::string& replacement);
|
||||
|
||||
/// Cast std::string
|
||||
inline const char *sprintf_cast(const std::string& s) { return s.c_str(); }
|
||||
|
||||
template<int N>
|
||||
struct expand_snprintf{
|
||||
template<typename Tuple, typename... Args>
|
||||
static int call(char *s, size_t maxlen, const char *format, const Tuple& tuple, const Args&... args) {
|
||||
return expand_snprintf<N-1>::call(s, maxlen, format, tuple, sprintf_cast(std::get<N-1>(tuple)), args...);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct expand_snprintf<0> {
|
||||
template<typename Tuple, typename... Args>
|
||||
static int call(char *s, size_t maxlen, const char *format, const Tuple& tuple, const Args&... args) {
|
||||
return snprintf(s, maxlen, format, args...);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct replace_extent { typedef T type; };
|
||||
|
||||
template<class T>
|
||||
struct replace_extent<T[]> { typedef const T* type; };
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct replace_extent<T[N]> { typedef const T* type;};
|
||||
|
||||
/// Improved sprintf that accepts std::string and other types
|
||||
template<typename... Args>
|
||||
int snprintf(char *s, size_t maxlen, const char *format, const Args&... args) {
|
||||
typedef typename std::tuple<typename replace_extent<Args>::type...> Tuple;
|
||||
enum { N = std::tuple_size<Tuple>::value };
|
||||
Tuple tuple(args...);
|
||||
return expand_snprintf<N>::call(s, maxlen, format, tuple);
|
||||
}
|
||||
|
||||
/// Format strings with the sprintf style, accepting std::string and string convertible types for %s
|
||||
template<typename... Args>
|
||||
std::string format(const std::string& format, const Args&... args) {
|
||||
int n, size = 1024;
|
||||
std::string str;
|
||||
while(true) {
|
||||
str.resize(size);
|
||||
n = snprintf(&str[0], size, format.c_str(), args...);
|
||||
assert(n != -1);
|
||||
if(n < size) {
|
||||
str.resize(n);
|
||||
return str;
|
||||
}
|
||||
size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
inline void fill_ostream(std::ostringstream&) { }
|
||||
|
||||
/// Fills an ostream by concatenating args
|
||||
template<class T, class... Args>
|
||||
void fill_ostream(std::ostringstream& stream, const T& first, const Args&... rest) {
|
||||
stream << first;
|
||||
fill_ostream(stream, rest...);
|
||||
}
|
||||
|
||||
/// Makes a std::string by concatenating args
|
||||
template<class... T>
|
||||
std::string mkstr(const T&... args) {
|
||||
std::ostringstream buf;
|
||||
fill_ostream(buf, args...);
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
/// Easy of use split
|
||||
template<typename T = std::string>
|
||||
std::vector<T> split(const std::string& str, const std::string& separators = " ") {
|
||||
std::vector<std::string> splitted;
|
||||
boost::split(splitted, str, boost::is_any_of(std::string(separators)));
|
||||
std::vector<std::string> split(const std::string& str, const std::string& separators = " ");
|
||||
template<typename T> std::vector<T> split(const std::string& str, const std::string& separators = " ") {
|
||||
std::vector<std::string> splitted = split(str, separators);
|
||||
std::vector<T> results(splitted.size());
|
||||
for(uint i=0;i<splitted.size();++i)
|
||||
results[i] = safe_cast<T>(splitted[i]);
|
||||
return results;
|
||||
}
|
||||
|
||||
/// Resolve a file path by combining sourcePath with filePath
|
||||
inline std::string resolve_path(const std::string& filePath, std::string sourcePath) {
|
||||
if(boost::starts_with(filePath, "/"))
|
||||
return filePath;
|
||||
if(!boost::ends_with(sourcePath, "/")) {
|
||||
std::size_t slashPos = sourcePath.find_last_of("/");
|
||||
if(slashPos == std::string::npos)
|
||||
throw_exception(format("invalid source path '%s', for file '%s'", sourcePath, filePath));
|
||||
sourcePath = sourcePath.substr(0, slashPos + 1);
|
||||
}
|
||||
return sourcePath + filePath;
|
||||
}
|
||||
|
||||
/// Get current date and time in a std::string
|
||||
inline std::string date_time_string() {
|
||||
char date[32];
|
||||
std::time_t tnow;
|
||||
std::time(&tnow);
|
||||
std::tm *ts = std::localtime(&tnow);
|
||||
std::strftime(date, 32, "%b %d %Y %H:%M:%S", ts);
|
||||
return std::string(date);
|
||||
}
|
||||
|
||||
/// Convert decimal to hexadecimal
|
||||
inline std::string dec_to_hex(uint64 num) {
|
||||
std::string str;
|
||||
std::ostringstream o;
|
||||
o << std::hex << num;
|
||||
str = o.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
/// Convert hexadecimal to decimal
|
||||
inline uint64 hex_to_dec(const std::string& str) {
|
||||
uint64 num;
|
||||
std::istringstream i(str);
|
||||
i >> std::hex >> num;
|
||||
return num;
|
||||
}
|
||||
|
||||
/// Convert ip to string
|
||||
inline std::string ip_to_string(uint32 ip) {
|
||||
char host[16];
|
||||
sprintf(host, "%d.%d.%d.%d", (uint8)ip, (uint8)(ip >> 8), (uint8)(ip >> 16), (uint8)(ip >> 24));
|
||||
return std::string(host);
|
||||
}
|
||||
|
||||
/// Convert utf8 characters to latin1
|
||||
inline char utf8CharToLatin1(uchar *utf8, int *read) {
|
||||
char c = '?';
|
||||
uchar opt1 = utf8[0];
|
||||
*read = 1;
|
||||
if(opt1 == 0xc3) {
|
||||
*read = 2;
|
||||
uchar opt2 = utf8[1];
|
||||
c = 64 + opt2;
|
||||
} else if(opt1 == 0xc2) {
|
||||
*read = 2;
|
||||
uchar opt2 = utf8[1];
|
||||
if(opt2 > 0xa1 && opt2 < 0xbb)
|
||||
c = opt2;
|
||||
} else if(opt1 < 0xc2) {
|
||||
c = opt1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Convert utf8 strings to latin1
|
||||
inline std::string utf8StringToLatin1(uchar *utf8) {
|
||||
std::string out;
|
||||
int len = strlen((char*)utf8);
|
||||
for(int i=0; i<len;) {
|
||||
int read = 0;
|
||||
uchar *utf8char = &utf8[i];
|
||||
out += utf8CharToLatin1(utf8char, &read);
|
||||
i += read;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Convert string to lower case
|
||||
inline std::string tolower(const std::string& str)
|
||||
{
|
||||
std::string cpy = str;
|
||||
boost::algorithm::to_lower(cpy);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
// Convert string to upper case
|
||||
inline std::string toupper(const std::string& str)
|
||||
{
|
||||
std::string cpy = str;
|
||||
boost::algorithm::to_upper(cpy);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
// Trim string
|
||||
inline std::string trim(const std::string& str)
|
||||
{
|
||||
std::string cpy = str;
|
||||
boost::algorithm::trim(cpy);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
// utility for printing messages into stdout
|
||||
template<class... T>
|
||||
void print(const T&... args) {
|
||||
std::ostringstream buf;
|
||||
fill_ostream(buf, args...);
|
||||
std::cout << buf.str();
|
||||
}
|
||||
|
||||
template<class... T>
|
||||
void println(const T&... args) {
|
||||
print(args...);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "cast.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "time.h"
|
||||
#include <chrono>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
const static auto startup_time = std::chrono::high_resolution_clock::now();
|
||||
|
||||
ticks_t millis()
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startup_time).count();
|
||||
}
|
||||
ticks_t micros() {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - startup_time).count();
|
||||
}
|
||||
|
||||
void millisleep(size_t ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
};
|
||||
|
||||
void microsleep(size_t us)
|
||||
{
|
||||
usleep(us);
|
||||
};
|
||||
|
||||
}
|
|
@ -24,16 +24,13 @@
|
|||
#define STDEXT_TIME_H
|
||||
|
||||
#include "types.h"
|
||||
#include <chrono>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
const static auto startup_time = std::chrono::high_resolution_clock::now();
|
||||
inline ticks_t millis() { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startup_time).count(); }
|
||||
inline ticks_t micros() { return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - startup_time).count(); }
|
||||
inline void millisleep(uint32 ms) { usleep(ms * 1000); };
|
||||
inline void microsleep(uint32 us) { usleep(us); };
|
||||
ticks_t millis();
|
||||
ticks_t micros();
|
||||
void millisleep(size_t ms);
|
||||
void microsleep(size_t us);
|
||||
|
||||
struct timer {
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STDEXT_TRAITS_H
|
||||
#define STDEXT_TRAITS_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace stdext {
|
||||
|
||||
template<class T> struct replace_extent { typedef T type; };
|
||||
template<class T> struct replace_extent<T[]> { typedef const T* type; };
|
||||
template<class T, unsigned long N> struct replace_extent<T[N]> { typedef const T* type;};
|
||||
template<typename T> struct remove_const_ref { typedef typename std::remove_const<typename std::remove_reference<T>::type>::type type; };
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -23,13 +23,13 @@
|
|||
#ifndef STDEXT_TYPES_H
|
||||
#define STDEXT_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
// easy handwriting types
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
|
||||
typedef uint64_t uint64;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint16_t uint16;
|
||||
|
@ -39,19 +39,9 @@ typedef int32_t int32;
|
|||
typedef int16_t int16;
|
||||
typedef int8_t int8;
|
||||
|
||||
typedef unsigned char fast_uchar;
|
||||
typedef unsigned long fast_ushort;
|
||||
typedef unsigned long fast_uint;
|
||||
typedef unsigned long fast_ulong;
|
||||
typedef uint_fast64_t fast_uint64;
|
||||
typedef uint_fast32_t fast_uint32;
|
||||
typedef uint_fast16_t fast_uint16;
|
||||
typedef uint_fast8_t fast_uint8;
|
||||
typedef int_fast64_t fast_int64;
|
||||
typedef int_fast32_t fast_int32;
|
||||
typedef int_fast16_t fast_int16;
|
||||
typedef int_fast8_t fast_int8;
|
||||
typedef int64 ticks_t;
|
||||
|
||||
typedef int64_t ticks_t;
|
||||
using std::size_t;
|
||||
using std::ptrdiff_t;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,15 +36,15 @@ class UIGridLayout;
|
|||
class UIAnchorLayout;
|
||||
class UIParticles;
|
||||
|
||||
typedef boost::intrusive_ptr<UIWidget> UIWidgetPtr;
|
||||
typedef boost::intrusive_ptr<UIParticles> UIParticlesPtr;
|
||||
typedef boost::intrusive_ptr<UITextEdit> UITextEditPtr;
|
||||
typedef boost::intrusive_ptr<UILayout> UILayoutPtr;
|
||||
typedef boost::intrusive_ptr<UIBoxLayout> UIBoxLayoutPtr;
|
||||
typedef boost::intrusive_ptr<UIHorizontalLayout> UIHorizontalLayoutPtr;
|
||||
typedef boost::intrusive_ptr<UIVerticalLayout> UIVerticalLayoutPtr;
|
||||
typedef boost::intrusive_ptr<UIGridLayout> UIGridLayoutPtr;
|
||||
typedef boost::intrusive_ptr<UIAnchorLayout> UIAnchorLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIWidget> UIWidgetPtr;
|
||||
typedef stdext::shared_object_ptr<UIParticles> UIParticlesPtr;
|
||||
typedef stdext::shared_object_ptr<UITextEdit> UITextEditPtr;
|
||||
typedef stdext::shared_object_ptr<UILayout> UILayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIBoxLayout> UIBoxLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIHorizontalLayout> UIHorizontalLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIVerticalLayout> UIVerticalLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIGridLayout> UIGridLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIAnchorLayout> UIAnchorLayoutPtr;
|
||||
|
||||
typedef std::deque<UIWidgetPtr> UIWidgetList;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ void UILayout::updateLater()
|
|||
if(!getParentWidget())
|
||||
return;
|
||||
|
||||
auto self = self_cast<UILayout>();
|
||||
auto self = static_self_cast<UILayout>();
|
||||
g_dispatcher.addEvent([self] {
|
||||
self->m_updateScheduled = false;
|
||||
self->update();
|
||||
|
|
|
@ -321,8 +321,7 @@ bool UIManager::importStyle(const std::string& file)
|
|||
void UIManager::importStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||
{
|
||||
std::string tag = styleNode->tag();
|
||||
std::vector<std::string> split;
|
||||
boost::split(split, tag, boost::is_any_of(std::string("<")));
|
||||
std::vector<std::string> split = stdext::split(tag, "<");
|
||||
if(split.size() != 2)
|
||||
throw OTMLException(styleNode, "not a valid style declaration");
|
||||
|
||||
|
@ -330,8 +329,8 @@ void UIManager::importStyleFromOTML(const OTMLNodePtr& styleNode)
|
|||
std::string base = split[1];
|
||||
bool unique = false;
|
||||
|
||||
boost::trim(name);
|
||||
boost::trim(base);
|
||||
stdext::trim(name);
|
||||
stdext::trim(base);
|
||||
|
||||
if(name[0] == '#') {
|
||||
name = name.substr(1);
|
||||
|
@ -367,7 +366,7 @@ OTMLNodePtr UIManager::getStyle(const std::string& styleName)
|
|||
return m_styles[styleName];
|
||||
|
||||
// styles starting with UI are automatically defined
|
||||
if(boost::starts_with(styleName, "UI")) {
|
||||
if(stdext::starts_with(styleName, "UI")) {
|
||||
OTMLNodePtr node = OTMLNode::create(styleName);
|
||||
node->writeAt("__class", styleName);
|
||||
m_styles[styleName] = node;
|
||||
|
|
|
@ -278,8 +278,8 @@ void UITextEdit::appendText(std::string text)
|
|||
if(m_cursorPos >= 0) {
|
||||
// replace characters that are now allowed
|
||||
if(!m_multiline)
|
||||
boost::replace_all(text, "\n", "");
|
||||
boost::replace_all(text, "\r", " ");
|
||||
stdext::replace_all(text, "\n", "");
|
||||
stdext::replace_all(text, "\r", " ");
|
||||
|
||||
if(text.length() > 0) {
|
||||
// only add text if textedit can add it
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "uitranslator.h"
|
||||
#include <framework/stdext/string.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
Fw::AlignmentFlag Fw::translateAlignment(std::string aligment)
|
||||
|
|
|
@ -141,11 +141,11 @@ void UIWidget::addChild(const UIWidgetPtr& child)
|
|||
UIWidgetPtr oldLastChild = getLastChild();
|
||||
|
||||
m_children.push_back(child);
|
||||
child->setParent(self_cast<UIWidget>());
|
||||
child->setParent(static_self_cast<UIWidget>());
|
||||
|
||||
// create default layout
|
||||
if(!m_layout)
|
||||
m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(self_cast<UIWidget>()));
|
||||
m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(static_self_cast<UIWidget>()));
|
||||
|
||||
// add to layout and updates it
|
||||
m_layout->addWidget(child);
|
||||
|
@ -184,11 +184,11 @@ void UIWidget::insertChild(int index, const UIWidgetPtr& child)
|
|||
// retrieve child by index
|
||||
auto it = m_children.begin() + index;
|
||||
m_children.insert(it, child);
|
||||
child->setParent(self_cast<UIWidget>());
|
||||
child->setParent(static_self_cast<UIWidget>());
|
||||
|
||||
// create default layout if needed
|
||||
if(!m_layout)
|
||||
m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(self_cast<UIWidget>()));
|
||||
m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(static_self_cast<UIWidget>()));
|
||||
|
||||
// add to layout and updates it
|
||||
m_layout->addWidget(child);
|
||||
|
@ -218,7 +218,7 @@ void UIWidget::removeChild(UIWidgetPtr child)
|
|||
m_children.erase(it);
|
||||
|
||||
// reset child parent
|
||||
assert(child->getParent() == self_cast<UIWidget>());
|
||||
assert(child->getParent() == static_self_cast<UIWidget>());
|
||||
child->setParent(nullptr);
|
||||
|
||||
m_layout->removeWidget(child);
|
||||
|
@ -504,7 +504,7 @@ void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
|
|||
callLuaField("onStyleApply", styleNode->tag(), styleNode);
|
||||
|
||||
if(m_firstOnStyle) {
|
||||
auto self = self_cast<UIWidget>();
|
||||
auto self = static_self_cast<UIWidget>();
|
||||
g_dispatcher.addEvent([self] {
|
||||
self->callLuaField("onSetup");
|
||||
});
|
||||
|
@ -525,7 +525,7 @@ void UIWidget::addAnchor(Fw::AnchorEdge anchoredEdge, const std::string& hookedW
|
|||
return;
|
||||
|
||||
if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout())
|
||||
anchorLayout->addAnchor(self_cast<UIWidget>(), anchoredEdge, hookedWidgetId, hookedEdge);
|
||||
anchorLayout->addAnchor(static_self_cast<UIWidget>(), anchoredEdge, hookedWidgetId, hookedEdge);
|
||||
else
|
||||
g_logger.error(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id));
|
||||
}
|
||||
|
@ -541,8 +541,8 @@ void UIWidget::centerIn(const std::string& hookedWidgetId)
|
|||
return;
|
||||
|
||||
if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) {
|
||||
anchorLayout->addAnchor(self_cast<UIWidget>(), Fw::AnchorHorizontalCenter, hookedWidgetId, Fw::AnchorHorizontalCenter);
|
||||
anchorLayout->addAnchor(self_cast<UIWidget>(), Fw::AnchorVerticalCenter, hookedWidgetId, Fw::AnchorVerticalCenter);
|
||||
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorHorizontalCenter, hookedWidgetId, Fw::AnchorHorizontalCenter);
|
||||
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorVerticalCenter, hookedWidgetId, Fw::AnchorVerticalCenter);
|
||||
} else
|
||||
g_logger.error(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id));
|
||||
}
|
||||
|
@ -553,10 +553,10 @@ void UIWidget::fill(const std::string& hookedWidgetId)
|
|||
return;
|
||||
|
||||
if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) {
|
||||
anchorLayout->addAnchor(self_cast<UIWidget>(), Fw::AnchorLeft, hookedWidgetId, Fw::AnchorLeft);
|
||||
anchorLayout->addAnchor(self_cast<UIWidget>(), Fw::AnchorRight, hookedWidgetId, Fw::AnchorRight);
|
||||
anchorLayout->addAnchor(self_cast<UIWidget>(), Fw::AnchorTop, hookedWidgetId, Fw::AnchorTop);
|
||||
anchorLayout->addAnchor(self_cast<UIWidget>(), Fw::AnchorBottom, hookedWidgetId, Fw::AnchorBottom);
|
||||
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorLeft, hookedWidgetId, Fw::AnchorLeft);
|
||||
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorRight, hookedWidgetId, Fw::AnchorRight);
|
||||
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorTop, hookedWidgetId, Fw::AnchorTop);
|
||||
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorBottom, hookedWidgetId, Fw::AnchorBottom);
|
||||
} else
|
||||
g_logger.error(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id));
|
||||
}
|
||||
|
@ -567,7 +567,7 @@ void UIWidget::breakAnchors()
|
|||
return;
|
||||
|
||||
if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout())
|
||||
anchorLayout->removeAnchors(self_cast<UIWidget>());
|
||||
anchorLayout->removeAnchors(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::updateParentLayout()
|
||||
|
@ -601,7 +601,7 @@ void UIWidget::lock()
|
|||
return;
|
||||
|
||||
if(UIWidgetPtr parent = getParent())
|
||||
parent->lockChild(self_cast<UIWidget>());
|
||||
parent->lockChild(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::unlock()
|
||||
|
@ -610,7 +610,7 @@ void UIWidget::unlock()
|
|||
return;
|
||||
|
||||
if(UIWidgetPtr parent = getParent())
|
||||
parent->unlockChild(self_cast<UIWidget>());
|
||||
parent->unlockChild(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::focus()
|
||||
|
@ -622,7 +622,7 @@ void UIWidget::focus()
|
|||
return;
|
||||
|
||||
if(UIWidgetPtr parent = getParent())
|
||||
parent->focusChild(self_cast<UIWidget>(), Fw::ActiveFocusReason);
|
||||
parent->focusChild(static_self_cast<UIWidget>(), Fw::ActiveFocusReason);
|
||||
}
|
||||
|
||||
void UIWidget::recursiveFocus(Fw::FocusReason reason)
|
||||
|
@ -632,7 +632,7 @@ void UIWidget::recursiveFocus(Fw::FocusReason reason)
|
|||
|
||||
if(UIWidgetPtr parent = getParent()) {
|
||||
if(m_focusable)
|
||||
parent->focusChild(self_cast<UIWidget>(), reason);
|
||||
parent->focusChild(static_self_cast<UIWidget>(), reason);
|
||||
parent->recursiveFocus(reason);
|
||||
}
|
||||
}
|
||||
|
@ -644,7 +644,7 @@ void UIWidget::lower()
|
|||
|
||||
UIWidgetPtr parent = getParent();
|
||||
if(parent)
|
||||
parent->lowerChild(self_cast<UIWidget>());
|
||||
parent->lowerChild(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::raise()
|
||||
|
@ -654,7 +654,7 @@ void UIWidget::raise()
|
|||
|
||||
UIWidgetPtr parent = getParent();
|
||||
if(parent)
|
||||
parent->raiseChild(self_cast<UIWidget>());
|
||||
parent->raiseChild(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::grabMouse()
|
||||
|
@ -662,12 +662,12 @@ void UIWidget::grabMouse()
|
|||
if(m_destroyed)
|
||||
return;
|
||||
|
||||
g_ui.setMouseReceiver(self_cast<UIWidget>());
|
||||
g_ui.setMouseReceiver(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::ungrabMouse()
|
||||
{
|
||||
if(g_ui.getMouseReceiver() == self_cast<UIWidget>())
|
||||
if(g_ui.getMouseReceiver() == static_self_cast<UIWidget>())
|
||||
g_ui.resetMouseReceiver();
|
||||
}
|
||||
|
||||
|
@ -676,12 +676,12 @@ void UIWidget::grabKeyboard()
|
|||
if(m_destroyed)
|
||||
return;
|
||||
|
||||
g_ui.setKeyboardReceiver(self_cast<UIWidget>());
|
||||
g_ui.setKeyboardReceiver(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::ungrabKeyboard()
|
||||
{
|
||||
if(g_ui.getKeyboardReceiver() == self_cast<UIWidget>())
|
||||
if(g_ui.getKeyboardReceiver() == static_self_cast<UIWidget>())
|
||||
g_ui.resetKeyboardReceiver();
|
||||
}
|
||||
|
||||
|
@ -721,7 +721,7 @@ void UIWidget::internalDestroy()
|
|||
|
||||
releaseLuaFieldsTable();
|
||||
|
||||
g_ui.onWidgetDestroy(self_cast<UIWidget>());
|
||||
g_ui.onWidgetDestroy(static_self_cast<UIWidget>());
|
||||
}
|
||||
|
||||
void UIWidget::destroy()
|
||||
|
@ -730,7 +730,7 @@ void UIWidget::destroy()
|
|||
g_logger.warning(stdext::format("attempt to destroy widget '%s' two times", m_id));
|
||||
|
||||
// hold itself reference
|
||||
UIWidgetPtr self = self_cast<UIWidget>();
|
||||
UIWidgetPtr self = static_self_cast<UIWidget>();
|
||||
m_destroyed = true;
|
||||
|
||||
// remove itself from parent
|
||||
|
@ -775,7 +775,7 @@ void UIWidget::setParent(const UIWidgetPtr& parent)
|
|||
if(oldParent == parent)
|
||||
return;
|
||||
|
||||
UIWidgetPtr self = self_cast<UIWidget>();
|
||||
UIWidgetPtr self = static_self_cast<UIWidget>();
|
||||
if(oldParent && oldParent->hasChild(self))
|
||||
oldParent->removeChild(self);
|
||||
|
||||
|
@ -797,7 +797,7 @@ void UIWidget::setLayout(const UILayoutPtr& layout)
|
|||
if(m_layout)
|
||||
m_layout->disableUpdates();
|
||||
|
||||
layout->setParent(self_cast<UIWidget>());
|
||||
layout->setParent(static_self_cast<UIWidget>());
|
||||
layout->disableUpdates();
|
||||
|
||||
for(const UIWidgetPtr& child : m_children) {
|
||||
|
@ -836,7 +836,7 @@ bool UIWidget::setRect(const Rect& rect)
|
|||
|
||||
// avoid massive update events
|
||||
if(!m_updateEventScheduled) {
|
||||
UIWidgetPtr self = self_cast<UIWidget>();
|
||||
UIWidgetPtr self = static_self_cast<UIWidget>();
|
||||
g_dispatcher.addEvent([self, oldRect]() {
|
||||
self->m_updateEventScheduled = false;
|
||||
if(oldRect != self->getRect())
|
||||
|
@ -896,9 +896,9 @@ void UIWidget::setVisible(bool visible)
|
|||
|
||||
// visibility can change the current hovered widget
|
||||
if(visible)
|
||||
g_ui.onWidgetAppear(self_cast<UIWidget>());
|
||||
g_ui.onWidgetAppear(static_self_cast<UIWidget>());
|
||||
else
|
||||
g_ui.onWidgetDisappear(self_cast<UIWidget>());
|
||||
g_ui.onWidgetDisappear(static_self_cast<UIWidget>());
|
||||
|
||||
callLuaField("onVisibilityChange", visible);
|
||||
}
|
||||
|
@ -963,14 +963,14 @@ bool UIWidget::isVisible()
|
|||
else if(UIWidgetPtr parent = getParent())
|
||||
return parent->isVisible();
|
||||
else
|
||||
return self_cast<UIWidget>() == g_ui.getRootWidget();
|
||||
return static_self_cast<UIWidget>() == g_ui.getRootWidget();
|
||||
}
|
||||
|
||||
bool UIWidget::isAnchored()
|
||||
{
|
||||
if(UIWidgetPtr parent = getParent())
|
||||
if(UIAnchorLayoutPtr anchorLayout = parent->getAnchoredLayout())
|
||||
return anchorLayout->hasAnchors(self_cast<UIWidget>());
|
||||
return anchorLayout->hasAnchors(static_self_cast<UIWidget>());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1046,7 @@ UIAnchorLayoutPtr UIWidget::getAnchoredLayout()
|
|||
|
||||
UILayoutPtr layout = parent->getLayout();
|
||||
if(layout->isUIAnchorLayout())
|
||||
return layout->self_cast<UIAnchorLayout>();
|
||||
return layout->static_self_cast<UIAnchorLayout>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1055,7 +1055,7 @@ UIWidgetPtr UIWidget::getRootParent()
|
|||
if(UIWidgetPtr parent = getParent())
|
||||
return parent->getRootParent();
|
||||
else
|
||||
return self_cast<UIWidget>();
|
||||
return static_self_cast<UIWidget>();
|
||||
}
|
||||
|
||||
UIWidgetPtr UIWidget::getChildAfter(const UIWidgetPtr& relativeChild)
|
||||
|
@ -1231,7 +1231,7 @@ void UIWidget::updateState(Fw::WidgetState state)
|
|||
|
||||
switch(state) {
|
||||
case Fw::ActiveState: {
|
||||
UIWidgetPtr widget = self_cast<UIWidget>();
|
||||
UIWidgetPtr widget = static_self_cast<UIWidget>();
|
||||
UIWidgetPtr parent;
|
||||
do {
|
||||
parent = widget->getParent();
|
||||
|
@ -1246,24 +1246,24 @@ void UIWidget::updateState(Fw::WidgetState state)
|
|||
break;
|
||||
}
|
||||
case Fw::FocusState: {
|
||||
newStatus = (getParent() && getParent()->getFocusedChild() == self_cast<UIWidget>());
|
||||
newStatus = (getParent() && getParent()->getFocusedChild() == static_self_cast<UIWidget>());
|
||||
break;
|
||||
}
|
||||
case Fw::HoverState: {
|
||||
newStatus = (g_ui.getHoveredWidget() == self_cast<UIWidget>() && isEnabled());
|
||||
newStatus = (g_ui.getHoveredWidget() == static_self_cast<UIWidget>() && isEnabled());
|
||||
break;
|
||||
}
|
||||
case Fw::PressedState: {
|
||||
newStatus = (g_ui.getPressedWidget() == self_cast<UIWidget>());
|
||||
newStatus = (g_ui.getPressedWidget() == static_self_cast<UIWidget>());
|
||||
break;
|
||||
}
|
||||
case Fw::DraggingState: {
|
||||
newStatus = (g_ui.getDraggingWidget() == self_cast<UIWidget>());
|
||||
newStatus = (g_ui.getDraggingWidget() == static_self_cast<UIWidget>());
|
||||
break;
|
||||
}
|
||||
case Fw::DisabledState: {
|
||||
bool enabled = true;
|
||||
UIWidgetPtr widget = self_cast<UIWidget>();
|
||||
UIWidgetPtr widget = static_self_cast<UIWidget>();
|
||||
do {
|
||||
if(!widget->isExplicitlyEnabled()) {
|
||||
enabled = false;
|
||||
|
@ -1275,19 +1275,19 @@ void UIWidget::updateState(Fw::WidgetState state)
|
|||
break;
|
||||
}
|
||||
case Fw::FirstState: {
|
||||
newStatus = (getParent() && getParent()->getFirstChild() == self_cast<UIWidget>());
|
||||
newStatus = (getParent() && getParent()->getFirstChild() == static_self_cast<UIWidget>());
|
||||
break;
|
||||
}
|
||||
case Fw::MiddleState: {
|
||||
newStatus = (getParent() && getParent()->getFirstChild() != self_cast<UIWidget>() && getParent()->getLastChild() != self_cast<UIWidget>());
|
||||
newStatus = (getParent() && getParent()->getFirstChild() != static_self_cast<UIWidget>() && getParent()->getLastChild() != static_self_cast<UIWidget>());
|
||||
break;
|
||||
}
|
||||
case Fw::LastState: {
|
||||
newStatus = (getParent() && getParent()->getLastChild() == self_cast<UIWidget>());
|
||||
newStatus = (getParent() && getParent()->getLastChild() == static_self_cast<UIWidget>());
|
||||
break;
|
||||
}
|
||||
case Fw::AlternateState: {
|
||||
newStatus = (getParent() && (getParent()->getChildIndex(self_cast<UIWidget>()) % 2) == 1);
|
||||
newStatus = (getParent() && (getParent()->getChildIndex(static_self_cast<UIWidget>()) % 2) == 1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1337,7 +1337,7 @@ void UIWidget::updateStyle()
|
|||
return;
|
||||
|
||||
if(m_loadingStyle && !m_updateStyleScheduled) {
|
||||
UIWidgetPtr self = self_cast<UIWidget>();
|
||||
UIWidgetPtr self = static_self_cast<UIWidget>();
|
||||
g_dispatcher.addEvent([self] {
|
||||
self->m_updateStyleScheduled = false;
|
||||
self->updateStyle();
|
||||
|
@ -1361,10 +1361,9 @@ void UIWidget::updateStyle()
|
|||
|
||||
// checks for states combination
|
||||
for(const OTMLNodePtr& style : m_style->children()) {
|
||||
if(boost::starts_with(style->tag(), "$")) {
|
||||
if(stdext::starts_with(style->tag(), "$")) {
|
||||
std::string statesStr = style->tag().substr(1);
|
||||
std::vector<std::string> statesSplit;
|
||||
boost::split(statesSplit, statesStr, boost::is_any_of(std::string(" ")));
|
||||
std::vector<std::string> statesSplit = stdext::split(statesStr, " ");
|
||||
|
||||
bool match = true;
|
||||
for(std::string stateStr : statesSplit) {
|
||||
|
@ -1642,7 +1641,7 @@ bool UIWidget::propagateOnMouseEvent(const Point& mousePos, UIWidgetList& widget
|
|||
}
|
||||
}
|
||||
|
||||
widgetList.push_back(self_cast<UIWidget>());
|
||||
widgetList.push_back(static_self_cast<UIWidget>());
|
||||
|
||||
if(!isPhantom())
|
||||
ret = true;
|
||||
|
@ -1657,6 +1656,6 @@ bool UIWidget::propagateOnMouseMove(const Point& mousePos, const Point& mouseMov
|
|||
child->propagateOnMouseMove(mousePos, mouseMoved, widgetList);
|
||||
}
|
||||
|
||||
widgetList.push_back(self_cast<UIWidget>());
|
||||
widgetList.push_back(static_self_cast<UIWidget>());
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -162,8 +162,7 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
|
|||
setMarginLeft(node->value<int>());
|
||||
else if(node->tag() == "margin") {
|
||||
std::string marginDesc = node->value();
|
||||
std::vector<std::string> split;
|
||||
boost::split(split, marginDesc, boost::is_any_of(std::string(" ")));
|
||||
std::vector<std::string> split = stdext::split(marginDesc, " ");
|
||||
if(split.size() == 4) {
|
||||
setMarginTop(stdext::safe_cast<int>(split[0]));
|
||||
setMarginRight(stdext::safe_cast<int>(split[1]));
|
||||
|
@ -202,8 +201,7 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
|
|||
setPaddingLeft(node->value<int>());
|
||||
else if(node->tag() == "padding") {
|
||||
std::string paddingDesc = node->value();
|
||||
std::vector<std::string> split;
|
||||
boost::split(split, paddingDesc, boost::is_any_of(std::string(" ")));
|
||||
std::vector<std::string> split = stdext::split(paddingDesc, " ");
|
||||
if(split.size() == 4) {
|
||||
setPaddingTop(stdext::safe_cast<int>(split[0]));
|
||||
setPaddingRight(stdext::safe_cast<int>(split[1]));
|
||||
|
@ -243,13 +241,13 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
|
|||
if(!layoutType.empty()) {
|
||||
UILayoutPtr layout;
|
||||
if(layoutType == "horizontalBox")
|
||||
layout = UIHorizontalLayoutPtr(new UIHorizontalLayout(self_cast<UIWidget>()));
|
||||
layout = UIHorizontalLayoutPtr(new UIHorizontalLayout(static_self_cast<UIWidget>()));
|
||||
else if(layoutType == "verticalBox")
|
||||
layout = UIVerticalLayoutPtr(new UIVerticalLayout(self_cast<UIWidget>()));
|
||||
layout = UIVerticalLayoutPtr(new UIVerticalLayout(static_self_cast<UIWidget>()));
|
||||
else if(layoutType == "grid")
|
||||
layout = UIGridLayoutPtr(new UIGridLayout(self_cast<UIWidget>()));
|
||||
layout = UIGridLayoutPtr(new UIGridLayout(static_self_cast<UIWidget>()));
|
||||
else if(layoutType == "anchor")
|
||||
layout = UIAnchorLayoutPtr(new UIAnchorLayout(self_cast<UIWidget>()));
|
||||
layout = UIAnchorLayoutPtr(new UIAnchorLayout(static_self_cast<UIWidget>()));
|
||||
else
|
||||
throw OTMLException(node, "cannot determine layout type");
|
||||
setLayout(layout);
|
||||
|
@ -259,7 +257,7 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
|
|||
m_layout->applyStyle(node);
|
||||
}
|
||||
// anchors
|
||||
else if(boost::starts_with(node->tag(), "anchors.")) {
|
||||
else if(stdext::starts_with(node->tag(), "anchors.")) {
|
||||
UIWidgetPtr parent = getParent();
|
||||
if(!parent) {
|
||||
if(m_firstOnStyle)
|
||||
|
@ -271,7 +269,7 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
|
|||
UILayoutPtr layout = parent->getLayout();
|
||||
UIAnchorLayoutPtr anchorLayout;
|
||||
if(layout->isUIAnchorLayout())
|
||||
anchorLayout = layout->self_cast<UIAnchorLayout>();
|
||||
anchorLayout = layout->static_self_cast<UIAnchorLayout>();
|
||||
|
||||
if(!anchorLayout)
|
||||
throw OTMLException(node, "cannot create anchor, the parent widget doesn't use anchor layout!");
|
||||
|
@ -304,7 +302,7 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
|
|||
}
|
||||
}
|
||||
// lua functions
|
||||
} else if(boost::starts_with(node->tag(), "@")) {
|
||||
} else if(stdext::starts_with(node->tag(), "@")) {
|
||||
// load once
|
||||
if(m_firstOnStyle) {
|
||||
std::string funcName = node->tag().substr(1);
|
||||
|
@ -313,7 +311,7 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
|
|||
luaSetField(funcName);
|
||||
}
|
||||
// lua fields value
|
||||
} else if(boost::starts_with(node->tag(), "&")) {
|
||||
} else if(stdext::starts_with(node->tag(), "&")) {
|
||||
std::string fieldName = node->tag().substr(1);
|
||||
std::string fieldOrigin = "@" + node->source() + "[" + node->tag() + "]";
|
||||
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
#include "../stdext/types.h"
|
||||
#include "../stdext/cast.h"
|
||||
#include "../stdext/string.h"
|
||||
#include "../const.h"
|
||||
#include <iomanip>
|
||||
|
||||
class Color
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@ set(otclient_SOURCES ${otclient_SOURCES}
|
|||
${CMAKE_CURRENT_LIST_DIR}/localplayer.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/map.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/map.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapio.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapview.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapview.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/missile.cpp
|
||||
|
|
|
@ -47,7 +47,7 @@ void AnimatedText::drawText(const Point& dest, const Rect& visibleRect)
|
|||
}
|
||||
}
|
||||
|
||||
void AnimatedText::startAnimation()
|
||||
void AnimatedText::onAppear()
|
||||
{
|
||||
m_animationTimer.restart();
|
||||
|
||||
|
|
|
@ -35,14 +35,16 @@ public:
|
|||
AnimatedText();
|
||||
|
||||
void drawText(const Point& dest, const Rect& visibleRect);
|
||||
void startAnimation();
|
||||
|
||||
void setColor(int color);
|
||||
void setText(const std::string& text);
|
||||
|
||||
AnimatedTextPtr asAnimatedText() { return self_cast<AnimatedText>(); }
|
||||
AnimatedTextPtr asAnimatedText() { return static_self_cast<AnimatedText>(); }
|
||||
bool isAnimatedText() { return true; }
|
||||
|
||||
protected:
|
||||
virtual void onAppear();
|
||||
|
||||
private:
|
||||
Color m_color;
|
||||
Timer m_animationTimer;
|
||||
|
|
|
@ -302,6 +302,11 @@ void Creature::stopWalk()
|
|||
terminateWalk();
|
||||
}
|
||||
|
||||
void Creature::onMove(const Position& newPos, const Position& oldPos)
|
||||
{
|
||||
walk(oldPos, newPos);
|
||||
}
|
||||
|
||||
void Creature::updateWalkAnimation(int totalPixelsWalked)
|
||||
{
|
||||
// update outfit animation
|
||||
|
@ -353,9 +358,9 @@ void Creature::updateWalkingTile()
|
|||
|
||||
if(newWalkingTile != m_walkingTile) {
|
||||
if(m_walkingTile)
|
||||
m_walkingTile->removeWalkingCreature(self_cast<Creature>());
|
||||
m_walkingTile->removeWalkingCreature(static_self_cast<Creature>());
|
||||
if(newWalkingTile)
|
||||
newWalkingTile->addWalkingCreature(self_cast<Creature>());
|
||||
newWalkingTile->addWalkingCreature(static_self_cast<Creature>());
|
||||
m_walkingTile = newWalkingTile;
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +376,7 @@ void Creature::nextWalkUpdate()
|
|||
|
||||
// schedules next update
|
||||
if(m_walking) {
|
||||
auto self = self_cast<Creature>();
|
||||
auto self = static_self_cast<Creature>();
|
||||
m_walkUpdateEvent = g_dispatcher.scheduleEvent([self] {
|
||||
self->m_walkUpdateEvent = nullptr;
|
||||
self->nextWalkUpdate();
|
||||
|
@ -409,7 +414,7 @@ void Creature::terminateWalk()
|
|||
}
|
||||
|
||||
if(m_walkingTile) {
|
||||
m_walkingTile->removeWalkingCreature(self_cast<Creature>());
|
||||
m_walkingTile->removeWalkingCreature(static_self_cast<Creature>());
|
||||
m_walkingTile = nullptr;
|
||||
}
|
||||
|
||||
|
@ -496,7 +501,7 @@ void Creature::setShieldTexture(const std::string& filename, bool blink)
|
|||
m_showShieldTexture = true;
|
||||
|
||||
if(blink && !m_shieldBlink) {
|
||||
auto self = self_cast<Creature>();
|
||||
auto self = static_self_cast<Creature>();
|
||||
g_dispatcher.scheduleEvent([self]() {
|
||||
self->updateShield();
|
||||
}, SHIELD_BLINK_TICKS);
|
||||
|
@ -516,7 +521,7 @@ void Creature::addTimedSquare(uint8 color)
|
|||
m_timedSquareColor = Color::from8bit(color);
|
||||
|
||||
// schedule removal
|
||||
auto self = self_cast<Creature>();
|
||||
auto self = static_self_cast<Creature>();
|
||||
g_dispatcher.scheduleEvent([self]() {
|
||||
self->removeTimedSquare();
|
||||
}, VOLATILE_SQUARE_DURATION);
|
||||
|
@ -527,7 +532,7 @@ void Creature::updateShield()
|
|||
m_showShieldTexture = !m_showShieldTexture;
|
||||
|
||||
if(m_shield != Otc::ShieldNone && m_shieldBlink) {
|
||||
auto self = self_cast<Creature>();
|
||||
auto self = static_self_cast<Creature>();
|
||||
g_dispatcher.scheduleEvent([self]() {
|
||||
self->updateShield();
|
||||
}, SHIELD_BLINK_TICKS);
|
||||
|
|
|
@ -100,6 +100,9 @@ public:
|
|||
const ThingTypePtr& getThingType();
|
||||
ThingType *rawGetThingType();
|
||||
|
||||
protected:
|
||||
virtual void onMove(const Position& newPos, const Position& oldPos);
|
||||
|
||||
protected:
|
||||
virtual void updateWalkAnimation(int totalPixelsWalked);
|
||||
virtual void updateWalkOffset(int totalPixelsWalked);
|
||||
|
|
|
@ -80,7 +80,11 @@ void Creatures::loadCreatureBuffer(const std::string &buffer)
|
|||
if(!root || (root->ValueStr() != "monster" && root->ValueStr() != "npc"))
|
||||
stdext::throw_exception("invalid root tag name");
|
||||
|
||||
CreatureTypePtr newType(new CreatureType(stdext::trim(stdext::tolower(root->Attribute("name")))));
|
||||
std::string cName = root->Attribute("name");
|
||||
stdext::tolower(cName);
|
||||
stdext::trim(cName);
|
||||
|
||||
CreatureTypePtr newType(new CreatureType(cName));
|
||||
for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
|
||||
if(attrib->ValueStr() != "look")
|
||||
continue;
|
||||
|
@ -120,9 +124,11 @@ bool Creatures::m_loadCreatureBuffer(TiXmlElement* attrib, const CreatureTypePtr
|
|||
return type >= 0;
|
||||
}
|
||||
|
||||
CreatureTypePtr Creatures::getCreature(const std::string& name)
|
||||
CreatureTypePtr Creatures::getCreature(std::string name)
|
||||
{
|
||||
stdext::tolower(name);
|
||||
stdext::trim(name);
|
||||
auto it = std::find_if(m_creatures.begin(), m_creatures.end(),
|
||||
[=] (const CreatureTypePtr& m) -> bool { return m->getName() == stdext::trim(stdext::tolower(name)); });
|
||||
[=] (const CreatureTypePtr& m) -> bool { return m->getName() == name; });
|
||||
return it != m_creatures.end() ? *it : nullptr;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
int getSpawnTime() { return m_attribs.get<int>(CreatureAttrSpawnTime); }
|
||||
|
||||
private:
|
||||
stdext::attrib_storage m_attribs;
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
};
|
||||
|
||||
class Creatures
|
||||
|
@ -63,7 +63,7 @@ public:
|
|||
void loadNpcs(const std::string& folder);
|
||||
void loadCreatureBuffer(const std::string& buffer);
|
||||
|
||||
CreatureTypePtr getCreature(const std::string& name);
|
||||
CreatureTypePtr getCreature(std::string name);
|
||||
bool isLoaded() const { return m_loaded; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -50,25 +50,25 @@ class House;
|
|||
class Town;
|
||||
class CreatureType;
|
||||
|
||||
typedef boost::intrusive_ptr<MapView> MapViewPtr;
|
||||
typedef boost::intrusive_ptr<Tile> TilePtr;
|
||||
typedef boost::intrusive_ptr<Thing> ThingPtr;
|
||||
typedef boost::intrusive_ptr<Item> ItemPtr;
|
||||
typedef boost::intrusive_ptr<Container> ContainerPtr;
|
||||
typedef boost::intrusive_ptr<Creature> CreaturePtr;
|
||||
typedef boost::intrusive_ptr<Monster> MonsterPtr;
|
||||
typedef boost::intrusive_ptr<Npc> NpcPtr;
|
||||
typedef boost::intrusive_ptr<Player> PlayerPtr;
|
||||
typedef boost::intrusive_ptr<LocalPlayer> LocalPlayerPtr;
|
||||
typedef boost::intrusive_ptr<Effect> EffectPtr;
|
||||
typedef boost::intrusive_ptr<Missile> MissilePtr;
|
||||
typedef boost::intrusive_ptr<AnimatedText> AnimatedTextPtr;
|
||||
typedef boost::intrusive_ptr<StaticText> StaticTextPtr;
|
||||
typedef boost::intrusive_ptr<ThingType> ThingTypePtr;
|
||||
typedef boost::intrusive_ptr<ItemType> ItemTypePtr;
|
||||
typedef boost::intrusive_ptr<House> HousePtr;
|
||||
typedef boost::intrusive_ptr<Town> TownPtr;
|
||||
typedef boost::intrusive_ptr<CreatureType> CreatureTypePtr;
|
||||
typedef stdext::shared_object_ptr<MapView> MapViewPtr;
|
||||
typedef stdext::shared_object_ptr<Tile> TilePtr;
|
||||
typedef stdext::shared_object_ptr<Thing> ThingPtr;
|
||||
typedef stdext::shared_object_ptr<Item> ItemPtr;
|
||||
typedef stdext::shared_object_ptr<Container> ContainerPtr;
|
||||
typedef stdext::shared_object_ptr<Creature> CreaturePtr;
|
||||
typedef stdext::shared_object_ptr<Monster> MonsterPtr;
|
||||
typedef stdext::shared_object_ptr<Npc> NpcPtr;
|
||||
typedef stdext::shared_object_ptr<Player> PlayerPtr;
|
||||
typedef stdext::shared_object_ptr<LocalPlayer> LocalPlayerPtr;
|
||||
typedef stdext::shared_object_ptr<Effect> EffectPtr;
|
||||
typedef stdext::shared_object_ptr<Missile> MissilePtr;
|
||||
typedef stdext::shared_object_ptr<AnimatedText> AnimatedTextPtr;
|
||||
typedef stdext::shared_object_ptr<StaticText> StaticTextPtr;
|
||||
typedef stdext::shared_object_ptr<ThingType> ThingTypePtr;
|
||||
typedef stdext::shared_object_ptr<ItemType> ItemTypePtr;
|
||||
typedef stdext::shared_object_ptr<House> HousePtr;
|
||||
typedef stdext::shared_object_ptr<Town> TownPtr;
|
||||
typedef stdext::shared_object_ptr<CreatureType> CreatureTypePtr;
|
||||
|
||||
typedef std::vector<ThingPtr> ThingList;
|
||||
typedef std::vector<ThingTypePtr> ThingTypeList;
|
||||
|
@ -81,8 +81,8 @@ typedef std::unordered_map<Position, TilePtr, PositionHasher> TileMap;
|
|||
class ProtocolLogin;
|
||||
class ProtocolGame;
|
||||
|
||||
typedef boost::intrusive_ptr<ProtocolGame> ProtocolGamePtr;
|
||||
typedef boost::intrusive_ptr<ProtocolLogin> ProtocolLoginPtr;
|
||||
typedef stdext::shared_object_ptr<ProtocolGame> ProtocolGamePtr;
|
||||
typedef stdext::shared_object_ptr<ProtocolLogin> ProtocolLoginPtr;
|
||||
|
||||
// ui
|
||||
class UIItem;
|
||||
|
@ -90,9 +90,9 @@ class UICreature;
|
|||
class UIMap;
|
||||
class UIProgressRect;
|
||||
|
||||
typedef boost::intrusive_ptr<UIItem> UIItemPtr;
|
||||
typedef boost::intrusive_ptr<UICreature> UICreaturePtr;
|
||||
typedef boost::intrusive_ptr<UIMap> UIMapPtr;
|
||||
typedef boost::intrusive_ptr<UIProgressRect> UIProgressRectPtr;
|
||||
typedef stdext::shared_object_ptr<UIItem> UIItemPtr;
|
||||
typedef stdext::shared_object_ptr<UICreature> UICreaturePtr;
|
||||
typedef stdext::shared_object_ptr<UIMap> UIMapPtr;
|
||||
typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,7 @@ void Effect::draw(const Point& dest, float scaleFactor, bool animate)
|
|||
rawGetThingType()->draw(dest, scaleFactor, 0, 0, 0, 0, animationPhase);
|
||||
}
|
||||
|
||||
void Effect::startAnimation()
|
||||
void Effect::onAppear()
|
||||
{
|
||||
m_animationTimer.restart();
|
||||
m_phaseDuration = EFFECT_TICKS_PER_FRAME;
|
||||
|
|
|
@ -33,20 +33,22 @@ class Effect : public Thing
|
|||
enum {
|
||||
EFFECT_TICKS_PER_FRAME = 75
|
||||
};
|
||||
|
||||
public:
|
||||
void draw(const Point& dest, float scaleFactor, bool animate);
|
||||
|
||||
void setId(uint32 id);
|
||||
void startAnimation();
|
||||
|
||||
uint32 getId() { return m_id; }
|
||||
|
||||
EffectPtr asEffect() { return self_cast<Effect>(); }
|
||||
EffectPtr asEffect() { return static_self_cast<Effect>(); }
|
||||
bool isEffect() { return true; }
|
||||
|
||||
const ThingTypePtr& getThingType();
|
||||
ThingType *rawGetThingType();
|
||||
|
||||
protected:
|
||||
void onAppear();
|
||||
|
||||
private:
|
||||
Timer m_animationTimer;
|
||||
uint m_phaseDuration;
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "outfit.h"
|
||||
#include <framework/core/timer.h>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
typedef std::tuple<std::string, bool> Vip;
|
||||
|
||||
//@bindsingleton g_game
|
||||
|
|
|
@ -63,7 +63,7 @@ protected:
|
|||
void save(TiXmlElement &elem) { } // TODO
|
||||
|
||||
private:
|
||||
stdext::attrib_storage m_attribs;
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
TileMap m_tiles;
|
||||
stdext::boolean<false> m_isGuildHall;
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ public:
|
|||
bool isTeleport() { return m_attribs.has(ATTR_TELE_DEST); }
|
||||
bool isMoveable();
|
||||
|
||||
ItemPtr asItem() { return self_cast<Item>(); }
|
||||
ItemPtr asItem() { return static_self_cast<Item>(); }
|
||||
bool isItem() { return true; }
|
||||
|
||||
const ThingTypePtr& getThingType();
|
||||
|
@ -125,7 +125,7 @@ private:
|
|||
uint16 m_id;
|
||||
uint16 m_otbId;
|
||||
uint8 m_countOrSubType;
|
||||
stdext::attrib_storage m_attribs;
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ private:
|
|||
ItemCategory m_category;
|
||||
stdext::boolean<true> m_null;
|
||||
|
||||
stdext::attrib_storage m_attribs;
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
bool isAutoWalking() { return m_autoWalking; }
|
||||
bool isPremium() { return m_premium; }
|
||||
|
||||
LocalPlayerPtr asLocalPlayer() { return self_cast<LocalPlayer>(); }
|
||||
LocalPlayerPtr asLocalPlayer() { return static_self_cast<LocalPlayer>(); }
|
||||
bool isLocalPlayer() { return true; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -27,14 +27,10 @@
|
|||
#include "item.h"
|
||||
#include "missile.h"
|
||||
#include "statictext.h"
|
||||
#include "mapview.h"
|
||||
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include "mapview.h"
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/core/binarytree.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/xml/tinyxml.h>
|
||||
|
||||
Map g_map;
|
||||
TilePtr Map::m_nulltile;
|
||||
|
@ -62,513 +58,6 @@ void Map::notificateTileUpdateToMapViews(const Position& pos)
|
|||
mapView->onTileUpdate(pos);
|
||||
}
|
||||
|
||||
void Map::loadOtbm(const std::string& fileName)
|
||||
{
|
||||
FileStreamPtr fin = g_resources.openFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("Unable to load map '%s'", fileName));
|
||||
|
||||
fin->cache();
|
||||
if(!g_things.isOtbLoaded())
|
||||
stdext::throw_exception("OTB isn't loaded yet to load a map.");
|
||||
|
||||
if(fin->getU32())
|
||||
stdext::throw_exception("Unknown file version detected");
|
||||
|
||||
BinaryTreePtr root = fin->getBinaryTree();
|
||||
if(root->getU8())
|
||||
stdext::throw_exception("could not read root property!");
|
||||
|
||||
uint32 headerVersion = root->getU32();
|
||||
if(!headerVersion || headerVersion > 3)
|
||||
stdext::throw_exception(stdext::format("Unknown OTBM version detected: %u.", headerVersion));
|
||||
|
||||
setWidth(root->getU16());
|
||||
setHeight(root->getU16());
|
||||
|
||||
uint32 headerMajorItems = root->getU8();
|
||||
if(headerMajorItems < 3) {
|
||||
stdext::throw_exception(stdext::format("This map needs to be upgraded. read %d what it's supposed to be: %u",
|
||||
headerMajorItems, g_things.getOtbMajorVersion()));
|
||||
}
|
||||
|
||||
if(headerMajorItems > g_things.getOtbMajorVersion()) {
|
||||
stdext::throw_exception(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d",
|
||||
headerMajorItems, g_things.getOtbMajorVersion()));
|
||||
}
|
||||
|
||||
root->skip(3);
|
||||
uint32 headerMinorItems = root->getU32();
|
||||
if(headerMinorItems > g_things.getOtbMinorVersion()) {
|
||||
g_logger.warning(stdext::format("This map needs an updated OTB. read %d what it's supposed to be: %d or less",
|
||||
headerMinorItems, g_things.getOtbMinorVersion()));
|
||||
}
|
||||
|
||||
BinaryTreePtr node = root->getChildren()[0];
|
||||
if(node->getU8() != OTBM_MAP_DATA)
|
||||
stdext::throw_exception("Could not read root data node");
|
||||
|
||||
while (node->canRead()) {
|
||||
uint8 attribute = node->getU8();
|
||||
std::string tmp = node->getString();
|
||||
switch (attribute) {
|
||||
case OTBM_ATTR_DESCRIPTION:
|
||||
setDescription(tmp);
|
||||
break;
|
||||
case OTBM_ATTR_SPAWN_FILE:
|
||||
setSpawnFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
|
||||
break;
|
||||
case OTBM_ATTR_HOUSE_FILE:
|
||||
setHouseFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
|
||||
break;
|
||||
default:
|
||||
stdext::throw_exception(stdext::format("Invalid attribute '%d'", (int)attribute));
|
||||
}
|
||||
}
|
||||
|
||||
for(const BinaryTreePtr &nodeMapData : node->getChildren()) {
|
||||
uint8 mapDataType = nodeMapData->getU8();
|
||||
if(mapDataType == OTBM_TILE_AREA) {
|
||||
Position basePos = nodeMapData->getPosition();
|
||||
|
||||
for(const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) {
|
||||
uint8 type = nodeTile->getU8();
|
||||
if(type != OTBM_TILE && type != OTBM_HOUSETILE)
|
||||
stdext::throw_exception(stdext::format("invalid node tile type %d", (int)type));
|
||||
|
||||
HousePtr house = nullptr;
|
||||
uint32 flags = TILESTATE_NONE;
|
||||
Position pos = basePos + nodeTile->getPoint();
|
||||
|
||||
if(type == OTBM_HOUSETILE) {
|
||||
uint32 hId = nodeTile->getU32();
|
||||
TilePtr tile = getOrCreateTile(pos);
|
||||
if(!(house = m_houses.getHouse(hId))) {
|
||||
house = HousePtr(new House(hId));
|
||||
m_houses.addHouse(house);
|
||||
}
|
||||
house->setTile(tile);
|
||||
}
|
||||
|
||||
while(nodeTile->canRead()) {
|
||||
uint8 tileAttr = nodeTile->getU8();
|
||||
switch (tileAttr) {
|
||||
case OTBM_ATTR_TILE_FLAGS: {
|
||||
uint32 _flags = nodeTile->getU32();
|
||||
if((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE)
|
||||
flags |= TILESTATE_PROTECTIONZONE;
|
||||
else if((_flags & TILESTATE_OPTIONALZONE) == TILESTATE_OPTIONALZONE)
|
||||
flags |= TILESTATE_OPTIONALZONE;
|
||||
else if((_flags & TILESTATE_HARDCOREZONE) == TILESTATE_HARDCOREZONE)
|
||||
flags |= TILESTATE_HARDCOREZONE;
|
||||
|
||||
if((_flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT)
|
||||
flags |= TILESTATE_NOLOGOUT;
|
||||
|
||||
if((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH)
|
||||
flags |= TILESTATE_REFRESH;
|
||||
|
||||
break;
|
||||
}
|
||||
case OTBM_ATTR_ITEM: {
|
||||
addThing(Item::createFromOtb(nodeTile->getU16()), pos);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %s", (int)tileAttr, stdext::to_string(pos)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const BinaryTreePtr &nodeItem : nodeTile->getChildren()) {
|
||||
if(nodeItem->getU8() != OTBM_ITEM)
|
||||
stdext::throw_exception("invalid item node");
|
||||
|
||||
ItemPtr item = Item::createFromOtb(nodeItem->getU16());
|
||||
item->unserializeItem(nodeItem);
|
||||
|
||||
if(item->isContainer()) {
|
||||
for(const BinaryTreePtr& containerItem : nodeItem->getChildren()) {
|
||||
if(containerItem->getU8() != OTBM_ITEM)
|
||||
stdext::throw_exception("invalid container item node");
|
||||
|
||||
ItemPtr cItem = Item::createFromOtb(containerItem->getU16());
|
||||
cItem->unserializeItem(containerItem);
|
||||
//item->addContainerItem(cItem);
|
||||
}
|
||||
}
|
||||
|
||||
if(house && item->isMoveable()) {
|
||||
g_logger.warning(stdext::format("Movable item found in house: %d at pos %s - escaping...", item->getId(), stdext::to_string(pos)));
|
||||
item.reset();
|
||||
}
|
||||
|
||||
addThing(item, pos);
|
||||
}
|
||||
|
||||
if(const TilePtr& tile = getTile(pos))
|
||||
tile->setFlags((tileflags_t)flags);
|
||||
}
|
||||
} else if(mapDataType == OTBM_TOWNS) {
|
||||
TownPtr town = nullptr;
|
||||
for(const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) {
|
||||
if(nodeTown->getU8() != OTBM_TOWN)
|
||||
stdext::throw_exception("invalid town node.");
|
||||
|
||||
uint32 townId = nodeTown->getU32();
|
||||
std::string townName = nodeTown->getString();
|
||||
Position townCoords = nodeTown->getPosition();
|
||||
if(!(town = m_towns.getTown(townId))) {
|
||||
town = TownPtr(new Town(townId, townName, townCoords));
|
||||
m_towns.addTown(town);
|
||||
}
|
||||
}
|
||||
} else if(mapDataType == OTBM_WAYPOINTS && headerVersion > 1) {
|
||||
for(const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) {
|
||||
if(nodeWaypoint->getU8() != OTBM_WAYPOINT)
|
||||
stdext::throw_exception("invalid waypoint node.");
|
||||
|
||||
std::string name = nodeWaypoint->getString();
|
||||
Position waypointPos = nodeWaypoint->getPosition();
|
||||
if(waypointPos.isValid() && !name.empty() && m_waypoints.find(waypointPos) == m_waypoints.end())
|
||||
m_waypoints.insert(std::make_pair(waypointPos, name));
|
||||
}
|
||||
} else
|
||||
stdext::throw_exception(stdext::format("Unknown map data node %d", (int)mapDataType));
|
||||
}
|
||||
|
||||
g_logger.debug("OTBM read successfully.");
|
||||
fin->close();
|
||||
|
||||
loadSpawns(getSpawnFile());
|
||||
m_houses.load(getHouseFile());
|
||||
}
|
||||
|
||||
void Map::saveOtbm(const std::string &fileName)
|
||||
{
|
||||
#if 0
|
||||
/// FIXME: Untested code
|
||||
FileStreamPtr fin = g_resources.appendFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));
|
||||
|
||||
std::string dir;
|
||||
if(fileName.find_last_of('/') == std::string::npos)
|
||||
dir = g_resources.getWorkDir();
|
||||
else
|
||||
dir = fileName.substr(0, fileName.find_last_of('/'));
|
||||
|
||||
uint32 version = 0;
|
||||
/// Support old versions (< 810 or 860 IIRC)
|
||||
/// TODO: Use constants?
|
||||
if(g_things.getOtbMajorVersion() < 10)
|
||||
version = 1;
|
||||
else
|
||||
version = 2;
|
||||
|
||||
/// Usually when a map has empty house/spawn file it means the map is new.
|
||||
/// TODO: Ask the user for a map name instead of those ugly uses of substr
|
||||
std::string houseFile = getHouseFile(), spawnFile = getSpawnFile();
|
||||
if(houseFile.empty() && version > 1)
|
||||
houseFile = fileName.substr(fileName.find_last_of('/')) + "-houses.xml";
|
||||
if(spawnFile.empty())
|
||||
spawnFile = fileName.substr(fileName.find_last_of('/')) + "-spawns.xml";
|
||||
|
||||
#if 0
|
||||
if(version > 1)
|
||||
m_houses->save(dir + "/" + houseFile);
|
||||
|
||||
saveSpawns(dir + "/" + spawnFile);
|
||||
#endif
|
||||
|
||||
time_t start = time(0);
|
||||
fin->addU32(0); // file version
|
||||
BinaryTreePtr root = fin->makeTree();
|
||||
{
|
||||
root->writeU32(version);
|
||||
|
||||
Size mapSize = getSize();
|
||||
root->writeU16(mapSize.width());
|
||||
root->writeU16(mapSize.height());
|
||||
|
||||
root->writeU32(g_things.getOtbMajorVersion());
|
||||
root->writeU32(g_things.getOtbMinorVersion());
|
||||
|
||||
BinaryTreePtr mapData = root->makeChild(OTBM_MAP_DATA);
|
||||
{
|
||||
// own description.
|
||||
for(const auto& desc : getDescriptions()) {
|
||||
mapData->writeU8(OTBM_ATTR_DESCRIPTION);
|
||||
mapData->writeString(desc);
|
||||
}
|
||||
|
||||
// special one
|
||||
mapData->writeU8(OTBM_ATTR_DESCRIPTION);
|
||||
mapData->writeString(stdext::format("Saved with %s v%d", g_app.getName(), stdext::unsafe_cast<int>(g_app.getVersion())));
|
||||
|
||||
// spawn file.
|
||||
mapData->writeU8(OTBM_ATTR_SPAWN_FILE);
|
||||
mapData->writeString(spawnFile);
|
||||
|
||||
// house file.
|
||||
if(version > 1) {
|
||||
mapData->writeU8(OTBM_ATTR_HOUSE_FILE);
|
||||
mapData->writeString(houseFile);
|
||||
}
|
||||
|
||||
/// write tiles first
|
||||
BinaryTreePtr tileArea = mapData->makeChild(OTBM_TILE_AREA);
|
||||
Position base(-1, -1, -1);
|
||||
for(const auto& pair : m_tiles) {
|
||||
Position pos = pair.first;
|
||||
TilePtr tile = pair.second;
|
||||
|
||||
/// base position
|
||||
if(pos.x < base.x || pos.x >= base.x + 256 || pos.y < base.y|| pos.y >= base.y + 256 ||
|
||||
pos.z != base.z) {
|
||||
tileArea->writePos(base = pos & 0xFF00);
|
||||
}
|
||||
|
||||
BinaryTreePtr tileNode(nullptr);
|
||||
uint32 flags = tile->getFlags();
|
||||
if((flags & TILESTATE_HOUSE) == TILESTATE_HOUSE)
|
||||
tileNode = tileArea->makeChild(OTBM_HOUSETILE);
|
||||
else
|
||||
tileNode = tileArea->makeChild(OTBM_TILE);
|
||||
|
||||
tileNode->writePoint(Point(pos.x, pos.y));
|
||||
// if(tileNode->getType() == OTBM_HOUSETILE)
|
||||
// tileNode->writeU32(tile->getHouseId());
|
||||
|
||||
/// Tile flags
|
||||
if(flags != 0) {
|
||||
tileNode->writeU8(OTBM_ATTR_TILE_FLAGS);
|
||||
tileNode->writeU32(flags);
|
||||
}
|
||||
|
||||
/// start writing tile items
|
||||
for(const ItemPtr& item : tile->getItems()) {
|
||||
BinaryTreePtr itemNode = tileNode->makeChild(OTBM_ATTR_ITEM);
|
||||
item->serializeItem(itemNode);
|
||||
}
|
||||
}
|
||||
|
||||
/// write towns
|
||||
BinaryTreePtr townNode = mapData->makeChild(OTBM_TOWNS);
|
||||
for(const TownPtr& town : m_towns.getTowns()) {
|
||||
BinaryTreePtr newTown = townNode->makeChild(OTBM_TOWN);
|
||||
{
|
||||
newTown->writeU32(town->getId());
|
||||
newTown->writeString(town->getName());
|
||||
newTown->writePos(town->getPos());
|
||||
}
|
||||
}
|
||||
|
||||
/// write waypoints
|
||||
if(version > 1) {
|
||||
BinaryTreePtr waypointNode = mapData->makeChild(OTBM_WAYPOINTS);
|
||||
for(const auto& it : m_waypoints) {
|
||||
BinaryTreePtr newWaypoint = waypointNode->makeChild(OTBM_WAYPOINT);
|
||||
{
|
||||
newWaypoint->writeString(it.second);
|
||||
newWaypoint->writePos(it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root->writeToFile();
|
||||
g_logger.debug(stdext::format("OTBM saving took %ld", time(0) - start));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Map::loadSpawns(const std::string &fileName)
|
||||
{
|
||||
if(!m_creatures.isLoaded())
|
||||
stdext::throw_exception("cannot load spawns; monsters/nps aren't loaded.");
|
||||
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.loadFile(fileName).c_str());
|
||||
if(doc.Error())
|
||||
stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc()));
|
||||
|
||||
TiXmlElement* root = doc.FirstChildElement();
|
||||
if(!root || root->ValueStr() != "spawns")
|
||||
stdext::throw_exception("malformed spawns file");
|
||||
|
||||
CreatureTypePtr cType(nullptr);
|
||||
for(TiXmlElement* node = root->FirstChildElement(); node; node = node->NextSiblingElement()) {
|
||||
if(node->ValueTStr() != "spawn")
|
||||
stdext::throw_exception("invalid spawn node");
|
||||
|
||||
Position centerPos = node->readPos("center");
|
||||
for(TiXmlElement* cNode = node->FirstChildElement(); cNode; cNode = cNode->NextSiblingElement()) {
|
||||
if(cNode->ValueStr() != "monster" && cNode->ValueStr() != "npc")
|
||||
stdext::throw_exception(stdext::format("invalid spawn-subnode %s", cNode->ValueStr()));
|
||||
|
||||
std::string cName = stdext::trim(stdext::tolower(cNode->Attribute("name")));
|
||||
if (!(cType = m_creatures.getCreature(cName)))
|
||||
continue;
|
||||
|
||||
cType->setSpawnTime(cNode->readType<int>("spawntime"));
|
||||
CreaturePtr creature(new Creature);
|
||||
creature->setOutfit(cType->getOutfit());
|
||||
creature->setName(cType->getName());
|
||||
|
||||
addThing(creature, centerPos + cNode->readPoint());
|
||||
}
|
||||
}
|
||||
|
||||
doc.Clear();
|
||||
}
|
||||
|
||||
bool Map::loadOtcm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.openFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception("unable to open file");
|
||||
|
||||
stdext::timer loadTimer;
|
||||
fin->cache();
|
||||
|
||||
uint32 signature = fin->getU32();
|
||||
if(signature != OTCM_SIGNATURE)
|
||||
stdext::throw_exception("invalid otcm file");
|
||||
|
||||
uint16 start = fin->getU16();
|
||||
uint16 version = fin->getU16();
|
||||
fin->getU32(); // flags
|
||||
|
||||
switch(version) {
|
||||
case 1: {
|
||||
fin->getString(); // description
|
||||
uint32 datSignature = fin->getU32();
|
||||
fin->getU16(); // protocol version
|
||||
fin->getString(); // world name
|
||||
|
||||
if(datSignature != g_things.getDatSignature())
|
||||
g_logger.warning("otcm map loaded was created with a different dat signature");
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
stdext::throw_exception("otcm version not supported");
|
||||
}
|
||||
|
||||
fin->seek(start);
|
||||
|
||||
while(true) {
|
||||
Position pos;
|
||||
|
||||
pos.x = fin->getU16();
|
||||
pos.y = fin->getU16();
|
||||
pos.z = fin->getU8();
|
||||
|
||||
// end of file
|
||||
if(!pos.isValid())
|
||||
break;
|
||||
|
||||
const TilePtr& tile = g_map.createTile(pos);
|
||||
|
||||
int stackPos = 0;
|
||||
while(true) {
|
||||
int id = fin->getU16();
|
||||
|
||||
// end of tile
|
||||
if(id == 0xFFFF)
|
||||
break;
|
||||
|
||||
int countOrSubType = fin->getU8();
|
||||
|
||||
ItemPtr item = Item::create(id);
|
||||
item->setCountOrSubType(countOrSubType);
|
||||
|
||||
if(item->isValid())
|
||||
tile->addThing(item, stackPos++);
|
||||
}
|
||||
}
|
||||
|
||||
fin->close();
|
||||
|
||||
g_logger.debug(stdext::format("Otcm load time: %.2f seconds", loadTimer.elapsed_seconds()));
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to load OTCM map: %s", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Map::saveOtcm(const std::string& fileName)
|
||||
{
|
||||
#if 0
|
||||
try {
|
||||
g_clock.update();
|
||||
|
||||
FileStreamPtr fin = g_resources.createFile(fileName);
|
||||
fin->cache();
|
||||
|
||||
//TODO: compression flag with zlib
|
||||
uint32 flags = 0;
|
||||
|
||||
// header
|
||||
fin->addU32(OTCM_SIGNATURE);
|
||||
fin->addU16(0); // data start, will be overwritten later
|
||||
fin->addU16(OTCM_VERSION);
|
||||
fin->addU32(flags);
|
||||
|
||||
// version 1 header
|
||||
fin->addString("OTCM 1.0"); // map description
|
||||
fin->addU32(g_things.getDatSignature());
|
||||
fin->addU16(g_game.getClientVersion());
|
||||
fin->addString(g_game.getWorldName());
|
||||
|
||||
// go back and rewrite where the map data starts
|
||||
uint32 start = fin->tell();
|
||||
fin->seek(4);
|
||||
fin->addU16(start);
|
||||
fin->seek(start);
|
||||
|
||||
for(auto& pair : m_tiles) {
|
||||
const TilePtr& tile = pair.second;
|
||||
if(!tile || tile->isEmpty())
|
||||
continue;
|
||||
|
||||
Position pos = pair.first;
|
||||
fin->addU16(pos.x);
|
||||
fin->addU16(pos.y);
|
||||
fin->addU8(pos.z);
|
||||
|
||||
const auto& list = tile->getThings();
|
||||
auto first = std::find_if(list.begin(), list.end(), [](const ThingPtr& thing) { return thing->isItem(); });
|
||||
for(auto it = first, end = list.end(); it != end; ++it) {
|
||||
const ThingPtr& thing = *it;
|
||||
if(thing->isItem()) {
|
||||
ItemPtr item = thing->self_cast<Item>();
|
||||
fin->addU16(item->getId());
|
||||
fin->addU8(item->getCountOrSubType());
|
||||
}
|
||||
}
|
||||
|
||||
// end of tile
|
||||
fin->addU16(0xFFFF);
|
||||
}
|
||||
|
||||
// end of file
|
||||
Position invalidPos;
|
||||
fin->addU16(invalidPos.x);
|
||||
fin->addU16(invalidPos.y);
|
||||
fin->addU8(invalidPos.z);
|
||||
|
||||
fin->flush();
|
||||
fin->close();
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to save OTCM map: %s", e.what()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Map::clean()
|
||||
{
|
||||
cleanDynamicThings();
|
||||
|
@ -617,11 +106,11 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
|
|||
if(thing->isItem() || thing->isCreature() || thing->isEffect()) {
|
||||
tile->addThing(thing, stackPos);
|
||||
} else if(thing->isMissile()) {
|
||||
m_floorMissiles[pos.z].push_back(thing->self_cast<Missile>());
|
||||
m_floorMissiles[pos.z].push_back(thing->static_self_cast<Missile>());
|
||||
} else if(thing->isAnimatedText()) {
|
||||
m_animatedTexts.push_back(thing->self_cast<AnimatedText>());
|
||||
m_animatedTexts.push_back(thing->static_self_cast<AnimatedText>());
|
||||
} else if(thing->isStaticText()) {
|
||||
StaticTextPtr staticText = thing->self_cast<StaticText>();
|
||||
StaticTextPtr staticText = thing->static_self_cast<StaticText>();
|
||||
bool mustAdd = true;
|
||||
for(auto it = m_staticTexts.begin(), end = m_staticTexts.end(); it != end; ++it) {
|
||||
StaticTextPtr cStaticText = *it;
|
||||
|
@ -641,11 +130,13 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
|
|||
m_staticTexts.push_back(staticText);
|
||||
}
|
||||
|
||||
thing->startAnimation();
|
||||
if(!thing->isCreature())
|
||||
thing->onAppear();
|
||||
|
||||
thing->setPosition(pos);
|
||||
|
||||
if(thing->isCreature()) {
|
||||
CreaturePtr creature = thing->self_cast<Creature>();
|
||||
CreaturePtr creature = thing->static_self_cast<Creature>();
|
||||
if(oldPos != pos) {
|
||||
if(oldPos.isInRange(pos,1,1))
|
||||
g_game.processCreatureMove(creature, oldPos, pos);
|
||||
|
@ -672,7 +163,7 @@ bool Map::removeThing(const ThingPtr& thing)
|
|||
notificateTileUpdateToMapViews(thing->getPosition());
|
||||
|
||||
if(thing->isMissile()) {
|
||||
MissilePtr missile = thing->self_cast<Missile>();
|
||||
MissilePtr missile = thing->static_self_cast<Missile>();
|
||||
int z = missile->getPosition().z;
|
||||
auto it = std::find(m_floorMissiles[z].begin(), m_floorMissiles[z].end(), missile);
|
||||
if(it != m_floorMissiles[z].end()) {
|
||||
|
@ -680,14 +171,14 @@ bool Map::removeThing(const ThingPtr& thing)
|
|||
return true;
|
||||
}
|
||||
} else if(thing->isAnimatedText()) {
|
||||
AnimatedTextPtr animatedText = thing->self_cast<AnimatedText>();
|
||||
AnimatedTextPtr animatedText = thing->static_self_cast<AnimatedText>();
|
||||
auto it = std::find(m_animatedTexts.begin(), m_animatedTexts.end(), animatedText);
|
||||
if(it != m_animatedTexts.end()) {
|
||||
m_animatedTexts.erase(it);
|
||||
return true;
|
||||
}
|
||||
} else if(thing->isStaticText()) {
|
||||
StaticTextPtr staticText = thing->self_cast<StaticText>();
|
||||
StaticTextPtr staticText = thing->static_self_cast<StaticText>();
|
||||
auto it = std::find(m_staticTexts.begin(), m_staticTexts.end(), staticText);
|
||||
if(it != m_staticTexts.end()) {
|
||||
m_staticTexts.erase(it);
|
||||
|
|
|
@ -267,7 +267,7 @@ private:
|
|||
Position m_centralPosition;
|
||||
Rect m_tilesRect;
|
||||
|
||||
stdext::attrib_storage m_attribs;
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
Houses m_houses;
|
||||
Towns m_towns;
|
||||
Creatures m_creatures;
|
||||
|
|
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/core/binarytree.h>
|
||||
#include <framework/xml/tinyxml.h>
|
||||
|
||||
void Map::loadOtbm(const std::string& fileName)
|
||||
{
|
||||
FileStreamPtr fin = g_resources.openFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("Unable to load map '%s'", fileName));
|
||||
|
||||
fin->cache();
|
||||
if(!g_things.isOtbLoaded())
|
||||
stdext::throw_exception("OTB isn't loaded yet to load a map.");
|
||||
|
||||
if(fin->getU32())
|
||||
stdext::throw_exception("Unknown file version detected");
|
||||
|
||||
BinaryTreePtr root = fin->getBinaryTree();
|
||||
if(root->getU8())
|
||||
stdext::throw_exception("could not read root property!");
|
||||
|
||||
uint32 headerVersion = root->getU32();
|
||||
if(!headerVersion || headerVersion > 3)
|
||||
stdext::throw_exception(stdext::format("Unknown OTBM version detected: %u.", headerVersion));
|
||||
|
||||
setWidth(root->getU16());
|
||||
setHeight(root->getU16());
|
||||
|
||||
uint32 headerMajorItems = root->getU8();
|
||||
if(headerMajorItems < 3) {
|
||||
stdext::throw_exception(stdext::format("This map needs to be upgraded. read %d what it's supposed to be: %u",
|
||||
headerMajorItems, g_things.getOtbMajorVersion()));
|
||||
}
|
||||
|
||||
if(headerMajorItems > g_things.getOtbMajorVersion()) {
|
||||
stdext::throw_exception(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d",
|
||||
headerMajorItems, g_things.getOtbMajorVersion()));
|
||||
}
|
||||
|
||||
root->skip(3);
|
||||
uint32 headerMinorItems = root->getU32();
|
||||
if(headerMinorItems > g_things.getOtbMinorVersion()) {
|
||||
g_logger.warning(stdext::format("This map needs an updated OTB. read %d what it's supposed to be: %d or less",
|
||||
headerMinorItems, g_things.getOtbMinorVersion()));
|
||||
}
|
||||
|
||||
BinaryTreePtr node = root->getChildren()[0];
|
||||
if(node->getU8() != OTBM_MAP_DATA)
|
||||
stdext::throw_exception("Could not read root data node");
|
||||
|
||||
while (node->canRead()) {
|
||||
uint8 attribute = node->getU8();
|
||||
std::string tmp = node->getString();
|
||||
switch (attribute) {
|
||||
case OTBM_ATTR_DESCRIPTION:
|
||||
setDescription(tmp);
|
||||
break;
|
||||
case OTBM_ATTR_SPAWN_FILE:
|
||||
setSpawnFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
|
||||
break;
|
||||
case OTBM_ATTR_HOUSE_FILE:
|
||||
setHouseFile(fileName.substr(0, fileName.rfind('/') + 1) + tmp);
|
||||
break;
|
||||
default:
|
||||
stdext::throw_exception(stdext::format("Invalid attribute '%d'", (int)attribute));
|
||||
}
|
||||
}
|
||||
|
||||
for(const BinaryTreePtr &nodeMapData : node->getChildren()) {
|
||||
uint8 mapDataType = nodeMapData->getU8();
|
||||
if(mapDataType == OTBM_TILE_AREA) {
|
||||
Position basePos = nodeMapData->getPosition();
|
||||
|
||||
for(const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) {
|
||||
uint8 type = nodeTile->getU8();
|
||||
if(type != OTBM_TILE && type != OTBM_HOUSETILE)
|
||||
stdext::throw_exception(stdext::format("invalid node tile type %d", (int)type));
|
||||
|
||||
HousePtr house = nullptr;
|
||||
uint32 flags = TILESTATE_NONE;
|
||||
Position pos = basePos + nodeTile->getPoint();
|
||||
|
||||
if(type == OTBM_HOUSETILE) {
|
||||
uint32 hId = nodeTile->getU32();
|
||||
TilePtr tile = getOrCreateTile(pos);
|
||||
if(!(house = m_houses.getHouse(hId))) {
|
||||
house = HousePtr(new House(hId));
|
||||
m_houses.addHouse(house);
|
||||
}
|
||||
house->setTile(tile);
|
||||
}
|
||||
|
||||
while(nodeTile->canRead()) {
|
||||
uint8 tileAttr = nodeTile->getU8();
|
||||
switch (tileAttr) {
|
||||
case OTBM_ATTR_TILE_FLAGS: {
|
||||
uint32 _flags = nodeTile->getU32();
|
||||
if((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE)
|
||||
flags |= TILESTATE_PROTECTIONZONE;
|
||||
else if((_flags & TILESTATE_OPTIONALZONE) == TILESTATE_OPTIONALZONE)
|
||||
flags |= TILESTATE_OPTIONALZONE;
|
||||
else if((_flags & TILESTATE_HARDCOREZONE) == TILESTATE_HARDCOREZONE)
|
||||
flags |= TILESTATE_HARDCOREZONE;
|
||||
|
||||
if((_flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT)
|
||||
flags |= TILESTATE_NOLOGOUT;
|
||||
|
||||
if((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH)
|
||||
flags |= TILESTATE_REFRESH;
|
||||
|
||||
break;
|
||||
}
|
||||
case OTBM_ATTR_ITEM: {
|
||||
addThing(Item::createFromOtb(nodeTile->getU16()), pos);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %s", (int)tileAttr, stdext::to_string(pos)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const BinaryTreePtr &nodeItem : nodeTile->getChildren()) {
|
||||
if(nodeItem->getU8() != OTBM_ITEM)
|
||||
stdext::throw_exception("invalid item node");
|
||||
|
||||
ItemPtr item = Item::createFromOtb(nodeItem->getU16());
|
||||
item->unserializeItem(nodeItem);
|
||||
|
||||
if(item->isContainer()) {
|
||||
for(const BinaryTreePtr& containerItem : nodeItem->getChildren()) {
|
||||
if(containerItem->getU8() != OTBM_ITEM)
|
||||
stdext::throw_exception("invalid container item node");
|
||||
|
||||
ItemPtr cItem = Item::createFromOtb(containerItem->getU16());
|
||||
cItem->unserializeItem(containerItem);
|
||||
//item->addContainerItem(cItem);
|
||||
}
|
||||
}
|
||||
|
||||
if(house && item->isMoveable()) {
|
||||
g_logger.warning(stdext::format("Movable item found in house: %d at pos %s - escaping...", item->getId(), stdext::to_string(pos)));
|
||||
item.reset();
|
||||
}
|
||||
|
||||
addThing(item, pos);
|
||||
}
|
||||
|
||||
if(const TilePtr& tile = getTile(pos))
|
||||
tile->setFlags((tileflags_t)flags);
|
||||
}
|
||||
} else if(mapDataType == OTBM_TOWNS) {
|
||||
TownPtr town = nullptr;
|
||||
for(const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) {
|
||||
if(nodeTown->getU8() != OTBM_TOWN)
|
||||
stdext::throw_exception("invalid town node.");
|
||||
|
||||
uint32 townId = nodeTown->getU32();
|
||||
std::string townName = nodeTown->getString();
|
||||
Position townCoords = nodeTown->getPosition();
|
||||
if(!(town = m_towns.getTown(townId))) {
|
||||
town = TownPtr(new Town(townId, townName, townCoords));
|
||||
m_towns.addTown(town);
|
||||
}
|
||||
}
|
||||
} else if(mapDataType == OTBM_WAYPOINTS && headerVersion > 1) {
|
||||
for(const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) {
|
||||
if(nodeWaypoint->getU8() != OTBM_WAYPOINT)
|
||||
stdext::throw_exception("invalid waypoint node.");
|
||||
|
||||
std::string name = nodeWaypoint->getString();
|
||||
Position waypointPos = nodeWaypoint->getPosition();
|
||||
if(waypointPos.isValid() && !name.empty() && m_waypoints.find(waypointPos) == m_waypoints.end())
|
||||
m_waypoints.insert(std::make_pair(waypointPos, name));
|
||||
}
|
||||
} else
|
||||
stdext::throw_exception(stdext::format("Unknown map data node %d", (int)mapDataType));
|
||||
}
|
||||
|
||||
g_logger.debug("OTBM read successfully.");
|
||||
fin->close();
|
||||
|
||||
loadSpawns(getSpawnFile());
|
||||
m_houses.load(getHouseFile());
|
||||
}
|
||||
|
||||
void Map::saveOtbm(const std::string &fileName)
|
||||
{
|
||||
#if 0
|
||||
/// FIXME: Untested code
|
||||
FileStreamPtr fin = g_resources.appendFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));
|
||||
|
||||
std::string dir;
|
||||
if(fileName.find_last_of('/') == std::string::npos)
|
||||
dir = g_resources.getWorkDir();
|
||||
else
|
||||
dir = fileName.substr(0, fileName.find_last_of('/'));
|
||||
|
||||
uint32 version = 0;
|
||||
/// Support old versions (< 810 or 860 IIRC)
|
||||
/// TODO: Use constants?
|
||||
if(g_things.getOtbMajorVersion() < 10)
|
||||
version = 1;
|
||||
else
|
||||
version = 2;
|
||||
|
||||
/// Usually when a map has empty house/spawn file it means the map is new.
|
||||
/// TODO: Ask the user for a map name instead of those ugly uses of substr
|
||||
std::string houseFile = getHouseFile(), spawnFile = getSpawnFile();
|
||||
if(houseFile.empty() && version > 1)
|
||||
houseFile = fileName.substr(fileName.find_last_of('/')) + "-houses.xml";
|
||||
if(spawnFile.empty())
|
||||
spawnFile = fileName.substr(fileName.find_last_of('/')) + "-spawns.xml";
|
||||
|
||||
#if 0
|
||||
if(version > 1)
|
||||
m_houses->save(dir + "/" + houseFile);
|
||||
|
||||
saveSpawns(dir + "/" + spawnFile);
|
||||
#endif
|
||||
|
||||
time_t start = time(0);
|
||||
fin->addU32(0); // file version
|
||||
BinaryTreePtr root = fin->makeTree();
|
||||
{
|
||||
root->writeU32(version);
|
||||
|
||||
Size mapSize = getSize();
|
||||
root->writeU16(mapSize.width());
|
||||
root->writeU16(mapSize.height());
|
||||
|
||||
root->writeU32(g_things.getOtbMajorVersion());
|
||||
root->writeU32(g_things.getOtbMinorVersion());
|
||||
|
||||
BinaryTreePtr mapData = root->makeChild(OTBM_MAP_DATA);
|
||||
{
|
||||
// own description.
|
||||
for(const auto& desc : getDescriptions()) {
|
||||
mapData->writeU8(OTBM_ATTR_DESCRIPTION);
|
||||
mapData->writeString(desc);
|
||||
}
|
||||
|
||||
// special one
|
||||
mapData->writeU8(OTBM_ATTR_DESCRIPTION);
|
||||
mapData->writeString(stdext::format("Saved with %s v%d", g_app.getName(), stdext::unsafe_cast<int>(g_app.getVersion())));
|
||||
|
||||
// spawn file.
|
||||
mapData->writeU8(OTBM_ATTR_SPAWN_FILE);
|
||||
mapData->writeString(spawnFile);
|
||||
|
||||
// house file.
|
||||
if(version > 1) {
|
||||
mapData->writeU8(OTBM_ATTR_HOUSE_FILE);
|
||||
mapData->writeString(houseFile);
|
||||
}
|
||||
|
||||
/// write tiles first
|
||||
BinaryTreePtr tileArea = mapData->makeChild(OTBM_TILE_AREA);
|
||||
Position base(-1, -1, -1);
|
||||
for(const auto& pair : m_tiles) {
|
||||
Position pos = pair.first;
|
||||
TilePtr tile = pair.second;
|
||||
|
||||
/// base position
|
||||
if(pos.x < base.x || pos.x >= base.x + 256 || pos.y < base.y|| pos.y >= base.y + 256 ||
|
||||
pos.z != base.z) {
|
||||
tileArea->writePos(base = pos & 0xFF00);
|
||||
}
|
||||
|
||||
BinaryTreePtr tileNode(nullptr);
|
||||
uint32 flags = tile->getFlags();
|
||||
if((flags & TILESTATE_HOUSE) == TILESTATE_HOUSE)
|
||||
tileNode = tileArea->makeChild(OTBM_HOUSETILE);
|
||||
else
|
||||
tileNode = tileArea->makeChild(OTBM_TILE);
|
||||
|
||||
tileNode->writePoint(Point(pos.x, pos.y));
|
||||
// if(tileNode->getType() == OTBM_HOUSETILE)
|
||||
// tileNode->writeU32(tile->getHouseId());
|
||||
|
||||
/// Tile flags
|
||||
if(flags != 0) {
|
||||
tileNode->writeU8(OTBM_ATTR_TILE_FLAGS);
|
||||
tileNode->writeU32(flags);
|
||||
}
|
||||
|
||||
/// start writing tile items
|
||||
for(const ItemPtr& item : tile->getItems()) {
|
||||
BinaryTreePtr itemNode = tileNode->makeChild(OTBM_ATTR_ITEM);
|
||||
item->serializeItem(itemNode);
|
||||
}
|
||||
}
|
||||
|
||||
/// write towns
|
||||
BinaryTreePtr townNode = mapData->makeChild(OTBM_TOWNS);
|
||||
for(const TownPtr& town : m_towns.getTowns()) {
|
||||
BinaryTreePtr newTown = townNode->makeChild(OTBM_TOWN);
|
||||
{
|
||||
newTown->writeU32(town->getId());
|
||||
newTown->writeString(town->getName());
|
||||
newTown->writePos(town->getPos());
|
||||
}
|
||||
}
|
||||
|
||||
/// write waypoints
|
||||
if(version > 1) {
|
||||
BinaryTreePtr waypointNode = mapData->makeChild(OTBM_WAYPOINTS);
|
||||
for(const auto& it : m_waypoints) {
|
||||
BinaryTreePtr newWaypoint = waypointNode->makeChild(OTBM_WAYPOINT);
|
||||
{
|
||||
newWaypoint->writeString(it.second);
|
||||
newWaypoint->writePos(it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root->writeToFile();
|
||||
g_logger.debug(stdext::format("OTBM saving took %ld", time(0) - start));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Map::loadSpawns(const std::string &fileName)
|
||||
{
|
||||
if(!m_creatures.isLoaded())
|
||||
stdext::throw_exception("cannot load spawns; monsters/nps aren't loaded.");
|
||||
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.loadFile(fileName).c_str());
|
||||
if(doc.Error())
|
||||
stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc()));
|
||||
|
||||
TiXmlElement* root = doc.FirstChildElement();
|
||||
if(!root || root->ValueStr() != "spawns")
|
||||
stdext::throw_exception("malformed spawns file");
|
||||
|
||||
CreatureTypePtr cType(nullptr);
|
||||
for(TiXmlElement* node = root->FirstChildElement(); node; node = node->NextSiblingElement()) {
|
||||
if(node->ValueTStr() != "spawn")
|
||||
stdext::throw_exception("invalid spawn node");
|
||||
|
||||
Position centerPos = node->readPos("center");
|
||||
for(TiXmlElement* cNode = node->FirstChildElement(); cNode; cNode = cNode->NextSiblingElement()) {
|
||||
if(cNode->ValueStr() != "monster" && cNode->ValueStr() != "npc")
|
||||
stdext::throw_exception(stdext::format("invalid spawn-subnode %s", cNode->ValueStr()));
|
||||
|
||||
std::string cName = cNode->Attribute("name");
|
||||
stdext::tolower(cName);
|
||||
stdext::trim(cName);
|
||||
|
||||
if (!(cType = m_creatures.getCreature(cName)))
|
||||
continue;
|
||||
|
||||
cType->setSpawnTime(cNode->readType<int>("spawntime"));
|
||||
CreaturePtr creature(new Creature);
|
||||
creature->setOutfit(cType->getOutfit());
|
||||
creature->setName(cType->getName());
|
||||
|
||||
addThing(creature, centerPos + cNode->readPoint());
|
||||
}
|
||||
}
|
||||
|
||||
doc.Clear();
|
||||
}
|
||||
|
||||
bool Map::loadOtcm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.openFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception("unable to open file");
|
||||
|
||||
stdext::timer loadTimer;
|
||||
fin->cache();
|
||||
|
||||
uint32 signature = fin->getU32();
|
||||
if(signature != OTCM_SIGNATURE)
|
||||
stdext::throw_exception("invalid otcm file");
|
||||
|
||||
uint16 start = fin->getU16();
|
||||
uint16 version = fin->getU16();
|
||||
fin->getU32(); // flags
|
||||
|
||||
switch(version) {
|
||||
case 1: {
|
||||
fin->getString(); // description
|
||||
uint32 datSignature = fin->getU32();
|
||||
fin->getU16(); // protocol version
|
||||
fin->getString(); // world name
|
||||
|
||||
if(datSignature != g_things.getDatSignature())
|
||||
g_logger.warning("otcm map loaded was created with a different dat signature");
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
stdext::throw_exception("otcm version not supported");
|
||||
}
|
||||
|
||||
fin->seek(start);
|
||||
|
||||
while(true) {
|
||||
Position pos;
|
||||
|
||||
pos.x = fin->getU16();
|
||||
pos.y = fin->getU16();
|
||||
pos.z = fin->getU8();
|
||||
|
||||
// end of file
|
||||
if(!pos.isValid())
|
||||
break;
|
||||
|
||||
const TilePtr& tile = g_map.createTile(pos);
|
||||
|
||||
int stackPos = 0;
|
||||
while(true) {
|
||||
int id = fin->getU16();
|
||||
|
||||
// end of tile
|
||||
if(id == 0xFFFF)
|
||||
break;
|
||||
|
||||
int countOrSubType = fin->getU8();
|
||||
|
||||
ItemPtr item = Item::create(id);
|
||||
item->setCountOrSubType(countOrSubType);
|
||||
|
||||
if(item->isValid())
|
||||
tile->addThing(item, stackPos++);
|
||||
}
|
||||
}
|
||||
|
||||
fin->close();
|
||||
|
||||
g_logger.debug(stdext::format("Otcm load time: %.2f seconds", loadTimer.elapsed_seconds()));
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to load OTCM map: %s", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Map::saveOtcm(const std::string& fileName)
|
||||
{
|
||||
#if 0
|
||||
try {
|
||||
g_clock.update();
|
||||
|
||||
FileStreamPtr fin = g_resources.createFile(fileName);
|
||||
fin->cache();
|
||||
|
||||
//TODO: compression flag with zlib
|
||||
uint32 flags = 0;
|
||||
|
||||
// header
|
||||
fin->addU32(OTCM_SIGNATURE);
|
||||
fin->addU16(0); // data start, will be overwritten later
|
||||
fin->addU16(OTCM_VERSION);
|
||||
fin->addU32(flags);
|
||||
|
||||
// version 1 header
|
||||
fin->addString("OTCM 1.0"); // map description
|
||||
fin->addU32(g_things.getDatSignature());
|
||||
fin->addU16(g_game.getClientVersion());
|
||||
fin->addString(g_game.getWorldName());
|
||||
|
||||
// go back and rewrite where the map data starts
|
||||
uint32 start = fin->tell();
|
||||
fin->seek(4);
|
||||
fin->addU16(start);
|
||||
fin->seek(start);
|
||||
|
||||
for(auto& pair : m_tiles) {
|
||||
const TilePtr& tile = pair.second;
|
||||
if(!tile || tile->isEmpty())
|
||||
continue;
|
||||
|
||||
Position pos = pair.first;
|
||||
fin->addU16(pos.x);
|
||||
fin->addU16(pos.y);
|
||||
fin->addU8(pos.z);
|
||||
|
||||
const auto& list = tile->getThings();
|
||||
auto first = std::find_if(list.begin(), list.end(), [](const ThingPtr& thing) { return thing->isItem(); });
|
||||
for(auto it = first, end = list.end(); it != end; ++it) {
|
||||
const ThingPtr& thing = *it;
|
||||
if(thing->isItem()) {
|
||||
ItemPtr item = thing->static_self_cast<Item>();
|
||||
fin->addU16(item->getId());
|
||||
fin->addU8(item->getCountOrSubType());
|
||||
}
|
||||
}
|
||||
|
||||
// end of tile
|
||||
fin->addU16(0xFFFF);
|
||||
}
|
||||
|
||||
// end of file
|
||||
Position invalidPos;
|
||||
fin->addU16(invalidPos.x);
|
||||
fin->addU16(invalidPos.y);
|
||||
fin->addU8(invalidPos.z);
|
||||
|
||||
fin->flush();
|
||||
fin->close();
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to save OTCM map: %s", e.what()));
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -103,7 +103,7 @@ public:
|
|||
// get tile
|
||||
TilePtr getTile(const Point& mousePos, const Rect& mapRect);
|
||||
|
||||
MapViewPtr asMapView() { return self_cast<MapView>(); }
|
||||
MapViewPtr asMapView() { return static_self_cast<MapView>(); }
|
||||
|
||||
private:
|
||||
int calcFirstVisibleFloor();
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
uint32 getId() { return m_id; }
|
||||
|
||||
MissilePtr asMissile() { return self_cast<Missile>(); }
|
||||
MissilePtr asMissile() { return static_self_cast<Missile>(); }
|
||||
bool isMissile() { return true; }
|
||||
|
||||
const ThingTypePtr& getThingType();
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
Player() { }
|
||||
virtual ~Player() { }
|
||||
|
||||
PlayerPtr asPlayer() { return self_cast<Player>(); }
|
||||
PlayerPtr asPlayer() { return static_self_cast<Player>(); }
|
||||
bool isPlayer() { return true; }
|
||||
};
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ public:
|
|||
return Otc::InvalidDirection;
|
||||
}
|
||||
|
||||
bool isMapPosition() const { return (x < 65535 && y < 65535 && z <= Otc::MAX_Z); }
|
||||
bool isValid() const { return !(x == 65535 && y == 65535 && z == 255); }
|
||||
float distance(const Position& pos) const { return sqrt(pow((pos.x - x), 2) + pow((pos.y - y), 2)); }
|
||||
int manhattanDistance(const Position& pos) const { return std::abs(pos.x - x) + std::abs(pos.y - y); }
|
||||
|
|
|
@ -499,7 +499,6 @@ void ProtocolGame::parseCreatureMove(const InputMessagePtr& msg)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
int stackPos = -2;
|
||||
// newer protocols stores creatures in reverse order
|
||||
if(!g_game.getClientVersion() >= 854)
|
||||
|
@ -507,6 +506,10 @@ void ProtocolGame::parseCreatureMove(const InputMessagePtr& msg)
|
|||
|
||||
g_map.removeThing(thing);
|
||||
g_map.addThing(thing, newPos, stackPos);
|
||||
|
||||
//CreaturePtr creature = thing->static_self_cast<Creature>();
|
||||
//Position oldPos = thing->getPosition();
|
||||
//creature->onMove(newPos, oldPos);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseOpenContainer(const InputMessagePtr& msg)
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
|
||||
bool addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text);
|
||||
|
||||
StaticTextPtr asStaticText() { return self_cast<StaticText>(); }
|
||||
StaticTextPtr asStaticText() { return static_self_cast<StaticText>(); }
|
||||
bool isStaticText() { return true; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -33,6 +33,13 @@ Thing::Thing() :
|
|||
{
|
||||
}
|
||||
|
||||
void Thing::setPosition(const Position& position)
|
||||
{
|
||||
Position oldPos = m_position;
|
||||
m_position = position;
|
||||
onPositionChange(position, oldPos);
|
||||
}
|
||||
|
||||
int Thing::getStackPriority()
|
||||
{
|
||||
if(isGround())
|
||||
|
@ -68,7 +75,7 @@ int Thing::getStackpos()
|
|||
if(m_position.x == 65535 && isItem()) // is inside a container
|
||||
return m_position.z;
|
||||
else if(const TilePtr& tile = getTile())
|
||||
return tile->getThingStackpos(self_cast<Thing>());
|
||||
return tile->getThingStackpos(static_self_cast<Thing>());
|
||||
else {
|
||||
g_logger.traceError("got a thing with invalid stackpos");
|
||||
return -1;
|
||||
|
|
|
@ -36,11 +36,10 @@ public:
|
|||
Thing();
|
||||
virtual ~Thing() { }
|
||||
|
||||
virtual void startAnimation() { }
|
||||
virtual void draw(const Point& dest, float scaleFactor, bool animate) { }
|
||||
|
||||
virtual void setId(uint32 id) { }
|
||||
void setPosition(const Position& position) { m_position = position; }
|
||||
void setPosition(const Position& position);
|
||||
|
||||
virtual uint32 getId() { return 0; }
|
||||
Position getPosition() { return m_position; }
|
||||
|
@ -119,8 +118,13 @@ public:
|
|||
bool isMarketable() { return rawGetThingType()->isMarketable(); }
|
||||
MarketData getMarketData() { return rawGetThingType()->getMarketData(); }
|
||||
|
||||
|
||||
protected:
|
||||
virtual void onPositionChange(const Position& newPos, const Position& oldPos) { }
|
||||
virtual void onAppear() { }
|
||||
virtual void onDisappear() { }
|
||||
|
||||
friend class Map;
|
||||
|
||||
Position m_position;
|
||||
uint16 m_datId;
|
||||
};
|
||||
|
|
|
@ -39,6 +39,7 @@ ThingType::ThingType()
|
|||
m_numPatternX = m_numPatternY = m_numPatternZ = 0;
|
||||
m_animationPhases = 0;
|
||||
m_layers = 0;
|
||||
m_elevation = 0;
|
||||
}
|
||||
|
||||
void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileStreamPtr& fin)
|
||||
|
@ -88,10 +89,14 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
|||
m_attribs.set(attr, market);
|
||||
break;
|
||||
}
|
||||
case ThingAttrElevation: {
|
||||
m_elevation = fin->getU16();
|
||||
m_attribs.set(attr, m_elevation);
|
||||
break;
|
||||
}
|
||||
case ThingAttrGround:
|
||||
case ThingAttrWritable:
|
||||
case ThingAttrWritableOnce:
|
||||
case ThingAttrElevation:
|
||||
case ThingAttrMinimapColor:
|
||||
case ThingAttrCloth:
|
||||
case ThingAttrLensHelp:
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
Point getDisplacement() { return m_displacement; }
|
||||
int getDisplacementX() { return getDisplacement().x; }
|
||||
int getDisplacementY() { return getDisplacement().y; }
|
||||
int getElevation() { return m_elevation; }
|
||||
|
||||
int getGroundSpeed() { return m_attribs.get<uint16>(ThingAttrGround); }
|
||||
int getMaxTextLength() { return m_attribs.has(ThingAttrWritableOnce) ? m_attribs.get<uint16>(ThingAttrWritableOnce) : m_attribs.get<uint16>(ThingAttrWritable); }
|
||||
|
@ -133,7 +134,6 @@ public:
|
|||
int getMinimapColor() { return m_attribs.get<uint16>(ThingAttrMinimapColor); }
|
||||
int getLensHelp() { return m_attribs.get<uint16>(ThingAttrLensHelp); }
|
||||
int getClothSlot() { return m_attribs.get<uint16>(ThingAttrCloth); }
|
||||
int getElevation() { return m_attribs.get<uint16>(ThingAttrElevation); }
|
||||
MarketData getMarketData() { return m_attribs.get<MarketData>(ThingAttrMarket); }
|
||||
bool isGround() { return m_attribs.has(ThingAttrGround); }
|
||||
bool isGroundBorder() { return m_attribs.has(ThingAttrGroundBorder); }
|
||||
|
@ -180,7 +180,7 @@ private:
|
|||
ThingCategory m_category;
|
||||
uint16 m_id;
|
||||
bool m_null;
|
||||
stdext::attrib_storage m_attribs;
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
|
||||
Size m_size;
|
||||
Point m_displacement;
|
||||
|
@ -188,6 +188,7 @@ private:
|
|||
int m_numPatternX, m_numPatternY, m_numPatternZ;
|
||||
int m_animationPhases;
|
||||
int m_layers;
|
||||
int m_elevation;
|
||||
|
||||
std::vector<int> m_spritesIndex;
|
||||
std::vector<TexturePtr> m_textures;
|
||||
|
|
|
@ -113,7 +113,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
|
|||
const ThingPtr& thing = *it;
|
||||
if(!thing->isCreature())
|
||||
continue;
|
||||
CreaturePtr creature = thing->self_cast<Creature>();
|
||||
CreaturePtr creature = thing->static_self_cast<Creature>();
|
||||
if(creature && (!creature->isWalking() || !animate))
|
||||
creature->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ void Tile::addThing(const ThingPtr& thing, int stackPos)
|
|||
return;
|
||||
|
||||
if(thing->isEffect()) {
|
||||
m_effects.push_back(thing->self_cast<Effect>());
|
||||
m_effects.push_back(thing->static_self_cast<Effect>());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ bool Tile::removeThing(ThingPtr thing)
|
|||
bool removed = false;
|
||||
|
||||
if(thing->isEffect()) {
|
||||
EffectPtr effect = thing->self_cast<Effect>();
|
||||
EffectPtr effect = thing->static_self_cast<Effect>();
|
||||
auto it = std::find(m_effects.begin(), m_effects.end(), effect);
|
||||
if(it != m_effects.end()) {
|
||||
m_effects.erase(it);
|
||||
|
@ -267,7 +267,7 @@ std::vector<ItemPtr> Tile::getItems()
|
|||
for(const ThingPtr& thing : m_things) {
|
||||
if(!thing->isItem())
|
||||
continue;
|
||||
ItemPtr item = thing->self_cast<Item>();
|
||||
ItemPtr item = thing->static_self_cast<Item>();
|
||||
items.push_back(item);
|
||||
}
|
||||
return items;
|
||||
|
@ -278,7 +278,7 @@ std::vector<CreaturePtr> Tile::getCreatures()
|
|||
std::vector<CreaturePtr> creatures;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isCreature())
|
||||
creatures.push_back(thing->self_cast<Creature>());
|
||||
creatures.push_back(thing->static_self_cast<Creature>());
|
||||
}
|
||||
return creatures;
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ ItemPtr Tile::getGround()
|
|||
if(!firstObject)
|
||||
return nullptr;
|
||||
if(firstObject->isGround() && firstObject->isItem())
|
||||
return firstObject->self_cast<Item>();
|
||||
return firstObject->static_self_cast<Item>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -348,9 +348,9 @@ CreaturePtr Tile::getTopCreature()
|
|||
for(uint i = 0; i < m_things.size(); ++i) {
|
||||
ThingPtr thing = m_things[i];
|
||||
if(thing->isLocalPlayer()) // return local player if there is no other creature
|
||||
creature = thing->self_cast<Creature>();
|
||||
creature = thing->static_self_cast<Creature>();
|
||||
else if(thing->isCreature() && !thing->isLocalPlayer())
|
||||
return thing->self_cast<Creature>();
|
||||
return thing->static_self_cast<Creature>();
|
||||
}
|
||||
if(!creature && !m_walkingCreatures.empty())
|
||||
creature = m_walkingCreatures.back();
|
||||
|
@ -408,7 +408,7 @@ bool Tile::isWalkable()
|
|||
return false;
|
||||
|
||||
if(thing->isCreature()) {
|
||||
CreaturePtr creature = thing->self_cast<Creature>();
|
||||
CreaturePtr creature = thing->static_self_cast<Creature>();
|
||||
if(!creature->isPassable())
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
int getDrawElevation() { return m_drawElevation; }
|
||||
std::vector<ItemPtr> getItems();
|
||||
std::vector<CreaturePtr> getCreatures();
|
||||
const std::vector<ThingPtr>& getThings() { return m_things; }
|
||||
std::vector<ThingPtr> getThings() { return m_things; }
|
||||
ItemPtr getGround();
|
||||
int getGroundSpeed();
|
||||
uint8 getMinimapColorByte();
|
||||
|
@ -109,12 +109,12 @@ public:
|
|||
void setHouseId(uint32 hid) { if(m_flags & TILESTATE_HOUSE) m_houseId = hid; }
|
||||
uint32 getHouseId() { return m_houseId; }
|
||||
|
||||
TilePtr asTile() { return self_cast<Tile>(); }
|
||||
TilePtr asTile() { return static_self_cast<Tile>(); }
|
||||
|
||||
private:
|
||||
std::vector<CreaturePtr> m_walkingCreatures;
|
||||
std::vector<EffectPtr> m_effects; // leave this outside m_things because it has no stackpos.
|
||||
std::vector<ThingPtr> m_things;
|
||||
stdext::packed_vector<CreaturePtr> m_walkingCreatures;
|
||||
stdext::packed_vector<EffectPtr> m_effects; // leave this outside m_things because it has no stackpos.
|
||||
stdext::packed_vector<ThingPtr> m_things;
|
||||
Position m_position;
|
||||
uint8 m_drawElevation;
|
||||
uint32 m_flags, m_houseId;
|
||||
|
|
Loading…
Reference in New Issue