diff --git a/apps/openmw-mp/CMakeLists.txt b/apps/openmw-mp/CMakeLists.txt index 11863815f..061b57fac 100644 --- a/apps/openmw-mp/CMakeLists.txt +++ b/apps/openmw-mp/CMakeLists.txt @@ -69,6 +69,7 @@ set(SERVER Networking.cpp Utils.cpp MasterClient.cpp + Cell.cpp Script/Script.cpp Script/ScriptFunction.cpp Script/ScriptFunctions.cpp diff --git a/apps/openmw-mp/Cell.cpp b/apps/openmw-mp/Cell.cpp new file mode 100644 index 000000000..67d5ee922 --- /dev/null +++ b/apps/openmw-mp/Cell.cpp @@ -0,0 +1,169 @@ +// +// Created by koncord on 18.02.17. +// + +#include "Cell.hpp" + +#include +#include "Player.hpp" + +using namespace std; + +void Cell::AddPlayer(Player *player) +{ + auto it = find(player->cells.begin(), player->cells.end(), this); + if(it == player->cells.end()) + player->cells.push_back(this); + players.push_back(player); +} + +void Cell::RemovePlayer(Player *player) +{ + for(Iterator it = players.begin(); it != players.end(); it++) + { + if(*it == player) + { + auto it2 = find(player->cells.begin(), player->cells.end(), this); + if(it2 != player->cells.end()) + player->cells.erase(it2); + players.erase(it); + return; + } + + } + +} + +Cell::TPlayers Cell::getPlayers() +{ + return players; +} + +CellController::CellController() +{ + +} + +CellController::~CellController() +{ + +} + +CellController *CellController::sThis = nullptr; + +void CellController::Create() +{ + sThis = new CellController; +} + +void CellController::Destroy() +{ + assert(sThis); + delete sThis; + sThis = nullptr; +} + +CellController *CellController::Get() +{ + return sThis; +} + +Cell *CellController::GetCellByXY(int x, int y) +{ + auto it = find_if(cells.begin(), cells.end(), [x, y](const Cell *c) { + return c->cell.mData.mX == x && c->cell.mData.mY == y; + }); + if(it == cells.end()) + return nullptr; + return *it; +} + +Cell *CellController::GetCellByID(std::string cellid) +{ + auto it = find_if(cells.begin(), cells.end(), [cellid](const Cell *c) { + return c->cell.mName == cellid; + }); + if(it == cells.end()) + return nullptr; + return *it; +} + +Cell *CellController::AddCell(ESM::Cell cellData) +{ + + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Loaded cells: %d", cells.size()); + auto it = find_if(cells.begin(), cells.end(), [cellData](const Cell *c) { + //return c->cell.sRecordId == cellData.sRecordId; // Currently we cannot compare because plugin lists can be loaded in different order + return c->cell.mData.mX == cellData.mData.mX && c->cell.mData.mY == cellData.mData.mY && + c->cell.mCellId.mWorldspace == cellData.mCellId.mWorldspace; + }); + Cell *cell; + if(it == cells.end()) + { + cell = new Cell(cellData); + cells.push_back(cell); + } + else + cell = *it; + return cell; + + +} + +void CellController::RemoveCell(Cell *cell) +{ + if(cell == nullptr) + return; + for (auto it = cells.begin(); it != cells.end();) + { + if(*it != nullptr && *it == cell) + { + delete *it; + it = cells.erase(it); + } + else + ++it; + } +} + +void CellController::RemovePlayer(Cell *cell, Player *player) +{ + + cell->RemovePlayer(player); + + if(cell->players.empty()) + { + auto it = find(cells.begin(), cells.end(), cell); + delete *it; + cells.erase(it); + } +} + +void CellController::update(Player *player) +{ + for(auto cell : player->cellStateChanges.cellStates) + { + if(cell.type == mwmp::CellState::LOAD) + { + Cell *c = AddCell(cell.cell); + c->AddPlayer(player); + } + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Unload cell: %d %d %s", cell.cell.mData.mX, cell.cell.mData.mY, cell.cell.mName.c_str()); + Cell *c; + if(!cell.cell.isExterior()) + c = GetCellByID(cell.cell.mName); + else + c = GetCellByXY(cell.cell.getGridX(), cell.cell.getGridY()); + + if(c != nullptr) + RemovePlayer(c, player); + } + } +} + +Cell::Cell(ESM::Cell cell): cell(cell) +{ + +} diff --git a/apps/openmw-mp/Cell.hpp b/apps/openmw-mp/Cell.hpp new file mode 100644 index 000000000..d121f9c3a --- /dev/null +++ b/apps/openmw-mp/Cell.hpp @@ -0,0 +1,64 @@ +// +// Created by koncord on 18.02.17. +// + +#ifndef OPENMW_CELL_HPP +#define OPENMW_CELL_HPP + +#include +#include +#include + +class Player; +class Cell; + + +class CellController +{ +private: + CellController(); + ~CellController(); + + CellController(CellController&); // not used +public: + static void Create(); + static void Destroy(); + static CellController *Get(); +public: + typedef std::deque TContainer; + typedef TContainer::iterator TIter; + + Cell * AddCell(ESM::Cell cell); + void RemoveCell(Cell *); + + void RemovePlayer(Cell *cell, Player *player); + + Cell *GetCellByXY(int x, int y); + Cell *GetCellByID(std::string cellid); + + void update(Player *player); + +private: + static CellController *sThis; + TContainer cells; +}; + +class Cell +{ + friend class CellController; +public: + Cell(ESM::Cell cell); + typedef std::deque TPlayers; + typedef TPlayers::iterator Iterator; + + void AddPlayer(Player *player); + void RemovePlayer(Player *player); + + TPlayers getPlayers(); +private: + TPlayers players; + ESM::Cell cell; +}; + + +#endif //OPENMW_CELL_HPP diff --git a/apps/openmw-mp/Player.cpp b/apps/openmw-mp/Player.cpp index 666ed5282..5c2325ae0 100644 --- a/apps/openmw-mp/Player.cpp +++ b/apps/openmw-mp/Player.cpp @@ -135,3 +135,8 @@ std::chrono::steady_clock::time_point Player::getLastAttackerTime() { return lastAttackerTime; } + +CellController::TContainer Player::GetCells() +{ + return cells; +} diff --git a/apps/openmw-mp/Player.hpp b/apps/openmw-mp/Player.hpp index 3fdc0b2e3..3045c4b4b 100644 --- a/apps/openmw-mp/Player.hpp +++ b/apps/openmw-mp/Player.hpp @@ -17,6 +17,7 @@ #include #include +#include "Cell.hpp" struct Player; typedef std::map TPlayers; @@ -38,6 +39,7 @@ private: class Player : public mwmp::BasePlayer { + friend class Cell; unsigned short id; public: @@ -67,12 +69,15 @@ public: virtual ~Player(); + CellController::TContainer GetCells(); + public: mwmp::InventoryChanges inventoryChangesBuffer; mwmp::SpellbookChanges spellbookChangesBuffer; mwmp::JournalChanges journalChangesBuffer; private: + CellController::TContainer cells; bool handshakeState; int loadState; unsigned short lastAttacker;