From 90f3ff2da4b37a6766e0eb369150d866ec488d06 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 12 Apr 2018 18:18:17 +0300 Subject: [PATCH 01/14] Don't force DDS file usage (fixes #1392) Fallback to a DDS file if the requested texture path doesn't point to an existing file, not vice versa --- components/misc/resourcehelpers.cpp | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/components/misc/resourcehelpers.cpp b/components/misc/resourcehelpers.cpp index 5cf4378b8..f38387ff8 100644 --- a/components/misc/resourcehelpers.cpp +++ b/components/misc/resourcehelpers.cpp @@ -63,28 +63,16 @@ std::string Misc::ResourceHelpers::correctResourcePath(const std::string &topLev std::string origExt = correctedPath; - // since we know all (GOTY edition or less) textures end - // in .dds, we change the extension - bool changedToDds = changeExtensionToDds(correctedPath); - if (vfs->exists(correctedPath)) + if (vfs->exists(origExt) + || (changeExtensionToDds(correctedPath) && vfs->exists(correctedPath))) return correctedPath; - // if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods) - // verify, and revert if false (this call succeeds quickly, but fails slowly) - if (changedToDds && vfs->exists(origExt)) - return origExt; // fall back to a resource in the top level directory if it exists - std::string fallback = topLevelDirectory + "\\" + getBasename(correctedPath); - if (vfs->exists(fallback)) + std::string fallback = topLevelDirectory + "\\" + getBasename(origExt); + if (vfs->exists(fallback) + || (changeExtensionToDds(fallback) && vfs->exists(fallback))) return fallback; - if (changedToDds) - { - fallback = topLevelDirectory + "\\" + getBasename(origExt); - if (vfs->exists(fallback)) - return fallback; - } - return correctedPath; } From 8617d0603b9d8b0fe4ce89cdee593bb032505230 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 18 Apr 2018 18:25:53 +0300 Subject: [PATCH 02/14] Display a message if a spell the player tries to use via a quick key is missing (fixes #4391) --- apps/openmw/mwgui/quickkeysmenu.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 6da7b0905..2ce9d04e5 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -330,7 +330,12 @@ namespace MWGui MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); MWMechanics::Spells& spells = stats.getSpells(); if (!spells.hasSpell(spellId)) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find(spellId); + MWBase::Environment::get().getWindowManager()->messageBox ( + "#{sQuickMenu5} " + spell->mName); return; + } store.setSelectedEnchantItem(store.end()); MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player))); MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell); From 48467814d4745cfe27835bd59cd1be6a98f29d58 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 8 Apr 2018 23:10:14 +0300 Subject: [PATCH 03/14] Improve random number generation --- components/misc/rng.cpp | 15 +++++++++------ components/misc/rng.hpp | 4 ++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/components/misc/rng.cpp b/components/misc/rng.cpp index df0fc687e..dfe0eff40 100644 --- a/components/misc/rng.cpp +++ b/components/misc/rng.cpp @@ -1,28 +1,31 @@ #include "rng.hpp" -#include -#include + +#include +#include namespace Misc { + std::mt19937 Rng::generator = std::mt19937(); + void Rng::init() { - std::srand(static_cast(std::time(NULL))); + generator.seed(static_cast(std::chrono::high_resolution_clock::now().time_since_epoch().count())); } float Rng::rollProbability() { - return static_cast(std::rand() / (static_cast(RAND_MAX)+1.0)); + return std::uniform_real_distribution(0, 1 - std::numeric_limits::epsilon())(generator); } float Rng::rollClosedProbability() { - return static_cast(std::rand() / static_cast(RAND_MAX)); + return std::uniform_real_distribution(0, 1)(generator); } int Rng::rollDice(int max) { - return static_cast((std::rand() / (static_cast(RAND_MAX)+1.0)) * (max)); + return std::uniform_int_distribution(0, max - 1)(generator); } } diff --git a/components/misc/rng.hpp b/components/misc/rng.hpp index 01fcdd763..ff56906d9 100644 --- a/components/misc/rng.hpp +++ b/components/misc/rng.hpp @@ -2,6 +2,7 @@ #define OPENMW_COMPONENTS_MISC_RNG_H #include +#include namespace Misc { @@ -13,6 +14,9 @@ class Rng { public: + /// create a RNG + static std::mt19937 generator; + /// seed the RNG static void init(); From 37dc3200d1360410280247ecef7dd024d802b6f4 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 19 Apr 2018 23:43:13 +0300 Subject: [PATCH 04/14] Inherit the calling object scale in PlaceAt (fixes #4308) --- apps/openmw/mwscript/transformationextensions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 68b1063e4..5e617fb1a 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -530,7 +530,8 @@ namespace MWScript // create item MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1); - MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance); + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance); + MWBase::Environment::get().getWorld()->scaleObject(ptr, actor.getCellRef().getScale()); } } }; From 48fb6bb9e8ec77b1d5306e8d7e729d2c2d224d8f Mon Sep 17 00:00:00 2001 From: Evgeny Kurnevsky Date: Sat, 21 Apr 2018 16:27:07 +0300 Subject: [PATCH 05/14] Fix crash when rollDice is called with 0. --- components/misc/rng.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/misc/rng.cpp b/components/misc/rng.cpp index dfe0eff40..e402f0b79 100644 --- a/components/misc/rng.cpp +++ b/components/misc/rng.cpp @@ -25,7 +25,7 @@ namespace Misc int Rng::rollDice(int max) { - return std::uniform_int_distribution(0, max - 1)(generator); + return max > 0 ? std::uniform_int_distribution(0, max - 1)(generator) : 0; } } From c025b8f8f3ceab7998c53778cecfdb11f0a2c5ca Mon Sep 17 00:00:00 2001 From: Evgeny Kurnevsky Date: Sat, 21 Apr 2018 16:42:28 +0300 Subject: [PATCH 06/14] Remove useless comparison. --- apps/openmw/mwmechanics/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 06e0a42d7..2ef5e07d7 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -286,7 +286,7 @@ void CharacterController::refreshHitRecoilAnims() } else if (recovery) { - std::string anim = isSwimming ? chooseRandomGroup("swimhit") : chooseRandomGroup("hit"); + std::string anim = chooseRandomGroup("swimhit"); if (isSwimming && mAnimation->hasAnimation(anim)) { mHitState = CharState_SwimHit; From 608dcbafe6590d25187071bc15558ac8e9c90c2b Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 22 Apr 2018 11:22:36 +0300 Subject: [PATCH 07/14] [Client] Fix skill updates for LocalPlayer partially broken by 78441c769a23c23b98deca1725d3ccfc0ced7f75 --- apps/openmw/mwmp/LocalPlayer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 98ec6bc0b..dd1e0515a 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -280,6 +280,7 @@ void LocalPlayer::updateSkills(bool forceUpdate) { // Update a skill if its base value has changed at all or its progress has changed enough if (ptrNpcStats.getSkill(i).getBase() != npcStats.mSkills[i].mBase || + ptrNpcStats.getSkill(i).getModifier() != npcStats.mSkills[i].mMod || ptrNpcStats.getSkill(i).getProgress() != npcStats.mSkills[i].mProgress || forceUpdate) { From f0288282bef8e3c3f20fd68910a43707fa6c9744 Mon Sep 17 00:00:00 2001 From: Alexander Olofsson Date: Sun, 22 Apr 2018 12:40:22 +0200 Subject: [PATCH 08/14] Slight appdata cleanup and improvement --- files/openmw.appdata.xml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/files/openmw.appdata.xml b/files/openmw.appdata.xml index 1503c2fd8..e66fb2978 100644 --- a/files/openmw.appdata.xml +++ b/files/openmw.appdata.xml @@ -3,10 +3,10 @@ Copyright 2015 Alexandre Moine Copyright 2017 Bret Curtis --> - + org.openmw.desktop CC0-1.0 - GPL-3.0 and MIT + GPL-3.0 and MIT OpenMW Unofficial open source engine re-implementation of the game Morrowind @@ -20,7 +20,6 @@ Copyright 2017 Bret Curtis You will still need the original game data to play OpenMW.

- https://wiki.openmw.org/images/b/b2/Openmw_0.11.1_launcher_1.png @@ -34,7 +33,18 @@ Copyright 2017 Bret Curtis https://wiki.openmw.org/images/5/5b/Screenshot_Vivec_seen_from_Ebonheart_0.35.png Vivec seen from Ebonheart on OpenMW + + http://wiki.openmw.org/images/a/a3/0.40_Screenshot-Balmora_3.png + Balmora at morning on OpenMW + + + Game + RolePlaying + + + + https://openmw.org https://bugs.openmw.org/ https://openmw.org/faq/ From 55a6344fb0dca253c2177a1bacd8e5c51ec989ba Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 22 Apr 2018 15:41:07 +0000 Subject: [PATCH 09/14] Revert log spam --- components/fallback/fallback.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/fallback/fallback.cpp b/components/fallback/fallback.cpp index ce6cba313..edc3f2678 100644 --- a/components/fallback/fallback.cpp +++ b/components/fallback/fallback.cpp @@ -1,7 +1,5 @@ #include "fallback.hpp" -#include - #include @@ -19,7 +17,6 @@ namespace Fallback std::map::const_iterator it; if((it = mFallbackMap.find(fall)) == mFallbackMap.end()) { - std::cerr << "Warning: fallback value " << fall << " not found." << std::endl; return ""; } return it->second; From 9073e4d4baf1cf5116c4ab456a5a42ecc321fb01 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 21 Apr 2018 22:20:07 +0300 Subject: [PATCH 10/14] Initialize playlist file list in playPlaylist (fixes #4134) --- apps/openmw/mwsound/soundmanagerimp.cpp | 53 +++++++++++++------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index a798d350c..db02bb482 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -393,32 +393,8 @@ namespace MWSound void SoundManager::startRandomTitle() { - std::vector filelist; + const std::vector &filelist = mMusicFiles[mCurrentPlaylist]; auto &tracklist = mMusicToPlay[mCurrentPlaylist]; - if (mMusicFiles.find(mCurrentPlaylist) == mMusicFiles.end()) - { - const std::map& index = mVFS->getIndex(); - - std::string pattern = "Music/" + mCurrentPlaylist; - mVFS->normalizeFilename(pattern); - - std::map::const_iterator found = index.lower_bound(pattern); - while (found != index.end()) - { - if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern) - filelist.push_back(found->first); - else - break; - ++found; - } - - mMusicFiles[mCurrentPlaylist] = filelist; - } - else - filelist = mMusicFiles[mCurrentPlaylist]; - - if(filelist.empty()) - return; // Do a Fisher-Yates shuffle @@ -454,6 +430,33 @@ namespace MWSound void SoundManager::playPlaylist(const std::string &playlist) { + if (mCurrentPlaylist == playlist) + return; + + if (mMusicFiles.find(playlist) == mMusicFiles.end()) + { + std::vector filelist; + const std::map& index = mVFS->getIndex(); + + std::string pattern = "Music/" + playlist; + mVFS->normalizeFilename(pattern); + + std::map::const_iterator found = index.lower_bound(pattern); + while (found != index.end()) + { + if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern) + filelist.push_back(found->first); + else + break; + ++found; + } + + mMusicFiles[playlist] = filelist; + } + + if (mMusicFiles[playlist].empty()) + return; + mCurrentPlaylist = playlist; startRandomTitle(); } From 4cc65239ff1c33269a1e56c15038b02503af808e Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Wed, 25 Apr 2018 10:21:58 +0000 Subject: [PATCH 11/14] Add section on dealing with regressions --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4b2b4dfdd..4805bff3b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,6 +103,10 @@ To be able to merge PRs, commit priviledges are required. If you do not have the The person to merge the PR may either use github's Merge button or if using the command line, use the ```--no-ff``` flag (so a merge commit is created, just like with Github's merge button) and include the pull request number in the commit description. +Dealing with regressions +======================== + +The master branch should always be in a working state that is not worse than the previous release in any way. If a regression is found, the first and foremost priority should be to get the regression fixed quickly, either by reverting the change that caused it or finding a better solution. Please avoid leaving the project in the 'broken' state for an extensive period of time while proper solutions are found. If the solution takes more than a day or so then it is usually better to revert the offending change first and reapply it later when fixed. Other resources =============== From 66d510950914eae51634d615415502571415ae59 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Thu, 26 Apr 2018 21:56:14 +0300 Subject: [PATCH 12/14] [General] Fix information exchange for players sharing a cell Previously, two players entering the same cell only sent and received their latest changes for dynamic stats, attributes, skills and equipment when they started sharing that cell. --- .../player/ProcessorPlayerCellChange.hpp | 8 +++ components/openmw-mp/Base/BasePlayer.hpp | 3 ++ .../Packets/Player/PacketPlayerAttribute.cpp | 37 +++++++++----- .../Packets/Player/PacketPlayerEquipment.cpp | 50 +++++++++++++------ .../Packets/Player/PacketPlayerEquipment.hpp | 1 + .../Packets/Player/PacketPlayerSkill.cpp | 35 ++++++++----- .../Player/PacketPlayerStatsDynamic.cpp | 35 ++++++++----- 7 files changed, 115 insertions(+), 54 deletions(-) diff --git a/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp b/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp index 5122c84c1..459ebc248 100644 --- a/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp +++ b/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp @@ -30,10 +30,14 @@ namespace mwmp { LOG_APPEND(Log::LOG_INFO, "- Moved to %s", player.cell.getDescription().c_str()); + player.exchangeFullInfo = true; + player.forEachLoaded([this](Player *pl, Player *other) { LOG_APPEND(Log::LOG_INFO, "- Started information exchange with %s", other->npc.mName.c_str()); + other->exchangeFullInfo = true; + playerController->GetPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(other); playerController->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(other); playerController->GetPacket(ID_PLAYER_POSITION)->setPlayer(other); @@ -64,6 +68,8 @@ namespace mwmp playerController->GetPacket(ID_PLAYER_ANIM_FLAGS)->Send(other->guid); playerController->GetPacket(ID_PLAYER_SHAPESHIFT)->Send(other->guid); + other->exchangeFullInfo = false; + LOG_APPEND(Log::LOG_INFO, "- Finished information exchange with %s", other->npc.mName.c_str()); }); @@ -75,6 +81,8 @@ namespace mwmp Script::Call(player.getId()); LOG_APPEND(Log::LOG_INFO, "- Finished processing ID_PLAYER_CELL_CHANGE", player.cell.getDescription().c_str()); + + player.exchangeFullInfo = false; } else LOG_APPEND(Log::LOG_INFO, "- Ignored because %s is dead", player.npc.mName.c_str()); diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 569e6d79c..65aebb05e 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -227,6 +227,7 @@ namespace mwmp spellbookChanges.action = 0; spellbookChanges.count = 0; + exchangeFullInfo = false; displayCreatureName = false; resetStats = false; enforcedLogLevel = -1; @@ -259,6 +260,8 @@ namespace mwmp // with the items themselves being stored in equipmentItems std::vector equipmentIndexChanges; + bool exchangeFullInfo; + InventoryChanges inventoryChanges; SpellbookChanges spellbookChanges; QuickKeyChanges quickKeyChanges; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp b/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp index e99e69d03..391fcf10e 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp @@ -13,23 +13,34 @@ void PacketPlayerAttribute::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - uint32_t count; - if (send) - count = static_cast(player->attributeIndexChanges.size()); + RW(player->exchangeFullInfo, send); - RW(count, send); - - if (!send) + if (player->exchangeFullInfo) { - player->attributeIndexChanges.clear(); - player->attributeIndexChanges.resize(count); + RW(player->creatureStats.mAttributes, send); + RW(player->npcStats.mSkillIncrease, send); } - - for (auto &&attributeIndex : player->attributeIndexChanges) + else { - RW(attributeIndex, send); + uint32_t count; + + if (send) + count = static_cast(player->attributeIndexChanges.size()); + + RW(count, send); + + if (!send) + { + player->attributeIndexChanges.clear(); + player->attributeIndexChanges.resize(count); + } + + for (auto &&attributeIndex : player->attributeIndexChanges) + { + RW(attributeIndex, send); - RW(player->creatureStats.mAttributes[attributeIndex], send); - RW(player->npcStats.mSkillIncrease[attributeIndex], send); + RW(player->creatureStats.mAttributes[attributeIndex], send); + RW(player->npcStats.mSkillIncrease[attributeIndex], send); + } } } diff --git a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp index 63d7a0b1f..c6f267935 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp @@ -1,4 +1,5 @@ #include "PacketPlayerEquipment.hpp" + #include using namespace mwmp; @@ -12,25 +13,42 @@ void PacketPlayerEquipment::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - uint32_t count; - if (send) - count = static_cast(player->equipmentIndexChanges.size()); - - RW(count, send); + RW(player->exchangeFullInfo, send); - if (!send) + if (player->exchangeFullInfo) { - player->equipmentIndexChanges.clear(); - player->equipmentIndexChanges.resize(count); + for (auto &&equipmentItem : player->equipmentItems) + { + ExchangeItemInformation(equipmentItem, send); + } } - - for (auto &&equipmentIndex : player->equipmentIndexChanges) + else { - RW(equipmentIndex, send); - - RW(player->equipmentItems[equipmentIndex].refId, send); - RW(player->equipmentItems[equipmentIndex].count, send); - RW(player->equipmentItems[equipmentIndex].charge, send); - RW(player->equipmentItems[equipmentIndex].enchantmentCharge, send); + uint32_t count; + if (send) + count = static_cast(player->equipmentIndexChanges.size()); + + RW(count, send); + + if (!send) + { + player->equipmentIndexChanges.clear(); + player->equipmentIndexChanges.resize(count); + } + + for (auto &&equipmentIndex : player->equipmentIndexChanges) + { + RW(equipmentIndex, send); + ExchangeItemInformation(player->equipmentItems[equipmentIndex], send); + } } } + +void PacketPlayerEquipment::ExchangeItemInformation(Item &item, bool send) +{ + RW(item.refId, send); + RW(item.count, send); + RW(item.charge, send); + RW(item.enchantmentCharge, send); +} + diff --git a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp index c204f8579..49579c8f4 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp @@ -15,6 +15,7 @@ namespace mwmp PacketPlayerEquipment(RakNet::RakPeerInterface *peer); virtual void Packet(RakNet::BitStream *bs, bool send); + void ExchangeItemInformation(Item &item, bool send); }; } diff --git a/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp b/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp index 157506074..0978e1797 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp @@ -14,22 +14,31 @@ void PacketPlayerSkill::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - uint32_t count; + RW(player->exchangeFullInfo, send); - if (send) - count = static_cast(player->skillIndexChanges.size()); - - RW(count, send); - - if (!send) + if (player->exchangeFullInfo) { - player->skillIndexChanges.clear(); - player->skillIndexChanges.resize(count); + RW(player->npcStats.mSkills, send); } - - for (auto &&skillId : player->skillIndexChanges) + else { - RW(skillId, send); - RW(player->npcStats.mSkills[skillId], send); + uint32_t count; + + if (send) + count = static_cast(player->skillIndexChanges.size()); + + RW(count, send); + + if (!send) + { + player->skillIndexChanges.clear(); + player->skillIndexChanges.resize(count); + } + + for (auto &&skillId : player->skillIndexChanges) + { + RW(skillId, send); + RW(player->npcStats.mSkills[skillId], send); + } } } diff --git a/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp b/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp index 97b1fe589..b83a75e9c 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp @@ -1,4 +1,5 @@ #include "PacketPlayerStatsDynamic.hpp" + #include using namespace mwmp; @@ -12,22 +13,32 @@ void PacketPlayerStatsDynamic::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - uint32_t count; - if (send) - count = static_cast(player->statsDynamicIndexChanges.size()); - - RW(count, send); + RW(player->exchangeFullInfo, send); - if (!send) + if (player->exchangeFullInfo) { - player->statsDynamicIndexChanges.clear(); - player->statsDynamicIndexChanges.resize(count); + RW(player->creatureStats.mDynamic, send); } - - for (auto &&statsDynamicIndex : player->statsDynamicIndexChanges) + else { - RW(statsDynamicIndex, send); + uint32_t count; + + if (send) + count = static_cast(player->statsDynamicIndexChanges.size()); + + RW(count, send); + + if (!send) + { + player->statsDynamicIndexChanges.clear(); + player->statsDynamicIndexChanges.resize(count); + } + + for (auto &&statsDynamicIndex : player->statsDynamicIndexChanges) + { + RW(statsDynamicIndex, send); - RW(player->creatureStats.mDynamic[statsDynamicIndex], send); + RW(player->creatureStats.mDynamic[statsDynamicIndex], send); + } } } From 399e049d87a0712c2baa4469d9ce799687b5b072 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Fri, 27 Apr 2018 03:45:17 +0300 Subject: [PATCH 13/14] [Client] Fix logic for minimal size packets in LocalPlayer Previously, the index changes were not cleared at the start of their corresponding update functions, which in turn meant that an Attribute/Skill/StatsDynamic/Equipment packet received by a player from the server made that player send back the same packet, as the index changes from it were retained. Additionally, exchangeFullInfo was not set to false, thus sometimes leading to constant full exchanges of information. --- apps/openmw/mwmp/LocalPlayer.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index dd1e0515a..e47cea911 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -194,6 +194,9 @@ bool LocalPlayer::hasFinishedCharGen() void LocalPlayer::updateStatsDynamic(bool forceUpdate) { + if (statsDynamicIndexChanges.size() > 0) + statsDynamicIndexChanges.clear(); + MWWorld::Ptr ptrPlayer = getPlayerPtr(); MWMechanics::CreatureStats *ptrCreatureStats = &ptrPlayer.getClass().getCreatureStats(ptrPlayer); @@ -231,9 +234,9 @@ void LocalPlayer::updateStatsDynamic(bool forceUpdate) magicka.writeState(creatureStats.mDynamic[1]); fatigue.writeState(creatureStats.mDynamic[2]); + exchangeFullInfo = false; getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(this); getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->Send(); - statsDynamicIndexChanges.clear(); } } @@ -243,6 +246,9 @@ void LocalPlayer::updateAttributes(bool forceUpdate) // overwritten by the werewolf ones if (isWerewolf) return; + if (attributeIndexChanges.size() > 0) + attributeIndexChanges.clear(); + MWWorld::Ptr ptrPlayer = getPlayerPtr(); const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer); @@ -261,9 +267,9 @@ void LocalPlayer::updateAttributes(bool forceUpdate) if (attributeIndexChanges.size() > 0) { + exchangeFullInfo = false; getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(this); getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->Send(); - attributeIndexChanges.clear(); } } @@ -273,6 +279,9 @@ void LocalPlayer::updateSkills(bool forceUpdate) // overwritten by the werewolf ones if (isWerewolf) return; + if (skillIndexChanges.size() > 0) + skillIndexChanges.clear(); + MWWorld::Ptr ptrPlayer = getPlayerPtr(); const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer); @@ -291,9 +300,9 @@ void LocalPlayer::updateSkills(bool forceUpdate) if (skillIndexChanges.size() > 0) { + exchangeFullInfo = false; getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->setPlayer(this); getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->Send(); - skillIndexChanges.clear(); } } @@ -432,6 +441,9 @@ void LocalPlayer::updateCell(bool forceUpdate) void LocalPlayer::updateEquipment(bool forceUpdate) { + if (equipmentIndexChanges.size() > 0) + equipmentIndexChanges.clear(); + MWWorld::Ptr ptrPlayer = getPlayerPtr(); MWWorld::InventoryStore &invStore = ptrPlayer.getClass().getInventoryStore(ptrPlayer); @@ -464,9 +476,9 @@ void LocalPlayer::updateEquipment(bool forceUpdate) if (equipmentIndexChanges.size() > 0) { + exchangeFullInfo = false; getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->setPlayer(this); getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->Send(); - equipmentIndexChanges.clear(); } } From 3b07dc4b4272b7ac94698fb196864d77c1080320 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 29 Apr 2018 05:40:42 +0300 Subject: [PATCH 14/14] [Client] Send equipment packets whenever an item charge or count changes Since the beginnings of TES3MP, equipment packets have only been sent whenever an item has been replaced by an item with a different refId, with changes in an item's charge or count not sending a packet (but being included in the next packet sent as a result of a refId change). The reason for this was ostensibly the fact that every single equipment packet always included the details for all 19 equipment items (as per Koncord's original design decision), which would have led to massive packet spam if such a packet was sent every time you shot an arrow or lost a little bit of your armor's condition. With minimalist equipment packets, it is now viable to send equipment packets whenever any item changes in some way, by having the equipment packet contain only that one item. --- apps/openmw/mwmp/LocalPlayer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index e47cea911..1e07fc203 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -454,7 +454,11 @@ void LocalPlayer::updateEquipment(bool forceUpdate) if (it != invStore.end()) { - if (!::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), equipmentItems[slot].refId) || forceUpdate) + if (!::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), equipmentItems[slot].refId) || + it->getCellRef().getCharge() != item.charge || + it->getCellRef().getEnchantmentCharge() != item.enchantmentCharge || + it->getRefData().getCount() != item.count || + forceUpdate) { equipmentIndexChanges.push_back(slot);