forked from mirror/openmw-tes3mp
Merge pull request #158 from TES3MP/tes3mp-LoadedCell
Add functionality for storing cell loads on the server
This commit is contained in:
commit
00cddabc12
8 changed files with 415 additions and 14 deletions
|
@ -69,6 +69,7 @@ set(SERVER
|
||||||
Networking.cpp
|
Networking.cpp
|
||||||
Utils.cpp
|
Utils.cpp
|
||||||
MasterClient.cpp
|
MasterClient.cpp
|
||||||
|
Cell.cpp
|
||||||
Script/Script.cpp Script/ScriptFunction.cpp
|
Script/Script.cpp Script/ScriptFunction.cpp
|
||||||
Script/ScriptFunctions.cpp
|
Script/ScriptFunctions.cpp
|
||||||
|
|
||||||
|
|
221
apps/openmw-mp/Cell.cpp
Normal file
221
apps/openmw-mp/Cell.cpp
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
//
|
||||||
|
// Created by koncord on 18.02.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Cell.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#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 = begin(); it != 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cell::sendToLoaded(mwmp::WorldPacket *worldPacket, mwmp::BaseEvent *baseEvent)
|
||||||
|
{
|
||||||
|
std::list <Player*> plList;
|
||||||
|
|
||||||
|
for (auto pl :getPlayers())
|
||||||
|
plList.push_back(pl);
|
||||||
|
|
||||||
|
plList.sort();
|
||||||
|
plList.unique();
|
||||||
|
|
||||||
|
for (auto pl : plList)
|
||||||
|
{
|
||||||
|
if (pl->guid == baseEvent->guid) continue;
|
||||||
|
worldPacket->Send(baseEvent, pl->guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Cell::getDescription() const
|
||||||
|
{
|
||||||
|
return cell.getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
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::getCell(ESM::Cell *esmCell)
|
||||||
|
{
|
||||||
|
if (esmCell->isExterior())
|
||||||
|
return getCellByXY(esmCell->mData.mX, esmCell->mData.mY);
|
||||||
|
else
|
||||||
|
return getCellByName(esmCell->mName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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::getCellByName(std::string cellName)
|
||||||
|
{
|
||||||
|
auto it = find_if(cells.begin(), cells.end(), [cellName](const Cell *c) {
|
||||||
|
return c->cell.mName == cellName;
|
||||||
|
});
|
||||||
|
if (it == cells.end())
|
||||||
|
return nullptr;
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell *CellController::addCell(ESM::Cell cellData)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "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())
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Deleting empty cell from memory: %s", player->npc.mName, player->getId(), cell->cell.getDescription().c_str());
|
||||||
|
auto it = find(cells.begin(), cells.end(), cell);
|
||||||
|
delete *it;
|
||||||
|
cells.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CellController::deletePlayer(Player *player)
|
||||||
|
{
|
||||||
|
for_each (player->getCells().begin(), player->getCells().end(), [&player](Cell *cell) {
|
||||||
|
for (auto it = cell->begin(); it != cell->end(); ++it)
|
||||||
|
{
|
||||||
|
if (*it == player)
|
||||||
|
{
|
||||||
|
cell->players.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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_VERBOSE, "Player %s (%d) unloaded cell: %s", player->npc.mName, player->getId(), cell.cell.getDescription().c_str());
|
||||||
|
Cell *c;
|
||||||
|
if (!cell.cell.isExterior())
|
||||||
|
c = getCellByName(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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell::Iterator Cell::begin()
|
||||||
|
{
|
||||||
|
return players.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell::Iterator Cell::end()
|
||||||
|
{
|
||||||
|
return players.end();
|
||||||
|
}
|
76
apps/openmw-mp/Cell.hpp
Normal file
76
apps/openmw-mp/Cell.hpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
//
|
||||||
|
// Created by koncord on 18.02.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OPENMW_CELL_HPP
|
||||||
|
#define OPENMW_CELL_HPP
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <string>
|
||||||
|
#include <components/esm/records.hpp>
|
||||||
|
#include <components/openmw-mp/Base/BaseEvent.hpp>
|
||||||
|
#include <components/openmw-mp/Packets/World/WorldPacket.hpp>
|
||||||
|
|
||||||
|
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<Cell*> TContainer;
|
||||||
|
typedef TContainer::iterator TIter;
|
||||||
|
|
||||||
|
Cell * addCell(ESM::Cell cell);
|
||||||
|
void removeCell(Cell *);
|
||||||
|
|
||||||
|
void removePlayer(Cell *cell, Player *player);
|
||||||
|
void deletePlayer(Player *player);
|
||||||
|
|
||||||
|
Cell *getCell(ESM::Cell *esmCell);
|
||||||
|
Cell *getCellByXY(int x, int y);
|
||||||
|
Cell *getCellByName(std::string cellName);
|
||||||
|
|
||||||
|
void update(Player *player);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static CellController *sThis;
|
||||||
|
TContainer cells;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Cell
|
||||||
|
{
|
||||||
|
friend class CellController;
|
||||||
|
public:
|
||||||
|
Cell(ESM::Cell cell);
|
||||||
|
typedef std::deque<Player*> TPlayers;
|
||||||
|
typedef TPlayers::iterator Iterator;
|
||||||
|
|
||||||
|
Iterator begin();
|
||||||
|
Iterator end();
|
||||||
|
|
||||||
|
void addPlayer(Player *player);
|
||||||
|
void removePlayer(Player *player);
|
||||||
|
|
||||||
|
TPlayers getPlayers();
|
||||||
|
void sendToLoaded(mwmp::WorldPacket *worldPacket, mwmp::BaseEvent *baseEvent);
|
||||||
|
|
||||||
|
std::string getDescription() const;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
TPlayers players;
|
||||||
|
ESM::Cell cell;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OPENMW_CELL_HPP
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "Networking.hpp"
|
#include "Networking.hpp"
|
||||||
#include "MasterClient.hpp"
|
#include "MasterClient.hpp"
|
||||||
|
#include "Cell.hpp"
|
||||||
|
|
||||||
using namespace mwmp;
|
using namespace mwmp;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -29,6 +30,8 @@ Networking::Networking(RakNet::RakPeerInterface *peer)
|
||||||
this->peer = peer;
|
this->peer = peer;
|
||||||
players = Players::getPlayers();
|
players = Players::getPlayers();
|
||||||
|
|
||||||
|
CellController::create();
|
||||||
|
|
||||||
playerController = new PlayerPacketController(peer);
|
playerController = new PlayerPacketController(peer);
|
||||||
worldController = new WorldPacketController(peer);
|
worldController = new WorldPacketController(peer);
|
||||||
|
|
||||||
|
@ -46,6 +49,8 @@ Networking::~Networking()
|
||||||
{
|
{
|
||||||
Script::Call<Script::CallbackIdentity("OnServerExit")>(false);
|
Script::Call<Script::CallbackIdentity("OnServerExit")>(false);
|
||||||
|
|
||||||
|
CellController::destroy();
|
||||||
|
|
||||||
sThis = 0;
|
sThis = 0;
|
||||||
delete playerController;
|
delete playerController;
|
||||||
LOG_QUIT();
|
LOG_QUIT();
|
||||||
|
@ -145,7 +150,10 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
if (!player->creatureStats.mDead)
|
if (!player->creatureStats.mDead)
|
||||||
{
|
{
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
myPacket->Send(player, true); //send to other clients
|
//myPacket->Send(player, true); //send to other clients
|
||||||
|
|
||||||
|
player->sendToLoaded(myPacket);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -162,7 +170,26 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Moved to %s",
|
LOG_APPEND(Log::LOG_INFO, "- Moved to %s",
|
||||||
player->cell.getDescription().c_str());
|
player->cell.getDescription().c_str());
|
||||||
|
|
||||||
|
player->forEachLoaded([this](Player *pl, Player *other) {
|
||||||
|
playerController->GetPacket(ID_PLAYER_DYNAMICSTATS)->Send(other, pl->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_ATTRIBUTE)->Send(other, pl->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_SKILL)->Send(other, pl->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_POS)->Send(other, pl->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_EQUIPMENT)->Send(other, pl->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_ATTACK)->Send(other, pl->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_DRAWSTATE)->Send(other, pl->guid);
|
||||||
|
|
||||||
|
playerController->GetPacket(ID_PLAYER_DYNAMICSTATS)->Send(pl, other->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_ATTRIBUTE)->Send(pl, other->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_SKILL)->Send(pl, other->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_POS)->Send(pl, other->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_EQUIPMENT)->Send(pl, other->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_ATTACK)->Send(pl, other->guid);
|
||||||
|
playerController->GetPacket(ID_PLAYER_DRAWSTATE)->Send(pl, other->guid);
|
||||||
|
});
|
||||||
|
|
||||||
myPacket->Send(player, true); //send to other clients
|
myPacket->Send(player, true); //send to other clients
|
||||||
|
|
||||||
Script::Call<Script::CallbackIdentity("OnPlayerCellChange")>(player->getId());
|
Script::Call<Script::CallbackIdentity("OnPlayerCellChange")>(player->getId());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -180,6 +207,8 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
|
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
|
|
||||||
|
CellController::get()->update(player);
|
||||||
|
|
||||||
Script::Call<Script::CallbackIdentity("OnPlayerCellState")>(player->getId());
|
Script::Call<Script::CallbackIdentity("OnPlayerCellState")>(player->getId());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -190,7 +219,9 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
if (!player->creatureStats.mDead)
|
if (!player->creatureStats.mDead)
|
||||||
{
|
{
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
myPacket->Send(player, true);
|
//myPacket->Send(player, true);
|
||||||
|
|
||||||
|
player->sendToLoaded(myPacket);
|
||||||
|
|
||||||
Script::Call<Script::CallbackIdentity("OnPlayerAttributesChange")>(player->getId());
|
Script::Call<Script::CallbackIdentity("OnPlayerAttributesChange")>(player->getId());
|
||||||
}
|
}
|
||||||
|
@ -203,7 +234,8 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
if (!player->creatureStats.mDead)
|
if (!player->creatureStats.mDead)
|
||||||
{
|
{
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
myPacket->Send(player, true);
|
//myPacket->Send(player, true);
|
||||||
|
player->sendToLoaded(myPacket);
|
||||||
|
|
||||||
Script::Call<Script::CallbackIdentity("OnPlayerSkillsChange")>(player->getId());
|
Script::Call<Script::CallbackIdentity("OnPlayerSkillsChange")>(player->getId());
|
||||||
}
|
}
|
||||||
|
@ -216,7 +248,7 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
if (!player->creatureStats.mDead)
|
if (!player->creatureStats.mDead)
|
||||||
{
|
{
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
myPacket->Send(player, true);
|
//myPacket->Send(player, true);
|
||||||
|
|
||||||
Script::Call<Script::CallbackIdentity("OnPlayerLevelChange")>(player->getId());
|
Script::Call<Script::CallbackIdentity("OnPlayerLevelChange")>(player->getId());
|
||||||
}
|
}
|
||||||
|
@ -228,7 +260,9 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
DEBUG_PRINTF("ID_PLAYER_EQUIPMENT\n");
|
DEBUG_PRINTF("ID_PLAYER_EQUIPMENT\n");
|
||||||
|
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
myPacket->Send(player, true);
|
//myPacket->Send(player, true);
|
||||||
|
|
||||||
|
player->sendToLoaded(myPacket);
|
||||||
|
|
||||||
Script::Call<Script::CallbackIdentity("OnPlayerEquipmentChange")>(player->getId());
|
Script::Call<Script::CallbackIdentity("OnPlayerEquipmentChange")>(player->getId());
|
||||||
|
|
||||||
|
@ -291,7 +325,8 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
myPacket->Send(player, true);
|
//myPacket->Send(player, true);
|
||||||
|
player->sendToLoaded(myPacket);
|
||||||
playerController->GetPacket(ID_PLAYER_DYNAMICSTATS)->RequestData(player->attack.target);
|
playerController->GetPacket(ID_PLAYER_DYNAMICSTATS)->RequestData(player->attack.target);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -301,7 +336,10 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
{
|
{
|
||||||
DEBUG_PRINTF("ID_PLAYER_DYNAMICSTATS\n");
|
DEBUG_PRINTF("ID_PLAYER_DYNAMICSTATS\n");
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
myPacket->Send(player, true);
|
//myPacket->Send(player, true);
|
||||||
|
|
||||||
|
player->sendToLoaded(myPacket);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +390,10 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
{
|
{
|
||||||
DEBUG_PRINTF("ID_PLAYER_DRAWSTATE\n");
|
DEBUG_PRINTF("ID_PLAYER_DRAWSTATE\n");
|
||||||
myPacket->Read(player);
|
myPacket->Read(player);
|
||||||
myPacket->Send(player, true);
|
//myPacket->Send(player, true);
|
||||||
|
|
||||||
|
player->sendToLoaded(myPacket);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,6 +599,15 @@ void Networking::processWorldPacket(RakNet::Packet *packet)
|
||||||
player->npc.mName.c_str());
|
player->npc.mName.c_str());
|
||||||
|
|
||||||
myPacket->Read(baseEvent);
|
myPacket->Read(baseEvent);
|
||||||
|
|
||||||
|
LOG_APPEND(Log::LOG_WARN, "- action: %i", baseEvent->action);
|
||||||
|
|
||||||
|
// Until we have a timestamp-based system, send packets pertaining to more
|
||||||
|
// than one container (i.e. replies to server requests for container contents)
|
||||||
|
// only to players who have the container's cell loaded
|
||||||
|
if (baseEvent->action == BaseEvent::SET && baseEvent->objectChanges.count > 1)
|
||||||
|
CellController::get()->getCell(&baseEvent->cell)->sendToLoaded(myPacket, baseEvent);
|
||||||
|
else
|
||||||
myPacket->Send(baseEvent, true);
|
myPacket->Send(baseEvent, true);
|
||||||
|
|
||||||
Script::Call<Script::CallbackIdentity("OnContainer")>(
|
Script::Call<Script::CallbackIdentity("OnContainer")>(
|
||||||
|
|
|
@ -15,6 +15,8 @@ void Players::deletePlayer(RakNet::RakNetGUID guid)
|
||||||
|
|
||||||
if (players[guid] != 0)
|
if (players[guid] != 0)
|
||||||
{
|
{
|
||||||
|
CellController::get()->deletePlayer(players[guid]);
|
||||||
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Emptying slot %i",
|
LOG_APPEND(Log::LOG_INFO, "- Emptying slot %i",
|
||||||
players[guid]->getId());
|
players[guid]->getId());
|
||||||
|
|
||||||
|
@ -135,3 +137,44 @@ std::chrono::steady_clock::time_point Player::getLastAttackerTime()
|
||||||
{
|
{
|
||||||
return lastAttackerTime;
|
return lastAttackerTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CellController::TContainer Player::getCells()
|
||||||
|
{
|
||||||
|
return cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::sendToLoaded(mwmp::PlayerPacket *myPacket)
|
||||||
|
{
|
||||||
|
std::list <Player*> plList;
|
||||||
|
|
||||||
|
for (auto cell : getCells())
|
||||||
|
for (auto pl : *cell)
|
||||||
|
plList.push_back(pl);
|
||||||
|
|
||||||
|
plList.sort();
|
||||||
|
plList.unique();
|
||||||
|
|
||||||
|
for (auto pl : plList)
|
||||||
|
{
|
||||||
|
if (pl == this) continue;
|
||||||
|
myPacket->Send(this, pl->guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::forEachLoaded(std::function<void(Player *pl, Player *other)> func)
|
||||||
|
{
|
||||||
|
std::list <Player*> plList;
|
||||||
|
|
||||||
|
for (auto cell : getCells())
|
||||||
|
for (auto pl : *cell)
|
||||||
|
plList.push_back(pl);
|
||||||
|
|
||||||
|
plList.sort();
|
||||||
|
plList.unique();
|
||||||
|
|
||||||
|
for (auto pl : plList)
|
||||||
|
{
|
||||||
|
if (pl == this) continue;
|
||||||
|
func(this, pl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include <components/openmw-mp/Log.hpp>
|
#include <components/openmw-mp/Log.hpp>
|
||||||
#include <components/openmw-mp/Base/BasePlayer.hpp>
|
#include <components/openmw-mp/Base/BasePlayer.hpp>
|
||||||
|
#include <components/openmw-mp/Packets/Player/PlayerPacket.hpp>
|
||||||
|
#include "Cell.hpp"
|
||||||
|
|
||||||
struct Player;
|
struct Player;
|
||||||
typedef std::map<RakNet::RakNetGUID, Player*> TPlayers;
|
typedef std::map<RakNet::RakNetGUID, Player*> TPlayers;
|
||||||
|
@ -38,6 +40,7 @@ private:
|
||||||
|
|
||||||
class Player : public mwmp::BasePlayer
|
class Player : public mwmp::BasePlayer
|
||||||
{
|
{
|
||||||
|
friend class Cell;
|
||||||
unsigned short id;
|
unsigned short id;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -67,12 +70,18 @@ public:
|
||||||
|
|
||||||
virtual ~Player();
|
virtual ~Player();
|
||||||
|
|
||||||
|
CellController::TContainer getCells();
|
||||||
|
void sendToLoaded(mwmp::PlayerPacket *myPacket);
|
||||||
|
|
||||||
|
void forEachLoaded(std::function<void(Player *pl, Player *other)> func);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mwmp::InventoryChanges inventoryChangesBuffer;
|
mwmp::InventoryChanges inventoryChangesBuffer;
|
||||||
mwmp::SpellbookChanges spellbookChangesBuffer;
|
mwmp::SpellbookChanges spellbookChangesBuffer;
|
||||||
mwmp::JournalChanges journalChangesBuffer;
|
mwmp::JournalChanges journalChangesBuffer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CellController::TContainer cells;
|
||||||
bool handshakeState;
|
bool handshakeState;
|
||||||
int loadState;
|
int loadState;
|
||||||
unsigned short lastAttacker;
|
unsigned short lastAttacker;
|
||||||
|
|
|
@ -747,6 +747,7 @@ void Networking::processWorldPacket(RakNet::Packet *packet)
|
||||||
if (!ptrCellStore) return;
|
if (!ptrCellStore) return;
|
||||||
|
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Received ID_CONTAINER");
|
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Received ID_CONTAINER");
|
||||||
|
LOG_APPEND(Log::LOG_WARN, "- action: %i", event->action);
|
||||||
|
|
||||||
// If we've received a request for information, comply with it
|
// If we've received a request for information, comply with it
|
||||||
if (event->action == mwmp::BaseEvent::REQUEST)
|
if (event->action == mwmp::BaseEvent::REQUEST)
|
||||||
|
|
Loading…
Reference in a new issue