From 957dbc96a3805284c787ea6b71e20cad922b2c3c Mon Sep 17 00:00:00 2001 From: Christoph Honal Date: Mon, 23 Nov 2020 02:00:10 +0100 Subject: [PATCH 1/4] Add realtime settings sync --- AUMInjector/gui/Blocks/PlayerInfoBlock.cpp | 1 + AUMInjector/gui/Blocks/SettingsBlock.cpp | 19 +++++-- AUMInjector/user/MumblePlayer.cpp | 15 ++++++ AUMInjector/user/MumblePlayer.h | 12 +++++ AUMInjector/user/deobfuscate.h | 10 ++-- AUMInjector/user/main.cpp | 62 ++++++++++++++-------- AUMInjector/user/settings.h | 3 ++ 7 files changed, 92 insertions(+), 30 deletions(-) diff --git a/AUMInjector/gui/Blocks/PlayerInfoBlock.cpp b/AUMInjector/gui/Blocks/PlayerInfoBlock.cpp index cb8003d..8c4d892 100644 --- a/AUMInjector/gui/Blocks/PlayerInfoBlock.cpp +++ b/AUMInjector/gui/Blocks/PlayerInfoBlock.cpp @@ -7,6 +7,7 @@ PlayerInfoBlock::PlayerInfoBlock() {} void PlayerInfoBlock::Update() { ImGui::Text("Player Position: (%.3f, %.3f)", mumblePlayer.posCache[0], mumblePlayer.posCache[1]); + ImGui::Text("Player is in a lobby: %s", mumblePlayer.IsInLobby() ? "True" : "False"); ImGui::Text("Player is in a game: %s", mumblePlayer.IsInGame() ? "True" : "False"); ImGui::Text("Player is a ghost: %s", mumblePlayer.IsGhost() ? "True" : "False"); ImGui::Text("Player is in a meeting: %s", mumblePlayer.IsInMeeting() ? "True" : "False"); diff --git a/AUMInjector/gui/Blocks/SettingsBlock.cpp b/AUMInjector/gui/Blocks/SettingsBlock.cpp index ce5e425..8949717 100644 --- a/AUMInjector/gui/Blocks/SettingsBlock.cpp +++ b/AUMInjector/gui/Blocks/SettingsBlock.cpp @@ -24,6 +24,7 @@ void BoolComboHelper(bool &comboBoolean, const char* label) { comboBoolean = n; appSettings.RecalculateAudioMap(); + appSettings.mustBroadcast = true; } } ImGui::EndCombo(); @@ -62,7 +63,10 @@ void EnumComboHelper(const char* label, const char* str, const char** arr, ENUM_ { for (int n = 0; n < (int)ENUM_TYPE::COUNT; n++) if (ImGui::Selectable(arr[n], (int)value == n)) + { value = (ENUM_TYPE)n; + appSettings.mustBroadcast = true; + } ImGui::EndCombo(); } } @@ -71,18 +75,27 @@ void SettingsBlock::Update() { // Config settings that can be changed each round ImGui::Text("[ Game Settings ]"); - ImGui::Text("These settings will be applied to the next round you host."); // If the user is in a game, don't let them change the settings and only display them - if (mumblePlayer.IsInGame()) + if (mumblePlayer.IsInGame() || (mumblePlayer.IsInLobby() && !mumblePlayer.IsHost())) { // Print current settings only, as they can't be changed. - ImGui::Text("You cannot change game settings while in a round."); + if (mumblePlayer.IsInGame()) + { + ImGui::Text("You cannot change game settings while in a round."); + } + else + { + ImGui::Text("You cannot change game settings."); + ImGui::Text("Only the lobby host can do that."); + } ImGui::Text("Ghost voice mode: %s", voiceText[(int)appSettings.ghostVoiceMode]); ImGui::Text("Directional Audio: %s", appSettings.directionalAudio ? "True" : "False"); } else { + ImGui::Text("These settings will be applied to next round."); + // Ghost voice mode verbosity setting if (ImGui::TreeNode("Ghost Voice Mode:")) { diff --git a/AUMInjector/user/MumblePlayer.cpp b/AUMInjector/user/MumblePlayer.cpp index a2846be..daae11c 100644 --- a/AUMInjector/user/MumblePlayer.cpp +++ b/AUMInjector/user/MumblePlayer.cpp @@ -117,6 +117,12 @@ bool MumblePlayer::IsInMeeting() { return isInMeeting; } bool MumblePlayer::IsInGame() { return isInGame; } +bool MumblePlayer::IsInLobby() { return isInLobby; } + +bool MumblePlayer::IsHost() { return isHost; } + +void MumblePlayer::SetHost(bool host) { isHost = host; } + // Returns the mumble-ready position of the player float MumblePlayer::GetMumblePos(int i) { return posCache[appSettings.audioCoordinateMap[i]]; } @@ -192,11 +198,20 @@ void MumblePlayer::TryLogPosition(bool force) void MumblePlayer::EnterGame() { isInGame = true; + isInLobby = false; +} + +// Player entered a lobby +void MumblePlayer::EnterLobby() +{ + isInLobby = true; + isInGame = false; } // Player exited a game void MumblePlayer::ExitGame() { isInGame = false; + isInLobby = false; } diff --git a/AUMInjector/user/MumblePlayer.h b/AUMInjector/user/MumblePlayer.h index 257fb7f..f707d76 100644 --- a/AUMInjector/user/MumblePlayer.h +++ b/AUMInjector/user/MumblePlayer.h @@ -19,6 +19,12 @@ class MumblePlayer bool IsInGame(); + bool IsInLobby(); + + bool IsHost(); + + void SetHost(bool host); + // --- Player Position --- // Returns the mumble-ready position of the player float GetMumblePos(int i); @@ -60,6 +66,9 @@ class MumblePlayer // Player exited a game void ExitGame(); + // Player entered a lobby + void EnterLobby(); + int GetNetID(); void SetNetID(int id); @@ -96,12 +105,15 @@ class MumblePlayer // -- Other State Info -- bool isInMeeting = false; + bool isInLobby = false; bool isSabotaged = false; bool isInGame = false; // Cached player network id int netID = 0; + bool isHost = false; + // Reads private information to display it to the user friend class PlayerInfoBlock; }; diff --git a/AUMInjector/user/deobfuscate.h b/AUMInjector/user/deobfuscate.h index 347d526..34e5b6b 100644 --- a/AUMInjector/user/deobfuscate.h +++ b/AUMInjector/user/deobfuscate.h @@ -28,6 +28,7 @@ using namespace app; using HqHudOverrideTask = MMPIJGKLMDC; using HudOverrideTask = GFBKIHICFNI; using ChatController = MLINJDBIIEC; + using AmongUsClient = JNFEHNLGIFF; InnerNetClient_GameState__Enum InnerNetClient_GameState__Enum_Joined = DNAFMCDBMCI_JPCEFDHGHAK__Enum_Joined; InnerNetClient_GameState__Enum InnerNetClient_GameState__Enum_Ended = DNAFMCDBMCI_JPCEFDHGHAK__Enum_Ended; InnerNetClient_GameState__Enum InnerNetClient_GameState__Enum_Started = DNAFMCDBMCI_JPCEFDHGHAK__Enum_Started; @@ -43,8 +44,9 @@ using namespace app; #define HudOverrideTask_Initialize_Trampoline GFBKIHICFNI_Initialize #define HudOverrideTask_Complete_Trampoline GFBKIHICFNI_Complete #define ChatController_AddChat_Trampoline MLINJDBIIEC_AddChat - #define InnerNetClient_StartRpc DNAFMCDBMCI_StartRpc - #define MessageWriter_Write_String MessageWriter_Write_6 + #define InnerNetClient_StartRpc_Trampoline DNAFMCDBMCI_StartRpc + #define MessageWriter_Write_String_Trampoline MessageWriter_Write_6 + #define AmongUsClient_OnPlayerJoined_Trampoline JNFEHNLGIFF_IKDNNJNBKBO // Stuff I researched at one point but thats not required atm //SystemTypes__Enum SystemTypes__Enum_Comms = JBPEMAACAEP__Enum_Comms; @@ -90,8 +92,8 @@ using namespace app; #define HudOverrideTask_Initialize_Trampoline MHKPCHGHHOK_Initialize #define HudOverrideTask_Complete_Trampoline MHKPCHGHHOK_Complete #define ChatController_AddChat_Trampoline LOGKEMANPPL_AddChat - #define InnerNetClient_StartRpc DBDDAJAICFN_StartRpc - #define MessageWriter_Write_String MessageWriter_Write_6 + #define InnerNetClient_StartRpc_Trampoline DBDDAJAICFN_StartRpc + #define MessageWriter_Write_String_Trampoline MessageWriter_Write_6 #else #error Unknown game version! #endif \ No newline at end of file diff --git a/AUMInjector/user/main.cpp b/AUMInjector/user/main.cpp index 15e0ff6..30c5d5c 100644 --- a/AUMInjector/user/main.cpp +++ b/AUMInjector/user/main.cpp @@ -93,11 +93,34 @@ void MeetingHud_Start_Hook(MeetingHud* __this, MethodInfo* method) mumblePlayer.StartMeeting(); } +// Broadcast the current settings +void BroadcastSettings(InnerNetClient* client) +{ + logger.Log(LOG_CODE::MSG, "Sending configuration: " + appSettings.HumanReadableSync()); + + // Broadcast config via chat + std::string messageText = SYNC_HEADER + appSettings.SerializeSync(); + String* messageString = (String*)il2cpp_string_new(messageText.c_str()); + MessageWriter* writer = InnerNetClient_StartRpc_Trampoline(client, mumblePlayer.GetNetID(), 13, SendOption__Enum_Reliable, NULL); + MessageWriter_Write_String_Trampoline(writer, messageString, NULL); + MessageWriter_EndMessage(writer, NULL); +} + // Fixed loop for the game client void InnerNetClient_FixedUpdate_Hook(InnerNetClient* __this, MethodInfo* method) { InnerNetClient_FixedUpdate_Trampoline(__this, method); + // Set if player is host + mumblePlayer.SetHost(__this->fields.ClientId == __this->fields.HostId); + + // Check if the host should broadcast the settings due to GUI change + if (appSettings.mustBroadcast && mumblePlayer.IsHost()) + { + BroadcastSettings(__this); + appSettings.mustBroadcast = false; + } + // Check if game state changed to lobby if (__this->fields.GameState != lastGameState) { @@ -109,34 +132,13 @@ void InnerNetClient_FixedUpdate_Hook(InnerNetClient* __this, MethodInfo* method) // Reset options to local version appSettings.Parse(); mumblePlayer.ResetState(); - mumblePlayer.ExitGame(); - - // For testing ghost voice modes (set user to "ghost" by default) - // Sleep(1000); - // mumblePlayer.EnterGhostState(); + mumblePlayer.EnterLobby(); } else if (__this->fields.GameState == InnerNetClient_GameState__Enum_Started) { logger.Log(LOG_CODE::MSG, "Round started"); mumblePlayer.EnterGame(); - - // Check if client is hosting - if (__this->fields.ClientId == __this->fields.HostId) - { - logger.Log(LOG_CODE::MSG, "Sending configuration: " + appSettings.HumanReadableSync()); - - // Broadcast config via chat - std::string messageText = SYNC_HEADER + appSettings.SerializeSync(); - String* messageString = (String*)il2cpp_string_new(messageText.c_str()); - MessageWriter* writer = InnerNetClient_StartRpc(__this, mumblePlayer.GetNetID(), 13, SendOption__Enum_Reliable, method); - MessageWriter_Write_String(writer, messageString, method); - MessageWriter_EndMessage(writer, method); - } - else - { - logger.Log(LOG_CODE::MSG, "Will not broadcast configuration, waiting for host"); - } } } lastGameState = __this->fields.GameState; @@ -213,6 +215,19 @@ void HudOverrideTask_Complete_Hook(HudOverrideTask* __this, MethodInfo* method) UpdateComms(false); } +// Gets called when a player joins +void AmongUsClient_OnPlayerJoined_Hook(AmongUsClient* __this, ClientData* data, MethodInfo* method) +{ + AmongUsClient_OnPlayerJoined_Trampoline(__this, data, method); + logger.Log(LOG_CODE::MSG, "Player joined lobby"); + + // New player joins -> Re-broadcast settings from host + if (__this->fields._.ClientId == __this->fields._.HostId) + { + BroadcastSettings((InnerNetClient*)__this); + } +} + //// This sets the keypad on mirahq to 10% speed for testing //void IGHKMHLJFLI_Detoriorate_Hook(IGHKMHLJFLI* __this, float PCHPGLOMPLD, MethodInfo* method) //{ @@ -235,7 +250,7 @@ void ChatController_AddChat_Hook(ChatController* __this, PlayerControl* sourcePl switch (result) { case SYNC_SUCCESS: - logger.Log(LOG_CODE::INF, "Got configuration: " + appSettings.HumanReadableSync()); + logger.Log(LOG_CODE::MSG, "Got configuration: " + appSettings.HumanReadableSync()); break; case SYNC_ERROR_NUM_ARGS: logger.Log(LOG_CODE::ERR, "Got bad configuration (invalid number of arguments), ignoring"); @@ -312,6 +327,7 @@ void Run() DetourAttach(&(PVOID&)HudOverrideTask_Initialize_Trampoline, HudOverrideTask_Initialize_Hook); DetourAttach(&(PVOID&)HudOverrideTask_Complete_Trampoline, HudOverrideTask_Complete_Hook); DetourAttach(&(PVOID&)ChatController_AddChat_Trampoline, ChatController_AddChat_Hook); + DetourAttach(&(PVOID&)AmongUsClient_OnPlayerJoined_Trampoline, AmongUsClient_OnPlayerJoined_Hook); //DetourAttach(&(PVOID&)IGHKMHLJFLI_Detoriorate, IGHKMHLJFLI_Detoriorate_Hook); //dynamic_analysis_attach(); diff --git a/AUMInjector/user/settings.h b/AUMInjector/user/settings.h index c875978..f78d23f 100644 --- a/AUMInjector/user/settings.h +++ b/AUMInjector/user/settings.h @@ -82,6 +82,9 @@ class Settings bool directionalAudio; GHOST_VOICE_MODE ghostVoiceMode; + // Should the sync settings be broadcasted ont he next tick + bool mustBroadcast = false; + // Setup argument parser Settings(); From f3a3b2053af0d4237e5e0d7d634be8dd414b9b69 Mon Sep 17 00:00:00 2001 From: Christoph Honal Date: Mon, 23 Nov 2020 02:59:20 +0100 Subject: [PATCH 2/4] Add broadcast rate limit --- AUMInjector/user/main.cpp | 18 ++++++++++++++---- AUMInjector/user/settings.h | 2 ++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/AUMInjector/user/main.cpp b/AUMInjector/user/main.cpp index 30c5d5c..c6ec5d5 100644 --- a/AUMInjector/user/main.cpp +++ b/AUMInjector/user/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "il2cpp-init.h" #include "il2cpp-appdata.h" @@ -117,8 +118,15 @@ void InnerNetClient_FixedUpdate_Hook(InnerNetClient* __this, MethodInfo* method) // Check if the host should broadcast the settings due to GUI change if (appSettings.mustBroadcast && mumblePlayer.IsHost()) { - BroadcastSettings(__this); - appSettings.mustBroadcast = false; + // Only broadcast at most every three seconds to prevent spam detection + long long timestamp = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + if ((timestamp - appSettings.lastBroadcastMs) >= 3000) + { + BroadcastSettings(__this); + appSettings.mustBroadcast = false; + appSettings.lastBroadcastMs = timestamp; + } } // Check if game state changed to lobby @@ -222,9 +230,11 @@ void AmongUsClient_OnPlayerJoined_Hook(AmongUsClient* __this, ClientData* data, logger.Log(LOG_CODE::MSG, "Player joined lobby"); // New player joins -> Re-broadcast settings from host - if (__this->fields._.ClientId == __this->fields._.HostId) + // Only if joining player is not host + if ((__this->fields._.ClientId == __this->fields._.HostId) && + (data->fields.Id != __this->fields._.HostId)) { - BroadcastSettings((InnerNetClient*)__this); + appSettings.mustBroadcast = true; } } diff --git a/AUMInjector/user/settings.h b/AUMInjector/user/settings.h index f78d23f..a588734 100644 --- a/AUMInjector/user/settings.h +++ b/AUMInjector/user/settings.h @@ -84,6 +84,8 @@ class Settings // Should the sync settings be broadcasted ont he next tick bool mustBroadcast = false; + long long lastBroadcastMs = 0; + // Setup argument parser Settings(); From 5c8416edb96cc66708a404753d860b7285b56ade Mon Sep 17 00:00:00 2001 From: Christoph Honal Date: Mon, 23 Nov 2020 03:13:24 +0100 Subject: [PATCH 3/4] add beta deobfuscations --- AUMInjector/user/deobfuscate.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AUMInjector/user/deobfuscate.h b/AUMInjector/user/deobfuscate.h index 34e5b6b..398d5fb 100644 --- a/AUMInjector/user/deobfuscate.h +++ b/AUMInjector/user/deobfuscate.h @@ -77,6 +77,7 @@ using namespace app; using HqHudOverrideTask = OFCAMODPCOA; using HudOverrideTask = MHKPCHGHHOK; using ChatController = LOGKEMANPPL; + using AmongUsClient = HJNEPPHDLBA; InnerNetClient_GameState__Enum InnerNetClient_GameState__Enum_Joined = DBDDAJAICFN_DKEKFCCGGEO__Enum_Joined; InnerNetClient_GameState__Enum InnerNetClient_GameState__Enum_Ended = DBDDAJAICFN_DKEKFCCGGEO__Enum_Ended; InnerNetClient_GameState__Enum InnerNetClient_GameState__Enum_Started = DBDDAJAICFN_DKEKFCCGGEO__Enum_Started; @@ -94,6 +95,7 @@ using namespace app; #define ChatController_AddChat_Trampoline LOGKEMANPPL_AddChat #define InnerNetClient_StartRpc_Trampoline DBDDAJAICFN_StartRpc #define MessageWriter_Write_String_Trampoline MessageWriter_Write_6 + #define AmongUsClient_OnPlayerJoined_Trampoline HJNEPPHDLBA_LKMONKFOADB #else #error Unknown game version! #endif \ No newline at end of file From 133d4c0819c94bec7749bc430debdb5f38df1b8c Mon Sep 17 00:00:00 2001 From: Christoph Honal Date: Mon, 23 Nov 2020 03:52:55 +0100 Subject: [PATCH 4/4] Add cool badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 52fa1af..69a2c6e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Discord](https://img.shields.io/discord/767166243303587882?color=cornflowerblue&label=Discord&logo=Discord&logoColor=white)](https://discord.gg/4UkHEJ5sqg) [![GitHub all releases](https://img.shields.io/github/downloads/StarGate01/AmongUs-Mumble/total?label=Downloads)](https://github.com/StarGate01/AmongUs-Mumble/releases) + # AmongUs-Mumble [Mumble VoIP](https://www.mumble.info/) Plugin and mod for the popular game "[Among Us](https://store.steampowered.com/app/945360/Among_Us/)" by [Innersloth](http://www.innersloth.com/) to enable **Proximity and Directional Voice Chat**.