From dcc3fb80ba819b1d06cf968f247b0d44547bbc5e Mon Sep 17 00:00:00 2001 From: Matthew Read Date: Wed, 29 May 2024 23:21:10 +0200 Subject: [PATCH 1/3] add arcdps self and squad update events --- src/entry.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 9 deletions(-) diff --git a/src/entry.cpp b/src/entry.cpp index 58a9f00..5b41f29 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "nexus/Nexus.h" #include "ArcDPS.h" @@ -30,6 +32,21 @@ struct EvCombatData uint64_t revision; }; +struct EvAgentUpdateData // when ev is null +{ + char account[64] = ""; // dst->name = account name + char character[64] = ""; // src->name = character name + uintptr_t id; // src->id = agent id + uintptr_t instanceId; // dst->id = instance id (per map) + uint32_t added; // src->prof = is new agent + uint32_t target; // src->elite = is new targeted agent + uint32_t self; // dst->self = is self + uint32_t prof; // dst->prof = profession / core spec + uint32_t elite; // dst->elite = elite spec + uint16_t team; // src->team = team + uint16_t subgroup; // dst->team = subgroup +}; + /* proto / globals */ void AddonLoad(AddonAPI* aApi); void AddonUnload(); @@ -37,6 +54,9 @@ void AddonUnload(); AddonDefinition AddonDef = {}; AddonAPI* APIDefs = nullptr; +std::mutex Mutex; +EvAgentUpdateData evSelfAgentData; + arcdps_exports arc_exports = {}; uint32_t cbtcount = 0; extern "C" __declspec(dllexport) void* get_init_addr(char* arcversion, void* imguictx, void* id3dptr, HANDLE arcdll, void* mallocfn, void* freefn, uint32_t d3dversion); @@ -65,13 +85,23 @@ extern "C" __declspec(dllexport) AddonDefinition* GetAddonDef() return &AddonDef; } +void SelfRequestHandler(void* eventArgs) { + std::scoped_lock lck(Mutex); + if (evSelfAgentData.id == NULL) return; + std::thread([&]() { + APIDefs->RaiseEvent("EV_ARCDPS_SELF_UPDATE", (void*)&evSelfAgentData); + }).detach(); +} + void AddonLoad(AddonAPI* aApi) { APIDefs = aApi; + APIDefs->SubscribeEvent("EV_ARCDPS_SELF_REQUEST", SelfRequestHandler); } void AddonUnload() { + APIDefs->UnsubscribeEvent("EV_ARCDPS_SELF_UPDATE", SelfRequestHandler); return; } @@ -115,6 +145,7 @@ uintptr_t mod_combat_local(cbtevent* ev, ag* src, ag* dst, char* skillname, uint uintptr_t mod_combat(const char* channel, cbtevent* ev, ag* src, ag* dst, char* skillname, uint64_t id, uint64_t revision) { + if (APIDefs == nullptr) return 0; EvCombatData evCbtData { ev, @@ -125,18 +156,60 @@ uintptr_t mod_combat(const char* channel, cbtevent* ev, ag* src, ag* dst, char* revision }; - if (APIDefs != nullptr) + if (strcmp(channel, "squad") == 0) + { + APIDefs->RaiseEvent("EV_ARCDPS_COMBATEVENT_SQUAD_RAW", &evCbtData); + } + else { - if (strcmp(channel, "local") == 0) - { - APIDefs->RaiseEvent("EV_ARCDPS_COMBATEVENT_LOCAL_RAW", &evCbtData); - } - else - { - APIDefs->RaiseEvent("EV_ARCDPS_COMBATEVENT_SQUAD_RAW", &evCbtData); - } + APIDefs->RaiseEvent("EV_ARCDPS_COMBATEVENT_LOCAL_RAW", &evCbtData); } + if (evCbtData.ev) return 0; + EvAgentUpdateData evAgentUpdateData { + "", + "", + evCbtData.src->id, + evCbtData.dst->id, + evCbtData.src->prof, + evCbtData.src->elite, + evCbtData.dst->self, + evCbtData.dst->prof, + evCbtData.dst->elite, + evCbtData.src->team, + evCbtData.dst->team + }; + strcpy_s(evAgentUpdateData.account, evCbtData.dst->name); + strcpy_s(evAgentUpdateData.character, evCbtData.src->name); + + /*APIDefs->Log(ELogLevel_DEBUG, "Nexus Arcdps Bridge", std::format( + "new agent event via {} channel. id: {}, instanceId: {}, account: {}, added: {}, target: {}, self: {}, prof: {}, elite: {}, team: {}, subgroup: {}", + channel, evAgentUpdateData.id, evAgentUpdateData.instanceId, evAgentUpdateData.account, evAgentUpdateData.added, evAgentUpdateData.target, + evAgentUpdateData.self, evAgentUpdateData.prof, evAgentUpdateData.elite, evAgentUpdateData.team, evAgentUpdateData.subgroup + ).c_str());*/ + + if (!evAgentUpdateData.added) + { + APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_UPDATE", &evAgentUpdateData); + return 0; + } + + if (evAgentUpdateData.account == nullptr || evAgentUpdateData.account[0] == '\0' || + evAgentUpdateData.character == nullptr || evAgentUpdateData.character[0] == '\0') return 0; + + if (!evAgentUpdateData.self) { + APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_UPDATE", &evAgentUpdateData); + return 0; + } + + { + std::scoped_lock lck(Mutex); + evSelfAgentData = evAgentUpdateData; + strcpy_s(evSelfAgentData.account, evAgentUpdateData.account); + strcpy_s(evSelfAgentData.character, evAgentUpdateData.character); + APIDefs->RaiseEvent("EV_ARCDPS_SELF_UPDATE", (void*)&evSelfAgentData); + } + return 0; } From 0548e621b96b0d177111230dc60a966b9ee83f1d Mon Sep 17 00:00:00 2001 From: Matthew Read Date: Thu, 30 May 2024 22:13:39 +0200 Subject: [PATCH 2/3] split arc agent updates to different events --- src/entry.cpp | 152 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 60 deletions(-) diff --git a/src/entry.cpp b/src/entry.cpp index 5b41f29..40bb3b4 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -32,19 +32,19 @@ struct EvCombatData uint64_t revision; }; -struct EvAgentUpdateData // when ev is null +struct EvAgentUpdate // when ev is null { - char account[64] = ""; // dst->name = account name - char character[64] = ""; // src->name = character name - uintptr_t id; // src->id = agent id - uintptr_t instanceId; // dst->id = instance id (per map) - uint32_t added; // src->prof = is new agent - uint32_t target; // src->elite = is new targeted agent - uint32_t self; // dst->self = is self - uint32_t prof; // dst->prof = profession / core spec - uint32_t elite; // dst->elite = elite spec - uint16_t team; // src->team = team - uint16_t subgroup; // dst->team = subgroup + char account[64] = ""; // dst->name = account name + char character[64] = ""; // src->name = character name + uintptr_t id = 0; // src->id = agent id + uintptr_t instanceId = 0; // dst->id = instance id (per map) + uint32_t added = 0; // src->prof = is new agent + uint32_t target = 0; // src->elite = is new targeted agent + uint32_t self = 0; // dst->self = is self + uint32_t prof = 0; // dst->prof = profession / core spec + uint32_t elite = 0; // dst->elite = elite spec + uint16_t team = 0ui16; // src->team = team + uint16_t subgroup = 0ui16; // dst->team = subgroup }; /* proto / globals */ @@ -55,7 +55,7 @@ AddonDefinition AddonDef = {}; AddonAPI* APIDefs = nullptr; std::mutex Mutex; -EvAgentUpdateData evSelfAgentData; +EvAgentUpdate self; arcdps_exports arc_exports = {}; uint32_t cbtcount = 0; @@ -87,9 +87,9 @@ extern "C" __declspec(dllexport) AddonDefinition* GetAddonDef() void SelfRequestHandler(void* eventArgs) { std::scoped_lock lck(Mutex); - if (evSelfAgentData.id == NULL) return; + if (self.id == NULL) return; std::thread([&]() { - APIDefs->RaiseEvent("EV_ARCDPS_SELF_UPDATE", (void*)&evSelfAgentData); + APIDefs->RaiseEvent("EV_ARCDPS_SELF_DETECT", (void*)&self); }).detach(); } @@ -101,7 +101,7 @@ void AddonLoad(AddonAPI* aApi) void AddonUnload() { - APIDefs->UnsubscribeEvent("EV_ARCDPS_SELF_UPDATE", SelfRequestHandler); + APIDefs->UnsubscribeEvent("EV_ARCDPS_SELF_REQUEST", SelfRequestHandler); return; } @@ -133,6 +133,81 @@ uintptr_t mod_release() return 0; } +void mod_agent_update(EvCombatData* evCbtData) { + if (evCbtData->ev) return; + + EvAgentUpdate evAgentUpdate{ + "", + "", + evCbtData->src != nullptr ? evCbtData->src->id : 0, + evCbtData->dst != nullptr ? evCbtData->dst->id : 0, + evCbtData->src != nullptr ? evCbtData->src->prof : 0, + evCbtData->src != nullptr ? evCbtData->src->elite : 0, + evCbtData->dst != nullptr ? evCbtData->dst->self : 0, + evCbtData->dst != nullptr ? evCbtData->dst->prof : 0, + evCbtData->dst != nullptr ? evCbtData->dst->elite : 0, + evCbtData->src != nullptr ? evCbtData->src->team : 0ui16, + evCbtData->dst != nullptr ? evCbtData->dst->team : 0ui16, + }; + if (evCbtData->dst != nullptr && evCbtData->dst->name != nullptr && evCbtData->dst->name[0] != '\0') { + strcpy_s(evAgentUpdate.account, evCbtData->dst->name); + } + if (evCbtData->src != nullptr && evCbtData->src->name != nullptr && evCbtData->src->name[0] != '\0') { + strcpy_s(evAgentUpdate.character, evCbtData->src->name); + } + + if (evAgentUpdate.target) { + APIDefs->RaiseEvent("EV_ARCDPS_TARGET_CHANGED", &evAgentUpdate); + return; + } + + /*APIDefs->Log(ELogLevel_DEBUG, "Nexus Arcdps Bridge", std::format( + "new agent event with id: {}, instanceId: {}, account: {}, added: {}, target: {}, self: {}, prof: {}, elite: {}, team: {}, subgroup: {}", + evAgentUpdate.id, evAgentUpdate.instanceId, evAgentUpdate.account, evAgentUpdate.added, evAgentUpdate.target, + evAgentUpdate.self, evAgentUpdate.prof, evAgentUpdate.elite, evAgentUpdate.team, evAgentUpdate.subgroup + ).c_str());*/ + + if (!evAgentUpdate.added) + { + std::scoped_lock lck(Mutex); + if (self.id != 0 && self.id == evAgentUpdate.id) { + // override values to make life easier + strcpy_s(evAgentUpdate.account, self.account); + strcpy_s(evAgentUpdate.character, self.character); + evAgentUpdate.self = 1; + APIDefs->RaiseEvent("EV_ARCDPS_SELF_LEAVE", &evAgentUpdate); + } + else { + // TODO: cache them all and add names to each leave event + APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_LEAVE", &evAgentUpdate); + } + return; + } + + if (evAgentUpdate.account == 0 || evAgentUpdate.character == 0) return; + + if (!evAgentUpdate.self) { + APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_JOIN", &evAgentUpdate); + return; + } + + { + std::scoped_lock lck(Mutex); + self.id = evAgentUpdate.id; + self.instanceId = evAgentUpdate.instanceId; + self.added = evAgentUpdate.added; + self.target = evAgentUpdate.target; + self.self = evAgentUpdate.self; + self.prof = evAgentUpdate.prof; + self.elite = evAgentUpdate.elite; + self.team = evAgentUpdate.team; + self.subgroup = evAgentUpdate.subgroup; + strcpy_s(self.account, evAgentUpdate.account); + strcpy_s(self.character, evAgentUpdate.character); + APIDefs->RaiseEvent("EV_ARCDPS_SELF_DETECT", (void*)&self); + } +} + uintptr_t mod_combat_squad(cbtevent* ev, ag* src, ag* dst, char* skillname, uint64_t id, uint64_t revision) { return mod_combat("squad", ev, src, dst, skillname, id, revision); @@ -165,50 +240,7 @@ uintptr_t mod_combat(const char* channel, cbtevent* ev, ag* src, ag* dst, char* APIDefs->RaiseEvent("EV_ARCDPS_COMBATEVENT_LOCAL_RAW", &evCbtData); } - if (evCbtData.ev) return 0; - EvAgentUpdateData evAgentUpdateData { - "", - "", - evCbtData.src->id, - evCbtData.dst->id, - evCbtData.src->prof, - evCbtData.src->elite, - evCbtData.dst->self, - evCbtData.dst->prof, - evCbtData.dst->elite, - evCbtData.src->team, - evCbtData.dst->team - }; - strcpy_s(evAgentUpdateData.account, evCbtData.dst->name); - strcpy_s(evAgentUpdateData.character, evCbtData.src->name); - - /*APIDefs->Log(ELogLevel_DEBUG, "Nexus Arcdps Bridge", std::format( - "new agent event via {} channel. id: {}, instanceId: {}, account: {}, added: {}, target: {}, self: {}, prof: {}, elite: {}, team: {}, subgroup: {}", - channel, evAgentUpdateData.id, evAgentUpdateData.instanceId, evAgentUpdateData.account, evAgentUpdateData.added, evAgentUpdateData.target, - evAgentUpdateData.self, evAgentUpdateData.prof, evAgentUpdateData.elite, evAgentUpdateData.team, evAgentUpdateData.subgroup - ).c_str());*/ - - if (!evAgentUpdateData.added) - { - APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_UPDATE", &evAgentUpdateData); - return 0; - } - - if (evAgentUpdateData.account == nullptr || evAgentUpdateData.account[0] == '\0' || - evAgentUpdateData.character == nullptr || evAgentUpdateData.character[0] == '\0') return 0; - - if (!evAgentUpdateData.self) { - APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_UPDATE", &evAgentUpdateData); - return 0; - } - - { - std::scoped_lock lck(Mutex); - evSelfAgentData = evAgentUpdateData; - strcpy_s(evSelfAgentData.account, evAgentUpdateData.account); - strcpy_s(evSelfAgentData.character, evAgentUpdateData.character); - APIDefs->RaiseEvent("EV_ARCDPS_SELF_UPDATE", (void*)&evSelfAgentData); - } + mod_agent_update(&evCbtData); return 0; } From 5024ec6ee6739e1353e55751cb21101268176775 Mon Sep 17 00:00:00 2001 From: Matthew Read Date: Fri, 31 May 2024 00:26:59 +0200 Subject: [PATCH 3/3] cache arcdps squad members and last target --- src/entry.cpp | 66 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/entry.cpp b/src/entry.cpp index 40bb3b4..29a01be 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "nexus/Nexus.h" #include "ArcDPS.h" @@ -56,6 +57,8 @@ AddonAPI* APIDefs = nullptr; std::mutex Mutex; EvAgentUpdate self; +EvAgentUpdate lastTarget; +std::vector squad; arcdps_exports arc_exports = {}; uint32_t cbtcount = 0; @@ -89,19 +92,41 @@ void SelfRequestHandler(void* eventArgs) { std::scoped_lock lck(Mutex); if (self.id == NULL) return; std::thread([&]() { - APIDefs->RaiseEvent("EV_ARCDPS_SELF_DETECT", (void*)&self); + APIDefs->RaiseEvent("EV_ARCDPS_SELF_JOIN", (void*)&self); }).detach(); } +void SquadRequestHandler(void* eventArgs) { + std::scoped_lock lck(Mutex); + if (!squad.size()) return; + std::thread([&]() { + for (EvAgentUpdate &member : squad) { + APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_JOIN", (void*)&member); + } + }).detach(); +} + +void TargetRequestHandler(void* eventArgs) { + std::scoped_lock lck(Mutex); + if (lastTarget.id == NULL) return; + std::thread([&]() { + APIDefs->RaiseEvent("EV_ARCDPS_TARGET_CHANGED", (void*)&lastTarget); + }).detach(); +} + void AddonLoad(AddonAPI* aApi) { APIDefs = aApi; - APIDefs->SubscribeEvent("EV_ARCDPS_SELF_REQUEST", SelfRequestHandler); + APIDefs->SubscribeEvent("EV_REPLAY_ARCDPS_SELF_JOIN", SelfRequestHandler); + APIDefs->SubscribeEvent("EV_REPLAY_ARCDPS_SQUAD_JOIN", SquadRequestHandler); + APIDefs->SubscribeEvent("EV_REPLAY_ARCDPS_TARGET_CHANGED", TargetRequestHandler); } void AddonUnload() { - APIDefs->UnsubscribeEvent("EV_ARCDPS_SELF_REQUEST", SelfRequestHandler); + APIDefs->UnsubscribeEvent("EV_REPLAY_ARCDPS_SELF_JOIN", SelfRequestHandler); + APIDefs->UnsubscribeEvent("EV_REPLAY_ARCDPS_SQUAD_JOIN", SquadRequestHandler); + APIDefs->UnsubscribeEvent("EV_REPLAY_ARCDPS_TARGET_CHANGED", TargetRequestHandler); return; } @@ -157,6 +182,8 @@ void mod_agent_update(EvCombatData* evCbtData) { } if (evAgentUpdate.target) { + std::scoped_lock lck(Mutex); + lastTarget = evAgentUpdate; APIDefs->RaiseEvent("EV_ARCDPS_TARGET_CHANGED", &evAgentUpdate); return; } @@ -171,15 +198,26 @@ void mod_agent_update(EvCombatData* evCbtData) { { std::scoped_lock lck(Mutex); if (self.id != 0 && self.id == evAgentUpdate.id) { - // override values to make life easier strcpy_s(evAgentUpdate.account, self.account); strcpy_s(evAgentUpdate.character, self.character); evAgentUpdate.self = 1; + squad.clear(); APIDefs->RaiseEvent("EV_ARCDPS_SELF_LEAVE", &evAgentUpdate); } else { - // TODO: cache them all and add names to each leave event - APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_LEAVE", &evAgentUpdate); + squad.erase(std::remove_if( + squad.begin(), squad.end(), + [&](EvAgentUpdate const &member) { + if (member.id == evAgentUpdate.id) { + strcpy_s(evAgentUpdate.account, member.account); + strcpy_s(evAgentUpdate.character, member.character); + APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_LEAVE", &evAgentUpdate); + return true; + } + return false; + }), + squad.end() + ); } return; } @@ -187,24 +225,16 @@ void mod_agent_update(EvCombatData* evCbtData) { if (evAgentUpdate.account == 0 || evAgentUpdate.character == 0) return; if (!evAgentUpdate.self) { + std::scoped_lock lck(Mutex); + squad.push_back(evAgentUpdate); APIDefs->RaiseEvent("EV_ARCDPS_SQUAD_JOIN", &evAgentUpdate); return; } { std::scoped_lock lck(Mutex); - self.id = evAgentUpdate.id; - self.instanceId = evAgentUpdate.instanceId; - self.added = evAgentUpdate.added; - self.target = evAgentUpdate.target; - self.self = evAgentUpdate.self; - self.prof = evAgentUpdate.prof; - self.elite = evAgentUpdate.elite; - self.team = evAgentUpdate.team; - self.subgroup = evAgentUpdate.subgroup; - strcpy_s(self.account, evAgentUpdate.account); - strcpy_s(self.character, evAgentUpdate.character); - APIDefs->RaiseEvent("EV_ARCDPS_SELF_DETECT", (void*)&self); + self = evAgentUpdate; + APIDefs->RaiseEvent("EV_ARCDPS_SELF_JOIN", (void*)&self); } }