From 14f90e773d6864e7217cd9139c2809934dfd87b7 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 8 Apr 2018 10:56:33 +0300 Subject: [PATCH] [Client] Split up creation of DedicatedPlayers into multiple methods Additionally, print player guids using their string representations for consistency. The creation and updating of DedicatedPlayer references remains very inelegant, but this commit is the first step towards fixing that. --- apps/openmw/mwmp/DedicatedPlayer.cpp | 217 +++++++++++++++++- apps/openmw/mwmp/DedicatedPlayer.hpp | 12 +- apps/openmw/mwmp/GUIController.cpp | 2 +- apps/openmw/mwmp/PlayerList.cpp | 166 +------------- apps/openmw/mwmp/PlayerList.hpp | 1 - .../player/ProcessorPlayerBaseInfo.hpp | 2 +- 6 files changed, 222 insertions(+), 178 deletions(-) diff --git a/apps/openmw/mwmp/DedicatedPlayer.cpp b/apps/openmw/mwmp/DedicatedPlayer.cpp index 1333f5b1d..a30d60939 100644 --- a/apps/openmw/mwmp/DedicatedPlayer.cpp +++ b/apps/openmw/mwmp/DedicatedPlayer.cpp @@ -1,7 +1,3 @@ -// -// Created by koncord on 02.01.16. -// - #include #include #include @@ -130,6 +126,56 @@ void DedicatedPlayer::move(float dt) MWMechanics::zTurn(ptr, position.rot[2], osg::DegreesToRadians(1.0)); } +void DedicatedPlayer::setBaseInfo() +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + ESM::Creature tempCreature; + ESM::NPC tempNpc; + + if (!creatureRefId.empty()) + { + const ESM::Creature *tmpCreature = world->getStore().get().search(creatureRefId); + if (tmpCreature == 0) + { + creatureRefId = ""; + } + else + { + tempCreature = getCreatureRecord(); + } + } + + if (creatureRefId.empty()) + { + tempNpc = getNpcRecord(); + } + + bool reset = false; + if (reference) + { + deleteReference(); + reset = true; + } + + if (state == 0) + { + createReference(tempNpc, tempCreature, reset); + } + else + { + updateReference(tempNpc, tempCreature); + } + + state = 2; + + // Give this new character a fatigue of at least 1 so it doesn't spawn + // on the ground + creatureStats.mDynamic[2].mBase = 1; + + world->enable(ptr); +} + void DedicatedPlayer::setAnimFlags() { using namespace MWMechanics; @@ -302,16 +348,169 @@ void DedicatedPlayer::playSpeech() winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never); } + +ESM::Creature DedicatedPlayer::getCreatureRecord() +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + ESM::Creature creature; + + const ESM::Creature *tmpCreature = world->getStore().get().search(creatureRefId); + + creature = *tmpCreature; + creature.mScript = ""; + if (!displayCreatureName) + creature.mName = npc.mName; + LOG_APPEND(Log::LOG_INFO, "Player %s looks like %s", npc.mName.c_str(), creatureRefId.c_str()); + + return creature; +} + +ESM::NPC DedicatedPlayer::getNpcRecord() +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + MWWorld::Ptr player = world->getPlayerPtr(); + + ESM::NPC newNpc = *player.get()->mBase; + + // To avoid freezes caused by invalid races, only set race if we find it + // on our client + if (world->getStore().get().search(npc.mRace) != 0) + newNpc.mRace = npc.mRace; + + newNpc.mHead = npc.mHead; + newNpc.mHair = npc.mHair; + newNpc.mClass = npc.mClass; + newNpc.mName = npc.mName; + newNpc.mFlags = npc.mFlags; + + return newNpc; +} + +void DedicatedPlayer::createReference(ESM::NPC& npc, ESM::Creature& creature, bool reset) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + // Temporarily spawn or move player to the center of exterior 0, 0 + ESM::Position spawnPos; + spawnPos.pos[0] = spawnPos.pos[1] = Main::get().getCellController()->getCellSize() / 2; + spawnPos.pos[2] = 0; + MWWorld::CellStore *cellStore = world->getExterior(0, 0); + + string recid; + if (creatureRefId.empty()) + { + LOG_APPEND(Log::LOG_INFO, "- Creating new NPC record"); + npc.mId = "Dedicated Player"; + recid = world->createRecord(npc)->mId; + } + else + { + LOG_APPEND(Log::LOG_INFO, "- Creating new Creature record"); + creature.mId = "Dedicated Player"; + recid = world->createRecord(creature)->mId; + } + + reference = new MWWorld::ManualRef(world->getStore(), recid, 1); + + LOG_APPEND(Log::LOG_INFO, "- Creating new reference pointer for %s", this->npc.mName.c_str()); + + MWWorld::Ptr tmp; + + if (reset) + { + if (cell.isExterior()) + cellStore = world->getExterior(cell.mData.mX, cell.mData.mY); + else + cellStore = world->getInterior(cell.mName); + + spawnPos = position; + } + + tmp = world->placeObject(reference->getPtr(), cellStore, spawnPos); + + ptr.mCell = tmp.mCell; + ptr.mRef = tmp.mRef; + + if (!reset) + { + cell = *ptr.getCell()->getCell(); + position = ptr.getRefData().getPosition(); + } + + ESM::CustomMarker mEditingMarker = Main::get().getGUIController()->createMarker(guid); + marker = mEditingMarker; + setMarkerState(true); +} + +void DedicatedPlayer::updateReference(ESM::NPC& npc, ESM::Creature& creature) +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + // Temporarily spawn or move player to the center of exterior 0, 0 + ESM::Position spawnPos; + spawnPos.pos[0] = spawnPos.pos[1] = Main::get().getCellController()->getCellSize() / 2; + spawnPos.pos[2] = 0; + MWWorld::CellStore *cellStore = world->getExterior(0, 0); + + LOG_APPEND(Log::LOG_INFO, "- Updating reference pointer for %s", npc.mName.c_str()); + + MWWorld::ESMStore *store = const_cast(&world->getStore()); + MWWorld::Store *creature_store = const_cast *> (&store->get()); + MWWorld::Store *npc_store = const_cast *> (&store->get()); + + if (!creatureRefId.empty()) + { + if (!npc.mId.empty() || npc.mId != "Dedicated Player") + { + LOG_APPEND(Log::LOG_INFO, "- Deleting NPC record"); + npc_store->erase(npc.mId); + npc.mId.clear(); + } + creature.mId = ptr.get()->mBase->mId; + creature_store->insert(creature); + } + else + { + if (!creature.mId.empty() || creature.mId != "Dedicated Player") + { + LOG_APPEND(Log::LOG_INFO, "- Deleting Creature record"); + creature_store->erase(creature.mId); + creature.mId.clear(); + } + npc.mId = ptr.get()->mBase->mId; + npc_store->insert(npc); + } + + // Disable Ptr to avoid graphical glitches caused by race changes + world->disable(ptr); + + setPtr(world->moveObject(ptr, cellStore, spawnPos.pos[0], spawnPos.pos[1], spawnPos.pos[2])); + setCell(); +} + +void DedicatedPlayer::deleteReference() +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + + bool isNPC = reference->getPtr().getTypeName() == typeid(ESM::NPC).name(); + if ((!creatureRefId.empty() && isNPC) || + (creatureRefId.empty() && !isNPC)) + { + LOG_APPEND(Log::LOG_INFO, "- Deleting old reference"); + state = 0; + world->deleteObject(ptr); + delete reference; + reference = nullptr; + } +} + MWWorld::Ptr DedicatedPlayer::getPtr() { return ptr; } -MWWorld::Ptr DedicatedPlayer::getLiveCellPtr() -{ - return reference->getPtr(); -} - MWWorld::ManualRef *DedicatedPlayer::getRef() { return reference; diff --git a/apps/openmw/mwmp/DedicatedPlayer.hpp b/apps/openmw/mwmp/DedicatedPlayer.hpp index 781748fb8..b141fa463 100644 --- a/apps/openmw/mwmp/DedicatedPlayer.hpp +++ b/apps/openmw/mwmp/DedicatedPlayer.hpp @@ -6,9 +6,12 @@ #define OPENMW_DEDICATEDPLAYER_HPP #include +#include #include #include +#include "../mwclass/npc.hpp" + #include "../mwmechanics/aisequence.hpp" #include "../mwworld/manualref.hpp" @@ -34,6 +37,7 @@ namespace mwmp void update(float dt); void move(float dt); + void setBaseInfo(); void setAnimFlags(); void setEquipment(); void setCell(); @@ -46,8 +50,14 @@ namespace mwmp void playAnimation(); void playSpeech(); + ESM::NPC getNpcRecord(); + ESM::Creature getCreatureRecord(); + + void createReference(ESM::NPC& npc, ESM::Creature& creature, bool reset); + void updateReference(ESM::NPC& npc, ESM::Creature& creature); + void deleteReference(); + MWWorld::Ptr getPtr(); - MWWorld::Ptr getLiveCellPtr(); MWWorld::ManualRef* getRef(); void setPtr(const MWWorld::Ptr& newPtr); diff --git a/apps/openmw/mwmp/GUIController.cpp b/apps/openmw/mwmp/GUIController.cpp index 2d5fb1a97..50525aa27 100644 --- a/apps/openmw/mwmp/GUIController.cpp +++ b/apps/openmw/mwmp/GUIController.cpp @@ -285,7 +285,7 @@ ESM::CustomMarker mwmp::GUIController::createMarker(const RakNet::RakNetGUID &gu ESM::CustomMarker mEditingMarker; if (!player) { - LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Unknown player guid: %lu", guid.g); + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Unknown player guid: %s", guid.ToString()); return mEditingMarker; } diff --git a/apps/openmw/mwmp/PlayerList.cpp b/apps/openmw/mwmp/PlayerList.cpp index f154938fa..c7d064d9b 100644 --- a/apps/openmw/mwmp/PlayerList.cpp +++ b/apps/openmw/mwmp/PlayerList.cpp @@ -34,173 +34,9 @@ void PlayerList::update(float dt) } } -void PlayerList::createPlayer(RakNet::RakNetGUID guid) -{ - LOG_APPEND(Log::LOG_INFO, "- Setting up character info"); - - MWBase::World *world = MWBase::Environment::get().getWorld(); - - DedicatedPlayer *dedicPlayer = players[guid]; - - ESM::Creature creature; - ESM::NPC npc; - if (!dedicPlayer->creatureRefId.empty()) - { - const ESM::Creature *tmpCreature = world->getStore().get().search(dedicPlayer->creatureRefId); - if (tmpCreature == 0) - { - dedicPlayer->creatureRefId = ""; - createPlayer(guid); - return; - } - creature = *tmpCreature; - creature.mScript = ""; - if (!dedicPlayer->displayCreatureName) - creature.mName = dedicPlayer->npc.mName; - LOG_APPEND(Log::LOG_INFO, "Player %s looks like %s", dedicPlayer->npc.mName.c_str(), - dedicPlayer->creatureRefId.c_str()); - } - else - { - MWWorld::Ptr player = world->getPlayerPtr(); - - npc = *player.get()->mBase; - - // To avoid freezes caused by invalid races, only set race if we find it - // on our client - if (world->getStore().get().search(dedicPlayer->npc.mRace) != 0) - npc.mRace = dedicPlayer->npc.mRace; - - npc.mHead = dedicPlayer->npc.mHead; - npc.mHair = dedicPlayer->npc.mHair; - npc.mClass = dedicPlayer->npc.mClass; - npc.mName = dedicPlayer->npc.mName; - npc.mFlags = dedicPlayer->npc.mFlags; - } - - bool reset = false; - if (dedicPlayer->reference) - { - bool isNPC = dedicPlayer->reference->getPtr().getTypeName() == typeid(ESM::NPC).name(); - if ((!dedicPlayer->creatureRefId.empty() && isNPC) || - (dedicPlayer->creatureRefId.empty() && !isNPC)) - { - if (dedicPlayer->reference) - { - LOG_APPEND(Log::LOG_INFO, "- Deleting old reference"); - dedicPlayer->state = 0; - world->deleteObject(dedicPlayer->ptr); - delete dedicPlayer->reference; - dedicPlayer->reference = nullptr; - reset = true; - } - } - } - - // Temporarily spawn or move player to the center of exterior 0,0 whenever setting base info - ESM::Position spawnPos; - spawnPos.pos[0] = spawnPos.pos[1] = Main::get().getCellController()->getCellSize() / 2; - spawnPos.pos[2] = 0; - MWWorld::CellStore *cellStore = world->getExterior(0, 0); - - if (dedicPlayer->state == 0) - { - string recid; - if (dedicPlayer->creatureRefId.empty()) - { - LOG_APPEND(Log::LOG_INFO, "- Creating new NPC record"); - npc.mId = "Dedicated Player"; - recid = world->createRecord(npc)->mId; - } - else - { - LOG_APPEND(Log::LOG_INFO, "- Creating new Creature record"); - creature.mId = "Dedicated Player"; - recid = world->createRecord(creature)->mId; - } - - dedicPlayer->reference = new MWWorld::ManualRef(world->getStore(), recid, 1); - - LOG_APPEND(Log::LOG_INFO, "- Creating new reference pointer for %s", dedicPlayer->npc.mName.c_str()); - - MWWorld::Ptr tmp; - - if (reset) - { - if (dedicPlayer->cell.isExterior()) - cellStore = world->getExterior(dedicPlayer->cell.mData.mX, dedicPlayer->cell.mData.mY); - else - cellStore = world->getInterior(dedicPlayer->cell.mName); - - spawnPos = dedicPlayer->position; - } - - tmp = world->placeObject(dedicPlayer->reference->getPtr(), cellStore, spawnPos); - - dedicPlayer->ptr.mCell = tmp.mCell; - dedicPlayer->ptr.mRef = tmp.mRef; - - if (!reset) - { - dedicPlayer->cell = *dedicPlayer->ptr.getCell()->getCell(); - dedicPlayer->position = dedicPlayer->ptr.getRefData().getPosition(); - } - - ESM::CustomMarker mEditingMarker = Main::get().getGUIController()->createMarker(guid); - dedicPlayer->marker = mEditingMarker; - dedicPlayer->setMarkerState(true); - } - else - { - LOG_APPEND(Log::LOG_INFO, "- Updating reference pointer for %s", dedicPlayer->npc.mName.c_str()); - - MWWorld::ESMStore *store = const_cast(&world->getStore()); - MWWorld::Store *creature_store = const_cast *> (&store->get()); - MWWorld::Store *npc_store = const_cast *> (&store->get()); - - if (!dedicPlayer->creatureRefId.empty()) - { - if (!npc.mId.empty() || npc.mId != "Dedicated Player") - { - LOG_APPEND(Log::LOG_INFO, "- Deleting NPC record"); - npc_store->erase(npc.mId); - npc.mId.clear(); - } - creature.mId = players[guid]->ptr.get()->mBase->mId; - creature_store->insert(creature); - } - else - { - if (!creature.mId.empty() || creature.mId != "Dedicated Player") - { - LOG_APPEND(Log::LOG_INFO, "- Deleting Creature record"); - creature_store->erase(creature.mId); - creature.mId.clear(); - } - npc.mId = players[guid]->ptr.get()->mBase->mId; - npc_store->insert(npc); - } - - // Disable Ptr to avoid graphical glitches caused by race changes - world->disable(players[guid]->ptr); - - dedicPlayer->setPtr(world->moveObject(dedicPlayer->ptr, cellStore, spawnPos.pos[0], spawnPos.pos[1], spawnPos.pos[2])); - dedicPlayer->setCell(); - } - - dedicPlayer->guid = guid; - dedicPlayer->state = 2; - - // Give this new character a fatigue of at least 1 so it doesn't spawn - // on the ground - dedicPlayer->creatureStats.mDynamic[2].mBase = 1; - - world->enable(players[guid]->ptr); -} - DedicatedPlayer *PlayerList::newPlayer(RakNet::RakNetGUID guid) { - LOG_APPEND(Log::LOG_INFO, "- Creating new DedicatedPlayer with guid %lu", guid.g); + LOG_APPEND(Log::LOG_INFO, "- Creating new DedicatedPlayer with guid %s", guid.ToString()); players[guid] = new DedicatedPlayer(guid); players[guid]->state = 0; diff --git a/apps/openmw/mwmp/PlayerList.hpp b/apps/openmw/mwmp/PlayerList.hpp index 84c39077e..91f03d869 100644 --- a/apps/openmw/mwmp/PlayerList.hpp +++ b/apps/openmw/mwmp/PlayerList.hpp @@ -27,7 +27,6 @@ namespace mwmp static void update(float dt); - static void createPlayer(RakNet::RakNetGUID guid); static DedicatedPlayer *newPlayer(RakNet::RakNetGUID guid); static void disconnectPlayer(RakNet::RakNetGUID guid); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerBaseInfo.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerBaseInfo.hpp index a8e805f5b..026a1ca1e 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerBaseInfo.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerBaseInfo.hpp @@ -49,7 +49,7 @@ namespace mwmp packet.Read(); } - PlayerList::createPlayer(guid); + static_cast(player)->setBaseInfo(); } } };