Skip to content

Instantly share code, notes, and snippets.

@Emtec
Last active November 17, 2015 21:59
Show Gist options
  • Save Emtec/e8ee5b588650c7c9b2d4 to your computer and use it in GitHub Desktop.
Save Emtec/e8ee5b588650c7c9b2d4 to your computer and use it in GitHub Desktop.
/*
* Copyright (C) 20011-2015 ACore3 <http://www.atlantiss.eu/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _OBJECTSTORAGE_H
#define _OBJECTSTORAGE_H
#include "inc/database.h"
#include "inc/cursor.h"
#include "inc/query.h"
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include "Object.h"
#include "ObjectGuid.h"
class Player;
class Transport;
class Guild;
// ------------------------------------------------------------
// In memory database section
// ------------------------------------------------------------
extern dbDatabase object_storage_db;
//
// BaseTable
// - uzywac tylko poprzed dziediczenie. Klasa
// ma tylko na celu stworzenia metod odpowiedzialnych
// za konwertowanie danych
//
class BaseTable
{
protected:
uint64 _guid;
public:
ObjectGuid GetGuid()
{
return ConvertUInt64ToObjectGuid(_guid);
}
protected:
inline const char* ConvertString(std::string str)
{
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
return str.c_str();
}
inline uint64 ConvertObjectGuid(ObjectGuid guid)
{
return guid.GetRawValue();
}
inline ObjectGuid ConvertUInt64ToObjectGuid(uint64 raw)
{
return ObjectGuid(raw);
}
};
class PlayerTable : BaseTable
{
private:
uint32 _guidGuild;
uint8 _level;
uint8 _race;
uint8 _class;
char const* _name;
char const* _guildName;
public:
PlayerTable(Player* player)
{
_guid = ConvertObjectGuid(player->GetGUID());
_level = player->getLevel();
_race = player->getRace();
_class = player->getClass();
_name = ConvertString(player->GetName());
if (player->GetGuild())
{
_guildName = ConvertString(player->GetGuildName());
_guidGuild = player->GetGuildId();
}
else
{
_guidGuild = 0;
_guildName = "";
}
}
public:
TYPE_DESCRIPTOR(KEY(_guid, INDEXED));
TYPE_DESCRIPTOR(KEY(_guidGuild, INDEXED));
TYPE_DESCRIPTOR(KEY(_level, INDEXED));
TYPE_DESCRIPTOR(KEY(_race, INDEXED));
TYPE_DESCRIPTOR(KEY(_class, INDEXED));
TYPE_DESCRIPTOR(KEY(_name, INDEXED|HASHED));
TYPE_DESCRIPTOR(KEY(_guildName, INDEXED|HASHED));
};
REGISTER(PlayerTable);
// ------------------------------------------------------------
// ObjectStorage Section
// ------------------------------------------------------------
template <class T, class Y>
class ObjectStorage
{
public:
static_assert(
(std::is_same<Player, T>::value && std::is_same<PlayerTable, Y>::value)
|| std::is_same<Transport, T>::value
|| std::is_same<Guild, T>::value, "Only Player/Transport/Guild can be registered in global ObjectStorage");
typedef std::unordered_map<ObjectGuid, T*> MapType;
public:
static void Insert(T* o)
{
boost::unique_lock<boost::shared_mutex> lock(_lock);
_objectMap[o->GetGUID()] = o;
if (!std::is_same<BaseTable, Y>::value)
InsertToTable(o);
}
static void Remove(T* o)
{
boost::unique_lock<boost::shared_mutex> lock(_lock);
_objectMap.erase(o->GetGUID());
if (!std::is_same<BaseTable, Y>::value)
RemoveFromTable(o);
}
static T* Find(ObjectGuid guid)
{
boost::shared_lock<boost::shared_mutex> lock(_lock);
typename MapType::iterator itr = _objectMap.find(guid);
return (itr != _objectMap.end()) ? itr->second : nullptr;
}
static T* Find(dbQuery q)
{
boost::shared_lock<boost::shared_mutex> lock(_lock);
if (std::is_same<BaseTable, Y>::value)
ASSERT(false, 'You must implement table class for using find by query');
dbCursor<Y> cursor(object_storage_db);
if (cursor.select(q) == 0)
return nullptr;
ObjectGuid guid = cursor.GetGuid();
typename MapType::iterator itr = _objectMap.find(guid);
return (itr != _objectMap.end()) ? itr->second : nullptr;
}
static std::list<T*> FindAll(dbQuery q, int& found, int maxReturn = -1)
{
boost::shared_lock<boost::shared_mutex> lock(_lock);
if (std::is_same<BaseTable, Y>::value)
ASSERT(false, 'You must implement table class for using find by query');
std::list<T*> objects;
dbCursor<Y> cursor(object_storage_db);
found = cursor.select(q) > 0;
if (found > 0 && (maxReturn == -1 || maxReturn > 0))
{
int iter = 0;
do
{
if (maxReturn > 0 && ++iter > maxReturn)
break;
ObjectGuid guid = cursor.GetGuid();
typename MapType::iterator itr = _objectMap.find(guid);
if (itr != _objectMap.end())
objects.insert<T*>(itr->second);
} while (cursor.next());
}
return objects;
}
static MapType& GetContainer() { return _objectMap; }
static boost::shared_mutex* GetLock() { return &_lock; }
private:
ObjectStorage() { }
static void InsertToTable(T* o)
{
object_storage_db->insert(new Y(o));
}
static void RemoveFromTable(T* o)
{
dbQuery q;
q = "_guid=", o->GetGUID().GetRawValue();
dbCursor<Y> cursor(object_storage_db);
if (cursor.select(q) != 0)
cursor.removeAllSelected();
}
static boost::shared_mutex _lock;
static MapType _objectMap;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment