From f8826d647b2db130203712c1daa908c0a5e46da5 Mon Sep 17 00:00:00 2001 From: dannuic Date: Thu, 4 Jan 2024 18:04:58 -0700 Subject: [PATCH] Added actors to meshgen --- MQ2Nav.sln | 11 ++++ common/MQ2Nav_Common.vcxproj | 3 + common/MQ2Nav_Common.vcxproj.filters | 9 +++ common/proto/NavMeshClient.proto | 28 +++++++++ meshgen/Actor.cpp | 90 +++++++++++++++++++++++++++ meshgen/Application.cpp | 46 ++++++++++++++ meshgen/Application.h | 25 ++++++++ meshgen/MeshGenerator.vcxproj | 4 ++ meshgen/MeshGenerator.vcxproj.filters | 3 + plugin/MQ2Nav.vcxproj | 2 + plugin/MQ2Nav.vcxproj.filters | 6 ++ plugin/MQ2Navigation.cpp | 2 + plugin/MeshgenHandler.cpp | 86 +++++++++++++++++++++++++ plugin/MeshgenHandler.h | 23 +++++++ 14 files changed, 338 insertions(+) create mode 100644 common/proto/NavMeshClient.proto create mode 100644 meshgen/Actor.cpp create mode 100644 plugin/MeshgenHandler.cpp create mode 100644 plugin/MeshgenHandler.h diff --git a/MQ2Nav.sln b/MQ2Nav.sln index bcbdbd19..70eb888d 100644 --- a/MQ2Nav.sln +++ b/MQ2Nav.sln @@ -20,6 +20,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui", "..\..\src\imgui\im EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zone-utilities", "dependencies\zone-utilities\zone-utilities.vcxproj", "{200FB60C-6C01-48A7-886A-8E3683EB21BC}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "routing", "..\..\src\routing\routing.vcxproj", "{6CE4F8D6-1709-47C5-9297-1619BBC4A71E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -80,6 +82,14 @@ Global {200FB60C-6C01-48A7-886A-8E3683EB21BC}.Release|Win32.Build.0 = Release|Win32 {200FB60C-6C01-48A7-886A-8E3683EB21BC}.Release|x64.ActiveCfg = Release|x64 {200FB60C-6C01-48A7-886A-8E3683EB21BC}.Release|x64.Build.0 = Release|x64 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Debug|Win32.ActiveCfg = Debug|Win32 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Debug|Win32.Build.0 = Debug|Win32 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Debug|x64.ActiveCfg = Debug|x64 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Debug|x64.Build.0 = Debug|x64 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Release|Win32.ActiveCfg = Release|Win32 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Release|Win32.Build.0 = Release|Win32 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Release|x64.ActiveCfg = Release|x64 + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -93,6 +103,7 @@ Global {A219F273-6B9D-4284-84F4-368539F0A9CF} = {1C00A77D-99DC-4366-8569-E75827AAF729} {1777E251-0F50-496A-B8C5-EC7F41A0B186} = {2884B755-835B-49DA-9E3F-E34AD401A5B9} {200FB60C-6C01-48A7-886A-8E3683EB21BC} = {2884B755-835B-49DA-9E3F-E34AD401A5B9} + {6CE4F8D6-1709-47C5-9297-1619BBC4A71E} = {2884B755-835B-49DA-9E3F-E34AD401A5B9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1498B1E1-4805-4819-A304-0BE8FDA62FD8} diff --git a/common/MQ2Nav_Common.vcxproj b/common/MQ2Nav_Common.vcxproj index 82bdcba0..e755fdda 100644 --- a/common/MQ2Nav_Common.vcxproj +++ b/common/MQ2Nav_Common.vcxproj @@ -145,6 +145,7 @@ + @@ -154,6 +155,7 @@ + 4244;4256 @@ -161,6 +163,7 @@ + Document diff --git a/common/MQ2Nav_Common.vcxproj.filters b/common/MQ2Nav_Common.vcxproj.filters index 877d0699..3c916cb5 100644 --- a/common/MQ2Nav_Common.vcxproj.filters +++ b/common/MQ2Nav_Common.vcxproj.filters @@ -51,6 +51,9 @@ Header Files + + Proto Files\Generated Files + @@ -74,11 +77,17 @@ Source Files + + Proto Files\Generated Files + Proto Files + + Proto Files + diff --git a/common/proto/NavMeshClient.proto b/common/proto/NavMeshClient.proto new file mode 100644 index 00000000..05fa6878 --- /dev/null +++ b/common/proto/NavMeshClient.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; + +package nav.client; + +import "NavMeshFile.proto"; + +message UpdateTransform +{ + string shortzone = 1; + nav.vector3 position = 2; + float heading = 3; + + string character_info = 10; +} + +message DropClient +{ + string character_info = 1; +} + +message ClientMessage +{ + oneof message + { + UpdateTransform transform = 1; + DropClient drop = 2; + } +} diff --git a/meshgen/Actor.cpp b/meshgen/Actor.cpp new file mode 100644 index 00000000..c5e32554 --- /dev/null +++ b/meshgen/Actor.cpp @@ -0,0 +1,90 @@ +// +// Actor.cpp +// + +#include "Application.h" + +#include "routing/Routing.h" +#include "common/proto/NavMeshClient.pb.h" + +using namespace mq; + +mq::ProtoPipeClient* s_pipeClient = nullptr; // { mq::MQ2_PIPE_SERVER_PATH }; + +class PipeEventsHandler : public NamedPipeEvents +{ +public: + PipeEventsHandler() {} + + virtual void OnIncomingMessage(PipeMessagePtr&& message) override + { + switch (message->GetMessageId()) + { + case MQMessageId::MSG_ROUTE: + { + auto envelope = ProtoMessage::Parse(message); + if (envelope.has_payload()) + { + nav::client::ClientMessage client_message; + client_message.ParseFromString(envelope.payload()); + + switch (client_message.message_case()) + { + case nav::client::ClientMessage::kTransform: + ClientInformation::UpdateTransform(client_message.transform()); + break; + case nav::client::ClientMessage::kDrop: + ClientInformation::DropCharacter(client_message.drop().character_info()); + break; + default: + break; + } + } + break; + } + + case MQMessageId::MSG_IDENTIFICATION: + { + // the launcher wants identification + proto::routing::Identification id; + id.set_name("meshgen"); + id.set_pid(GetCurrentProcessId()); + s_pipeClient->SendProtoMessage(MQMessageId::MSG_IDENTIFICATION, id); + break; + } + + default: break; + } + } + + virtual void OnClientConnected() override + { + // Send an ID message to the launcher + proto::routing::Identification id; + id.set_name("meshgen"); + id.set_pid(GetCurrentProcessId()); + s_pipeClient->SendProtoMessage(MQMessageId::MSG_IDENTIFICATION, id); + } +}; + +void StopPipeClient() +{ + s_pipeClient->Stop(); + + delete s_pipeClient; + s_pipeClient = nullptr; +} + +void StartPipeClient() +{ + s_pipeClient = new mq::ProtoPipeClient(mq::MQ2_PIPE_SERVER_PATH); + s_pipeClient->SetHandler(std::make_shared()); + s_pipeClient->Start(); + ::atexit(StopPipeClient); +} + +void ProcessPipeClient() +{ + if (s_pipeClient != nullptr) + s_pipeClient->Process(); +} diff --git a/meshgen/Application.cpp b/meshgen/Application.cpp index 202f73d3..5b1f3a4d 100644 --- a/meshgen/Application.cpp +++ b/meshgen/Application.cpp @@ -13,6 +13,7 @@ #include "meshgen/imgui/imgui_impl_opengl2.h" #include "meshgen/imgui/imgui_impl_sdl.h" #include "common/Utilities.h" +#include "common/proto/NavMeshClient.pb.h" #include "imgui/ImGuiUtils.h" @@ -41,6 +42,8 @@ namespace fs = std::filesystem; static const int32_t MAX_LOG_MESSAGES = 1000; +static ClientInformation s_clientInformation; + static bool IsKeyboardBlocked() { return ImGui::GetIO().WantCaptureKeyboard || ImGui::GetIO().WantTextInput; } @@ -296,6 +299,7 @@ int Application::RunMainLoop() m_raye = glm::unProject(glm::vec3{ m_m.x, m_m.y, 1.0f }, m_model, m_proj, m_view); DispatchCallbacks(); + ProcessPipeClient(); // Handle input events. HandleEvents(); @@ -773,6 +777,20 @@ void Application::RenderInterface() m_cam.z = camPos[0]; } + if (!s_clientInformation.m_transforms.empty()) + { + ImGui::Separator(); + ImGui::Text("Connected Character Information:"); + for (const auto& [charInfo, xform] : s_clientInformation.m_transforms) + { + ImGui::Text( + "[%s] %s x: %.2f y: %.2f z: %.2f h: %.2f", + charInfo.c_str(), xform.shortzone().c_str(), + xform.position().x(), xform.position().y(), + xform.position().z(), xform.heading()); + } + } + if (m_geom) { auto* loader = m_geom->getMeshLoader(); @@ -1427,3 +1445,31 @@ void ImportExportSettingsDialog::Show(bool* open /* = nullptr */) m_firstShow = false; } + +ClientInformation::ClientInformation() +{ + StartPipeClient(); +} + +ClientInformation::~ClientInformation() +{ + StopPipeClient(); +} + +void ClientInformation::UpdateTransform(const nav::client::UpdateTransform& transform) +{ + std::string characterInfo = transform.character_info(); + + auto it = s_clientInformation.m_transforms.find(transform.character_info()); + if (it != s_clientInformation.m_transforms.end()) + it->second = transform; + else + s_clientInformation.m_transforms.emplace(characterInfo, transform); +} + +void ClientInformation::DropCharacter(const std::string& characterInfo) +{ + auto it = s_clientInformation.m_transforms.find(characterInfo); + if (it != s_clientInformation.m_transforms.end()) + s_clientInformation.m_transforms.erase(it); +} diff --git a/meshgen/Application.h b/meshgen/Application.h index a71c4456..6fb83630 100644 --- a/meshgen/Application.h +++ b/meshgen/Application.h @@ -332,3 +332,28 @@ class ImportExportSettingsDialog PersistedDataFields m_fields = PersistedDataFields::All & ~PersistedDataFields::MeshTiles; }; + +//---------------------------------------------------------------------------- + +namespace nav::client { +class UpdateTransform; +} + +class ClientInformation +{ + friend class Application; + +public: + ClientInformation(); + ~ClientInformation(); + + static void UpdateTransform(const nav::client::UpdateTransform& transform); + static void DropCharacter(const std::string& characterInfo); + +private: + std::unordered_map m_transforms; +}; + +void StopPipeClient(); +void StartPipeClient(); +void ProcessPipeClient(); diff --git a/meshgen/MeshGenerator.vcxproj b/meshgen/MeshGenerator.vcxproj index b8ed34b9..c793f1e0 100644 --- a/meshgen/MeshGenerator.vcxproj +++ b/meshgen/MeshGenerator.vcxproj @@ -32,6 +32,7 @@ Create Create + @@ -61,6 +62,9 @@ {1777e251-0f50-496a-b8c5-ec7f41a0b186} + + {6ce4f8d6-1709-47c5-9297-1619bbc4a71e} + {45e99b43-f47b-4aad-ac88-f95bf467f463} diff --git a/meshgen/MeshGenerator.vcxproj.filters b/meshgen/MeshGenerator.vcxproj.filters index de442118..fcf8e516 100644 --- a/meshgen/MeshGenerator.vcxproj.filters +++ b/meshgen/MeshGenerator.vcxproj.filters @@ -86,6 +86,9 @@ Source Files\tools + + Source Files + diff --git a/plugin/MQ2Nav.vcxproj b/plugin/MQ2Nav.vcxproj index ae698c03..cccf4cf4 100644 --- a/plugin/MQ2Nav.vcxproj +++ b/plugin/MQ2Nav.vcxproj @@ -140,6 +140,7 @@ + Create @@ -167,6 +168,7 @@ + diff --git a/plugin/MQ2Nav.vcxproj.filters b/plugin/MQ2Nav.vcxproj.filters index 55242210..70fcb403 100644 --- a/plugin/MQ2Nav.vcxproj.filters +++ b/plugin/MQ2Nav.vcxproj.filters @@ -69,6 +69,9 @@ Source Files + + Source Files + @@ -140,6 +143,9 @@ Header Files + + Header Files + diff --git a/plugin/MQ2Navigation.cpp b/plugin/MQ2Navigation.cpp index 9daa1713..a1df0341 100644 --- a/plugin/MQ2Navigation.cpp +++ b/plugin/MQ2Navigation.cpp @@ -16,6 +16,7 @@ #include "plugin/NavMeshRenderer.h" #include "plugin/RenderHandler.h" #include "plugin/SwitchHandler.h" +#include "plugin/MeshgenHandler.h" #include "plugin/UiController.h" #include "plugin/Utilities.h" #include "plugin/Waypoints.h" @@ -562,6 +563,7 @@ void MQ2NavigationPlugin::Plugin_Initialize() AddModule(); AddModule(); AddModule(); + AddModule(); for (const auto& m : m_modules) { diff --git a/plugin/MeshgenHandler.cpp b/plugin/MeshgenHandler.cpp new file mode 100644 index 00000000..92706105 --- /dev/null +++ b/plugin/MeshgenHandler.cpp @@ -0,0 +1,86 @@ +// +// MeshgenHandler.cpp +// + +#include "pch.h" +#include "MeshgenHandler.h" + +#include "common/proto/NavMeshClient.pb.h" + +#include +#include + +#include + +void MeshgenHandler::Initialize() +{ + if (pLocalPC != nullptr) + { + m_characterInfo = fmt::format("{}_{}", GetServerShortName(), pLocalPC->Name); + to_lower(m_characterInfo); + } +} + +void MeshgenHandler::Shutdown() +{ + postoffice::Address address; + address.Name = "meshgen"; + + nav::client::DropClient drop; + drop.set_character_info(m_characterInfo); + + nav::client::ClientMessage message; + *message.mutable_drop() = drop; + + postoffice::SendToActor(address, message); +} + +void MeshgenHandler::OnPulse() +{ + using clock = std::chrono::system_clock; + using namespace std::chrono_literals; + + static clock::time_point last_update = clock::now(); + static constexpr clock::duration update_interval = 1s; + + if (!m_characterInfo.empty() && pZoneInfo != nullptr && pLocalPC != nullptr) + { + auto now = clock::now(); + if (now >= last_update + update_interval) + { + nav::client::UpdateTransform transform; + transform.set_character_info(m_characterInfo); + transform.set_shortzone(pZoneInfo->ShortName); + + nav::vector3& position = *transform.mutable_position(); + position.set_x(pLocalPlayer->X); + position.set_y(pLocalPlayer->Y); + position.set_z(pLocalPlayer->Z); + + transform.set_heading(pLocalPlayer->Heading); + + postoffice::Address address; + address.Name = "meshgen"; + + nav::client::ClientMessage message; + *message.mutable_transform() = transform; + + postoffice::SendToActor(address, message); + + last_update = now; + } + } +} + +void MeshgenHandler::SetGameState(int gameState) +{ + if (pLocalPC != nullptr) + { + m_characterInfo = fmt::format("{}_{}", GetServerShortName(), pLocalPC->Name); + to_lower(m_characterInfo); + } + else + { + m_characterInfo.clear(); + } +} diff --git a/plugin/MeshgenHandler.h b/plugin/MeshgenHandler.h new file mode 100644 index 00000000..c2475dd9 --- /dev/null +++ b/plugin/MeshgenHandler.h @@ -0,0 +1,23 @@ +// +// MeshgenHandler.h +// + +#pragma once + +#include "common/NavModule.h" + +#include + +class MeshgenHandler : public NavModule +{ +public: + void Initialize() override; + void Shutdown() override; + + void OnPulse() override; + + void SetGameState(int gameState) override; + +private: + std::string m_characterInfo; +}; \ No newline at end of file