Skip to content

Commit

Permalink
Lock PCLevelMultManager map
Browse files Browse the repository at this point in the history
  • Loading branch information
powerof3 committed Nov 13, 2022
1 parent 7c78f65 commit a549080
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 16 deletions.
2 changes: 1 addition & 1 deletion SPID/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
set(NAME "po3_SpellPerkItemDistributor" CACHE STRING "")
set(VERSION 6.0.3 CACHE STRING "")
set(VERSION 6.1.0 CACHE STRING "")
set(AE_VERSION 1)
set(VR_VERSION 1)

Expand Down
1 change: 1 addition & 0 deletions SPID/include/PCH.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define NOMINMAX

#include <ranges>
#include <shared_mutex>

#include "RE/Skyrim.h"
#include "SKSE/SKSE.h"
Expand Down
8 changes: 6 additions & 2 deletions SPID/include/PCLevelMultManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,13 @@ namespace PCLevelMult
Map<std::uint16_t, Entries> entries{}; // Actor Level, Entries
};

Map<std::uint64_t, // PlayerID
using Lock = std::shared_mutex;
using Locker = std::lock_guard<Lock>;

Map<std::uint64_t, // PlayerID
Map<RE::FormID, Data>> // NPC formID, Data
cache{};
_cache{};
mutable Lock _lock;

std::uint64_t currentPlayerID{ 0 };
std::uint64_t oldPlayerID{ 0 };
Expand Down
35 changes: 23 additions & 12 deletions SPID/src/PCLevelMultManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ namespace PCLevelMult
return false;
}

if (const auto idIt = cache.find(a_input.playerID); idIt != cache.end()) {
Locker lock(_lock);
if (const auto idIt = _cache.find(a_input.playerID); idIt != _cache.end()) {
auto& npcFormIDMap = idIt->second;
if (const auto npcIt = npcFormIDMap.find(a_input.npcFormID); npcIt != npcFormIDMap.end()) {
auto& [levelCapState, levelMap] = npcIt->second;
Expand All @@ -86,7 +87,8 @@ namespace PCLevelMult
return false;
}

return cache[a_input.playerID]
Locker lock(_lock);
return _cache[a_input.playerID]
[a_input.npcFormID]
.entries[a_input.npcLevel]
.rejectedEntries[a_distributedFormID]
Expand All @@ -96,7 +98,8 @@ namespace PCLevelMult

void Manager::DumpRejectedEntries()
{
for (auto& [playerID, npcFormIDs] : cache) {
Locker lock(_lock);
for (auto& [playerID, npcFormIDs] : _cache) {
logger::info("PlayerID : {:X}", playerID);
for (auto& [npcFormID, levelMap] : npcFormIDs) {
logger::info("\tNPC : {} [{:X}]", Cache::EditorID::GetEditorID(npcFormID), npcFormID);
Expand All @@ -115,7 +118,8 @@ namespace PCLevelMult

bool Manager::FindDistributedEntry(const Input& a_input)
{
if (const auto it = cache.find(a_input.playerID); it != cache.end()) {
Locker lock(_lock);
if (const auto it = _cache.find(a_input.playerID); it != _cache.end()) {
if (const auto npcIt = it->second.find(a_input.npcFormID); npcIt != it->second.end()) {
return !npcIt->second.entries.empty();
}
Expand All @@ -129,7 +133,8 @@ namespace PCLevelMult
return;
}

cache[a_input.playerID][a_input.npcFormID].entries[a_input.npcLevel].distributedEntries.push_back({ a_distributedFormID, a_idx });
Locker lock(_lock);
_cache[a_input.playerID][a_input.npcFormID].entries[a_input.npcLevel].distributedEntries.push_back({ a_distributedFormID, a_idx });
}

void Manager::ForEachDistributedEntry(const Input& a_input, std::function<void(RE::TESForm&, IdxOrCount a_idx, bool)> a_fn) const
Expand All @@ -138,7 +143,8 @@ namespace PCLevelMult
return;
}

if (const auto idIt = cache.find(a_input.playerID); idIt != cache.end()) {
Locker lock(_lock);
if (const auto idIt = _cache.find(a_input.playerID); idIt != _cache.end()) {
auto& npcFormIDMap = idIt->second;
if (const auto npcIt = npcFormIDMap.find(a_input.npcFormID); npcIt != npcFormIDMap.end()) {
auto& [levelCapState, levelMap] = npcIt->second;
Expand All @@ -156,7 +162,8 @@ namespace PCLevelMult

void Manager::DumpDistributedEntries()
{
for (auto& [playerID, npcFormIDs] : cache) {
Locker lock(_lock);
for (auto& [playerID, npcFormIDs] : _cache) {
logger::info("PlayerID : {:X}", playerID);
for (auto& [npcFormID, levelMap] : npcFormIDs) {
logger::info("\tNPC : {} [{:X}]", Cache::EditorID::GetEditorID(npcFormID), npcFormID);
Expand All @@ -173,7 +180,8 @@ namespace PCLevelMult
// For spawned actors with FF reference IDs
void Manager::DeleteNPC(RE::FormID a_characterID)
{
auto& currentCache = cache[GetSingleton()->GetCurrentPlayerID()];
Locker lock(_lock);
auto& currentCache = _cache[GetSingleton()->GetCurrentPlayerID()];
if (const auto it = currentCache.find(a_characterID); it != currentCache.end()) {
currentCache.erase(it);
}
Expand All @@ -183,7 +191,9 @@ namespace PCLevelMult
{
bool hitCap = (a_input.npcLevel == a_input.npcLevelCap);

auto& map = cache[a_input.playerID];
Locker lock(_lock);

auto& map = _cache[a_input.playerID];
if (const auto it = map.find(a_input.npcFormID); it == map.end()) {
map[a_input.npcFormID].levelCapState = static_cast<LEVEL_CAP_STATE>(hitCap);
} else {
Expand Down Expand Up @@ -235,9 +245,10 @@ namespace PCLevelMult

void Manager::remap_player_ids(std::uint64_t a_oldID, std::uint64_t a_newID)
{
if (!cache.contains(a_newID)) {
if (const auto it = cache.find(a_oldID); it != cache.end()) {
cache[a_newID] = it->second;
Locker lock(_lock);
if (!_cache.contains(a_newID)) {
if (const auto it = _cache.find(a_oldID); it != _cache.end()) {
_cache[a_newID] = it->second;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion SPID/vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "spid",
"version-string": "6.0.3",
"version-string": "6.1.0",
"description": "Spell Perk Item Distributor",
"homepage": "https://github.com/powerof3/Spell-Perk-Item-Distributor",
"license": "MIT",
Expand Down

0 comments on commit a549080

Please sign in to comment.