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(); } } };