From 86129b42ded2445717dbbd6352235e27b0e9860e Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sat, 8 Jan 2022 01:27:26 +0100 Subject: [PATCH 01/56] Update to 1.19 untested as test servers didn't seem to want to work --- MultiQuestensions/Android.mk | 10 +-- MultiQuestensions/MultiQuestensions.vcxproj | 1 + .../MultiQuestensions.vcxproj.filters | 1 + MultiQuestensions/build.ps1 | 2 +- MultiQuestensions/buildQMOD.ps1 | 6 +- .../include/Beatmaps/PreviewBeatmapStub.hpp | 4 +- .../include/Extensions/ExtendedPlayer.hpp | 2 +- .../include/Packets/PacketSerializer.hpp | 2 +- MultiQuestensions/mod.json | 6 +- .../CodegenExtensions/TempBloomFilterUtil.hpp | 14 ++++ MultiQuestensions/src/Assets/Sprites.cpp | 2 +- .../src/Beatmaps/PreviewBeatmapStub.cpp | 16 ++--- .../src/Environments/LobbyAvatarNameTag.cpp | 2 +- .../Environments/LobbyAvatarPlaceLighting.cpp | 4 +- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 17 ++--- .../src/Hooks/InstallerHooks.cpp | 18 ++--- .../src/Hooks/MaxPlayerHooks.cpp | 22 +++--- .../src/Hooks/QuickplayHooks.cpp | 4 +- .../SessionManagerAndExtendedPlayerHooks.cpp | 18 ++--- .../src/UI/CenterScreenLoading.cpp | 2 +- .../src/UI/DownloadedSongsGSM.cpp | 4 +- MultiQuestensions/src/main.cpp | 67 ++++++++++--------- 22 files changed, 122 insertions(+), 102 deletions(-) create mode 100644 MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp diff --git a/MultiQuestensions/Android.mk b/MultiQuestensions/Android.mk index fa98188..770d885 100644 --- a/MultiQuestensions/Android.mk +++ b/MultiQuestensions/Android.mk @@ -18,12 +18,11 @@ TARGET_ARCH_ABI := $(APP_ABI) rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) -# Creating prebuilt for dependency: beatsaber-hook - version: 2.3.2 +# Creating prebuilt for dependency: beatsaber-hook - version: 3.4.4 include $(CLEAR_VARS) -LOCAL_MODULE := beatsaber-hook_2_3_2 +LOCAL_MODULE := beatsaber-hook_3_4_4 LOCAL_EXPORT_C_INCLUDES := extern/beatsaber-hook -LOCAL_SRC_FILES := extern/libbeatsaber-hook_2_3_2.so -LOCAL_CPP_FEATURES += exceptions +LOCAL_SRC_FILES := extern/libbeatsaber-hook_3_4_4.so include $(PREBUILT_SHARED_LIBRARY) # Creating prebuilt for dependency: custom-types - version: 0.12.7 include $(CLEAR_VARS) @@ -68,7 +67,7 @@ LOCAL_SRC_FILES += $(call rwildcard,src/,*.cpp) LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook,*.cpp) LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook,*.c) LOCAL_SHARED_LIBRARIES += modloader -LOCAL_SHARED_LIBRARIES += beatsaber-hook_2_3_2 +LOCAL_SHARED_LIBRARIES += beatsaber-hook_3_4_4 LOCAL_SHARED_LIBRARIES += custom-types LOCAL_SHARED_LIBRARIES += songloader LOCAL_SHARED_LIBRARIES += questui @@ -76,6 +75,7 @@ LOCAL_SHARED_LIBRARIES += songdownloader LOCAL_SHARED_LIBRARIES += codegen LOCAL_LDLIBS += -llog LOCAL_CFLAGS += -I'extern/libil2cpp/il2cpp/libil2cpp' -DID='"multiquestensions"' -DVERSION='"$(VERSION)"' -DMPEX_PROTOCOL='"$(MPEX_PROTOCOL)"' -I'./shared' -I'./extern' -isystem'extern/codegen/include' -Ofast +LOCAL_CPP_FEATURES += rtti exceptions LOCAL_CPPFLAGS += -std=c++2a LOCAL_C_INCLUDES += ./include ./src include $(BUILD_SHARED_LIBRARY) diff --git a/MultiQuestensions/MultiQuestensions.vcxproj b/MultiQuestensions/MultiQuestensions.vcxproj index 1eee77b..f38ca26 100644 --- a/MultiQuestensions/MultiQuestensions.vcxproj +++ b/MultiQuestensions/MultiQuestensions.vcxproj @@ -81,6 +81,7 @@ + diff --git a/MultiQuestensions/MultiQuestensions.vcxproj.filters b/MultiQuestensions/MultiQuestensions.vcxproj.filters index ba30a51..8d605c3 100644 --- a/MultiQuestensions/MultiQuestensions.vcxproj.filters +++ b/MultiQuestensions/MultiQuestensions.vcxproj.filters @@ -229,5 +229,6 @@ + \ No newline at end of file diff --git a/MultiQuestensions/build.ps1 b/MultiQuestensions/build.ps1 index be252ad..808a0d8 100644 --- a/MultiQuestensions/build.ps1 +++ b/MultiQuestensions/build.ps1 @@ -8,7 +8,7 @@ if ($env:VERSION) { $Version = $env:VERSION } if (!($Version)) { -$Version = "0.1.1" +$Version = "0.1.2" } if ($env:MPEX_PROTOCOL) { $MpEx_Protocol = $env:MPEX_PROTOCOL diff --git a/MultiQuestensions/buildQMOD.ps1 b/MultiQuestensions/buildQMOD.ps1 index 67b8620..abff185 100644 --- a/MultiQuestensions/buildQMOD.ps1 +++ b/MultiQuestensions/buildQMOD.ps1 @@ -1,9 +1,9 @@ # Builds a .qmod file for loading with QP if ($args.Count -eq 0) { $ModID = "multiquestensions" -$BSHook = "2_3_2" -$VERSION = "0.1.0" -$BS_Version = "1.17.1" +$BSHook = "3_4_4" +$VERSION = "0.1.2" +$BS_Version = "1.19.0" $new_VERSION = Read-Host -Prompt "Input desired mod version (leave empty for default: '$VERSION')" $bs_hook_version = $BSHook.Replace("_", ".") $new_BSHook = Read-Host -Prompt "Input current bs-hook version (leave empty for default: '$bs_hook_version')" diff --git a/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp b/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp index 539f947..4756907 100644 --- a/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp +++ b/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp @@ -23,7 +23,7 @@ namespace MultiQuestensions::Beatmaps { } DECLARE_CLASS_INTERFACES(MultiQuestensions::Beatmaps, PreviewBeatmapStub, "System", "Object", sizeof(Il2CppObject), - { classof(GlobalNamespace::IPreviewBeatmapLevel*) }, + classof(GlobalNamespace::IPreviewBeatmapLevel*), DECLARE_CTOR(FromPreviewPacket, Il2CppString* levelhash, GlobalNamespace::IPreviewBeatmapLevel* level, PreviewBeatmapPacket* lvl = nullptr); //DECLARE_CTOR(FromPreview, Il2CppString* levelHash, GlobalNamespace::IPreviewBeatmapLevel*); @@ -73,7 +73,7 @@ DECLARE_CLASS_INTERFACES(MultiQuestensions::Beatmaps, PreviewBeatmapStub, "Syste DECLARE_OVERRIDE_METHOD(Array*, get_previewDifficultyBeatmapSets, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_previewDifficultyBeatmapSets", 0)); DECLARE_OVERRIDE_METHOD(System::Threading::Tasks::Task_1*, GetCoverImageAsync, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "GetCoverImageAsync", 1), System::Threading::CancellationToken cancellationToken); - DECLARE_OVERRIDE_METHOD(System::Threading::Tasks::Task_1*, GetPreviewAudioClipAsync, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "GetPreviewAudioClipAsync", 1), System::Threading::CancellationToken cancellationToken); + //DECLARE_OVERRIDE_METHOD(System::Threading::Tasks::Task_1*, GetPreviewAudioClipAsync, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "GetPreviewAudioClipAsync", 1), System::Threading::CancellationToken cancellationToken); // C++ Definitions private: diff --git a/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp b/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp index 84eaf34..7c111dc 100644 --- a/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp +++ b/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp @@ -70,7 +70,7 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlaye DECLARE_INSTANCE_METHOD(bool, HasState, Il2CppString* state); public: - static const constexpr UnityEngine::Color DefaultColor = UnityEngine::Color(0.031f, 0.752f, 1.0f); + static const constexpr UnityEngine::Color DefaultColor{ 0.031f, 0.752f, 1.0f, 1.0f }; /// /// Platform diff --git a/MultiQuestensions/include/Packets/PacketSerializer.hpp b/MultiQuestensions/include/Packets/PacketSerializer.hpp index affeba1..ff19f85 100644 --- a/MultiQuestensions/include/Packets/PacketSerializer.hpp +++ b/MultiQuestensions/include/Packets/PacketSerializer.hpp @@ -31,7 +31,7 @@ using CallbackDictionary = std::map; DECLARE_CLASS_INTERFACES(MultiQuestensions, PacketSerializer, "System", "Object", sizeof(Il2CppObject), - { classof(GlobalNamespace::INetworkPacketSubSerializer_1*) }, + classof(GlobalNamespace::INetworkPacketSubSerializer_1*), DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::INetworkPacketSubSerializer_1*), "Serialize", 2), LiteNetLib::Utils::NetDataWriter* writer, LiteNetLib::Utils::INetSerializable* packet); DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::INetworkPacketSubSerializer_1*), "Deserialize", 3), LiteNetLib::Utils::NetDataReader* reader, int length, GlobalNamespace::IConnectedPlayer* data); DECLARE_OVERRIDE_METHOD(bool, HandlesType, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::INetworkPacketSubSerializer_1*), "HandlesType", 1), Il2CppReflectionType* type); diff --git a/MultiQuestensions/mod.json b/MultiQuestensions/mod.json index a269238..7b02318 100644 --- a/MultiQuestensions/mod.json +++ b/MultiQuestensions/mod.json @@ -3,15 +3,15 @@ "name": "MultiQuestensions", "id": "multiquestensions", "author": "EnderdracheLP and Goobie", - "version": "0.1.1", + "version": "0.1.2-Test", "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.17.1", + "packageVersion": "1.19.0", "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to official Multiplayer.", "modFiles": [ "libmultiquestensions.so" ], "libraryFiles": [ - "libbeatsaber-hook_2_3_2.so" + "libbeatsaber-hook_3_4_4.so" ], "dependencies": [ { diff --git a/MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp b/MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp new file mode 100644 index 0000000..eedcf03 --- /dev/null +++ b/MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp @@ -0,0 +1,14 @@ +#pragma once +namespace GlobalNamespace { + class BloomFilterUtil : public ::Il2CppObject { + public: + template + static T ToBloomFilter(::Il2CppString* value, int hashCount, int hashBits) { + //static_assert(std::is_base_of_v, std::remove_pointer_t>); + static auto ___internal__logger = ::Logger::get().WithContext("GlobalNamespace::BloomFilterUtil::ToBloomFilter"); + static auto* ___internal__method = THROW_UNLESS((::il2cpp_utils::FindMethod("", "BloomFilterUtil", "ToBloomFilter", std::vector{::il2cpp_utils::il2cpp_type_check::il2cpp_no_arg_class::get()}, ::std::vector{::il2cpp_utils::ExtractType(value), ::il2cpp_utils::ExtractType(hashCount), ::il2cpp_utils::ExtractType(hashBits)}))); + static auto* ___generic__method = THROW_UNLESS(::il2cpp_utils::MakeGenericMethod(___internal__method, std::vector{::il2cpp_utils::il2cpp_type_check::il2cpp_no_arg_class::get()})); + return ::il2cpp_utils::RunMethodRethrow(static_cast(nullptr), ___generic__method, value, hashCount, hashBits); + } + }; +} diff --git a/MultiQuestensions/src/Assets/Sprites.cpp b/MultiQuestensions/src/Assets/Sprites.cpp index 4a0030d..aadbeae 100644 --- a/MultiQuestensions/src/Assets/Sprites.cpp +++ b/MultiQuestensions/src/Assets/Sprites.cpp @@ -15,7 +15,7 @@ namespace MultiQuestensions { std::string Sprites::Steam64 = "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"; Sprite* CreateSpriteFromBase64(std::string& base64) { - Array* bytes = System::Convert::FromBase64String(il2cpp_utils::newcsstr(base64)); + ArrayW bytes = System::Convert::FromBase64String(il2cpp_utils::newcsstr(base64)); Texture2D* texture = Texture2D::New_ctor(2, 2); if (ImageConversion::LoadImage(texture, bytes, false)) { return Sprite::Create(texture, UnityEngine::Rect(0.0f, 0.0f, (float)texture->get_width(), (float)texture->get_height()), UnityEngine::Vector2(0, 0), 10.0f, 0u, SpriteMeshType::Tight, UnityEngine::Vector4(0.0f, 0.0f, 0.0f, 0.0f), false); diff --git a/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp b/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp index 4001b49..36dee6b 100644 --- a/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp +++ b/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp @@ -80,14 +80,14 @@ namespace MultiQuestensions::Beatmaps { } } - System::Threading::Tasks::Task_1* PreviewBeatmapStub::GetPreviewAudioClipAsync(System::Threading::CancellationToken cancellationToken) { - if (_preview) { - return _preview->GetPreviewAudioClipAsync(cancellationToken); - } - else { - return nullptr; - } - } + //System::Threading::Tasks::Task_1* PreviewBeatmapStub::GetPreviewAudioClipAsync(System::Threading::CancellationToken cancellationToken) { + // if (_preview) { + // return _preview->GetPreviewAudioClipAsync(cancellationToken); + // } + // else { + // return nullptr; + // } + //} MultiQuestensions::Beatmaps::PreviewBeatmapPacket* PreviewBeatmapStub::GetPacket(Il2CppString* characteristic, GlobalNamespace::BeatmapDifficulty difficulty) { getLogger().debug("Start PreviewBeatmapStub::GetPacket"); diff --git a/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp b/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp index bbd011c..41ccd3b 100644 --- a/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp +++ b/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp @@ -150,7 +150,7 @@ namespace MultiQuestensions::Environments { _playerIcons.insert_or_assign(slot, imageView); auto rectTransform = iconObj->GetComponent(); - rectTransform->set_localScale({ 3.2f, 3.2f }); + rectTransform->set_localScale({ 3.2f, 3.2f, 0.0f }); } else imageView = _playerIcons.at(slot); diff --git a/MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp b/MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp index 23a5f59..4611318 100644 --- a/MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp +++ b/MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp @@ -14,8 +14,8 @@ namespace MultiQuestensions::Environments { void LobbyAvatarPlaceLighting::OnEnable() { auto lightsArr = this->GetComponentsInChildren(); - for (int i = 0; i < lightsArr->Length(); i++) { - this->lights.emplace_back(lightsArr->get(i)); + for (int i = 0; i < lightsArr.Length(); i++) { + this->lights.emplace_back(lightsArr.get(i)); } } diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index d444e17..72c9c4a 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -131,10 +131,10 @@ namespace MultiQuestensions { void HandleLobbyEnvironmentLoaded() { initialized = false; //getLogger().debug("HandleLobbyEnvironmentLoaded Started"); - auto* nativeAvatarPlaces = Resources::FindObjectsOfTypeAll(); - for (int i = 0; i < nativeAvatarPlaces->Length(); i++) + auto nativeAvatarPlaces = Resources::FindObjectsOfTypeAll(); + for (int i = 0; i < nativeAvatarPlaces.Length(); i++) { - auto* nativeAvatarPlace = nativeAvatarPlaces->values[i]; + auto nativeAvatarPlace = nativeAvatarPlaces[i]; auto avatarPlace = nativeAvatarPlace->GetComponent(); if (avatarPlace == nullptr) @@ -170,10 +170,10 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(MultiplayerLobbyController_ActivateMultiplayerLobby, &MultiplayerLobbyController::ActivateMultiplayerLobby, void, MultiplayerLobbyController* self) { - if (!_placeManager) _placeManager = Resources::FindObjectsOfTypeAll()->values[0]; - if (!_menuEnvironmentManager) _menuEnvironmentManager = Resources::FindObjectsOfTypeAll()->values[0]; - if (!_stageManager) _stageManager = Resources::FindObjectsOfTypeAll()->values[0]; - if (!_lobbyStateDataModel) _lobbyStateDataModel = _placeManager->lobbyStateDataModel; + if (!_placeManager) _placeManager = Resources::FindObjectsOfTypeAll()[0]; + if (!_menuEnvironmentManager) _menuEnvironmentManager = Resources::FindObjectsOfTypeAll()[0]; + if (!_stageManager) _stageManager = Resources::FindObjectsOfTypeAll()[0]; + if (!_lobbyStateDataModel) _lobbyStateDataModel = _placeManager->dyn__lobbyStateDataModel(); self->dyn__innerCircleRadius() = 1; self->dyn__minOuterCircleRadius() = 4.4f; @@ -183,7 +183,8 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(LightWithIdMonoBehaviour_RegisterLight, &LightWithIdMonoBehaviour::RegisterLight, void, LightWithIdMonoBehaviour* self) { - if (!(self->get_transform()->get_parent() != nullptr && self->get_transform()->get_parent()->get_name()->Contains(il2cpp_utils::newcsstr("LobbyAvatarPlace")))) LightWithIdMonoBehaviour_RegisterLight(self); + if (!(self->get_transform()->get_parent() != nullptr && self->get_transform()->get_parent()->get_name()->Contains(il2cpp_utils::newcsstr("LobbyAvatarPlace")))) + LightWithIdMonoBehaviour_RegisterLight(self); } #pragma endregion diff --git a/MultiQuestensions/src/Hooks/InstallerHooks.cpp b/MultiQuestensions/src/Hooks/InstallerHooks.cpp index 71a7b37..fd3fcb6 100644 --- a/MultiQuestensions/src/Hooks/InstallerHooks.cpp +++ b/MultiQuestensions/src/Hooks/InstallerHooks.cpp @@ -12,13 +12,13 @@ using namespace GlobalNamespace; namespace MultiQuestensions { MAKE_HOOK_MATCH(MultiplayerConnectedPlayerInstaller_InstallBindings, &MultiplayerConnectedPlayerInstaller::InstallBindings, void, MultiplayerConnectedPlayerInstaller* self) { - getLogger().debug("LagReducer set to '%s'", getConfig().config["LagReducer"].GetBool() ? "true" : "false"); + //getLogger().debug("LagReducer set to '%s'", getConfig().config["LagReducer"].GetBool() ? "true" : "false"); //self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() |= getConfig().config["LagReducer"].GetBool(); self->dyn__sceneSetupData() = GameplayCoreSceneSetupData::New_ctor( - self->dyn__sceneSetupData()->difficultyBeatmap, - self->dyn__sceneSetupData()->previewBeatmapLevel, - self->dyn__sceneSetupData()->gameplayModifiers->CopyWith( + self->dyn__sceneSetupData()->dyn_difficultyBeatmap(), + self->dyn__sceneSetupData()->dyn_previewBeatmapLevel(), + self->dyn__sceneSetupData()->dyn_gameplayModifiers()->CopyWith( System::Nullable_1(), System::Nullable_1(), System::Nullable_1(), @@ -38,11 +38,11 @@ namespace MultiQuestensions { System::Nullable_1() //zenMode: Plugin.Config.LagReducer ), - self->dyn__sceneSetupData()->playerSpecificSettings, - self->dyn__sceneSetupData()->practiceSettings, - self->dyn__sceneSetupData()->useTestNoteCutSoundEffects, - self->dyn__sceneSetupData()->environmentInfo, - self->dyn__sceneSetupData()->colorScheme + self->dyn__sceneSetupData()->dyn_playerSpecificSettings(), + self->dyn__sceneSetupData()->dyn_practiceSettings(), + self->dyn__sceneSetupData()->dyn_useTestNoteCutSoundEffects(), + self->dyn__sceneSetupData()->dyn_environmentInfo(), + self->dyn__sceneSetupData()->dyn_colorScheme() ); MultiplayerConnectedPlayerInstaller_InstallBindings(self); diff --git a/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp b/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp index 723b65c..201fd3e 100644 --- a/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp @@ -40,24 +40,24 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(IntroAnimationPatch, &MultiplayerIntroAnimationController::PlayIntroAnimation, void, MultiplayerIntroAnimationController* self, float maxDesiredIntroAnimationDuration, Action* onCompleted) { - PlayableDirector* realDirector = self->introPlayableDirector; + PlayableDirector* realDirector = self->dyn__introPlayableDirector(); if (targetIterations == 0) { - targetIterations = floor((reinterpret_cast*>(self->multiplayerPlayersManager->allActiveAtGameStartPlayers)->get_Count() - 1) / 4) + 1; + targetIterations = floor((reinterpret_cast*>(self->dyn__multiplayerPlayersManager()->dyn__allActiveAtGameStartPlayers())->get_Count() - 1) / 4) + 1; } try { // Run animation one time for each set of 4 players if (targetIterations != 1) { // Create duplicated animations GameObject* newPlayableGameObject = GameObject::New_ctor(); - self->introPlayableDirector = newPlayableGameObject->AddComponent(); + self->dyn__introPlayableDirector() = newPlayableGameObject->AddComponent(); using SetPlayableAsset = function_ptr_t; static SetPlayableAsset setPlayableAsset = reinterpret_cast(il2cpp_functions::resolve_icall("UnityEngine.Playables.PlayableDirector::SetPlayableAsset")); - setPlayableAsset(self->introPlayableDirector, realDirector->get_playableAsset()); + setPlayableAsset(self->dyn__introPlayableDirector(), realDirector->get_playableAsset()); // Mute duplicated animations except one (otherwise audio is very loud) - TimelineAsset* mutedTimeline = reinterpret_cast(self->introPlayableDirector->get_playableAsset()); + TimelineAsset* mutedTimeline = reinterpret_cast(self->dyn__introPlayableDirector()->get_playableAsset()); static auto* Enumerable_ToList_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "ToList", 1)); static auto* Enumerable_ToList = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_ToList_Generic, { classof(TrackAsset*) })); @@ -73,18 +73,18 @@ namespace MultiQuestensions { } } - self->bindingFinished = false; + self->dyn__bindingFinished() = false; IntroAnimationPatch(self, maxDesiredIntroAnimationDuration, onCompleted); // Reset director to real director - self->introPlayableDirector = realDirector; + self->dyn__introPlayableDirector() = realDirector; targetIterations--; if (targetIterations != 0) self->PlayIntroAnimation(maxDesiredIntroAnimationDuration, onCompleted); } catch (const std::runtime_error& e) { // Reset director to real director - self->introPlayableDirector = realDirector; - getLogger().critical("REPORT TO ENDER: Hook IntroAnimationPatch" __FILE__ " at Line %d: %s", __LINE__, e.what()); + self->dyn__introPlayableDirector() = realDirector; + getLogger().critical("REPORT TO ENDER: Hook IntroAnimationPatch Exception: %s", e.what()); IntroAnimationPatch(self, maxDesiredIntroAnimationDuration, onCompleted); } } @@ -158,7 +158,7 @@ namespace MultiQuestensions { return reinterpret_cast*>(selectedActivePlayers); } catch (const std::runtime_error& e) { - getLogger().critical("REPORT TO ENDER: Hook MultiplayerPlayersManager_get_allActiveAtGameStartPlayers" __FILE__ " at Line %d: %s", __LINE__, e.what()); + getLogger().critical("REPORT TO ENDER: Hook MultiplayerPlayersManager_get_allActiveAtGameStartPlayers Exception: %s", e.what()); } } else if (cpispt == BindOutroTimeline) { @@ -191,7 +191,7 @@ namespace MultiQuestensions { std::vector resultVec(rangeVec.begin(), rangeVec.end()); self->dyn__maxPlayersList()->dyn__values() = il2cpp_utils::vectorToArray(resultVec); } catch (const std::runtime_error& e) { - getLogger().critical("REPORT TO ENDER: Hook CreateServerFormController_Setup caught on" __FILE__ " at Line %d: %s", __LINE__, e.what()); + getLogger().critical("REPORT TO ENDER: Hook CreateServerFormController_Setup Exception: %s", e.what()); } CreateServerFormController_Setup(self, selectedNumberOfPlayers, netDiscoverable); } diff --git a/MultiQuestensions/src/Hooks/QuickplayHooks.cpp b/MultiQuestensions/src/Hooks/QuickplayHooks.cpp index 52833a4..3477d56 100644 --- a/MultiQuestensions/src/Hooks/QuickplayHooks.cpp +++ b/MultiQuestensions/src/Hooks/QuickplayHooks.cpp @@ -8,6 +8,8 @@ #include "GlobalNamespace/MasterServerQuickPlaySetupData_QuickPlaySongPacksOverride.hpp" #include "GlobalNamespace/MasterServerQuickPlaySetupData.hpp" +#include "CodegenExtensions/TempBloomFilterUtil.hpp" + //#include "GlobalNamespace/MasterServerQuickPlaySetupModel.hpp" #include "GlobalNamespace/SongPackMaskModelSO.hpp" @@ -45,7 +47,7 @@ namespace MultiQuestensions { self->dyn__songPackMaskModel()->ToSongPackMask( levelPackName ).Contains( - getCustomLevelSongPackMaskStr()) + BloomFilterUtil::ToBloomFilter(getCustomLevelSongPackMaskStr(), 2, 13)) ) { self->dyn__simpleDialogPromptViewController()->Init( il2cpp_utils::newcsstr("Custom Song Quickplay"), diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp index ed6d0f4..7ba4911 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp @@ -24,7 +24,7 @@ using namespace GlobalNamespace; // Handles a PreviewBeatmapPacket used to transmit data about a custom song. static void HandlePreviewBeatmapPacket(MultiQuestensions::Beatmaps::PreviewBeatmapPacket* packet, GlobalNamespace::IConnectedPlayer* player) { getLogger().debug("'%s' selected song '%s'", to_utf8(csstrtostr(player->get_userId())).c_str(), to_utf8(csstrtostr(packet->levelHash)).c_str()); - IPreviewBeatmapLevel* localPreview = lobbyPlayersDataModel->beatmapLevelsModel->GetLevelPreviewForLevelId(packet->levelId); + IPreviewBeatmapLevel* localPreview = lobbyPlayersDataModel->dyn__beatmapLevelsModel()->GetLevelPreviewForLevelId(packet->levelId); MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview; try { if (localPreview == nullptr) { @@ -40,7 +40,7 @@ static void HandlePreviewBeatmapPacket(MultiQuestensions::Beatmaps::PreviewBeatm QuestUI::MainThreadScheduler::Schedule([packet, player, preview, bytes] { if (packet && player && preview && lobbyPlayersDataModel) { preview->coverImage = QuestUI::BeatSaberUI::VectorToSprite(bytes); - BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->beatmapCharacteristicCollection->GetBeatmapCharacteristicBySerializedName(packet->characteristic); + BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(packet->characteristic); lobbyPlayersDataModel->SetPlayerBeatmapLevel(player->get_userId(), reinterpret_cast(preview), packet->difficulty, characteristic); } else { @@ -54,7 +54,7 @@ static void HandlePreviewBeatmapPacket(MultiQuestensions::Beatmaps::PreviewBeatm else { QuestUI::MainThreadScheduler::Schedule([packet, player, preview] { if (packet && player && preview) { - BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->beatmapCharacteristicCollection->GetBeatmapCharacteristicBySerializedName(packet->characteristic); + BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(packet->characteristic); lobbyPlayersDataModel->SetPlayerBeatmapLevel(player->get_userId(), reinterpret_cast(preview), packet->difficulty, characteristic); } else { @@ -71,7 +71,7 @@ static void HandlePreviewBeatmapPacket(MultiQuestensions::Beatmaps::PreviewBeatm MultiQuestensions::Beatmaps::PreviewBeatmapPacket* nullpacket = nullptr; preview = THROW_UNLESS(il2cpp_utils::New(packet->levelHash, localPreview, nullpacket)); } - BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->beatmapCharacteristicCollection->GetBeatmapCharacteristicBySerializedName(packet->characteristic); + BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(packet->characteristic); //getLogger().debug("Check difficulty as unsigned int: %u", packet->difficulty); lobbyPlayersDataModel->SetPlayerBeatmapLevel(player->get_userId(), reinterpret_cast(preview), packet->difficulty, characteristic); } @@ -201,15 +201,15 @@ MAKE_HOOK_FIND_VERBOSE(SessionManager_StartSession, il2cpp_utils::FindMethodUnsa //localExtendedPlayerSPTR = localExtendedPlayer; if (!UnityEngine::ColorUtility::TryParseHtmlString(il2cpp_utils::newcsstr(getConfig().config["color"].GetString()), localExtendedPlayer->playerColor)) - localExtendedPlayer->playerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f); + localExtendedPlayer->playerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f, 1.0f); - static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll()->get(0); - static auto UserInfoTask = localNetworkPlayerModel->platformUserModel->GetUserInfo(); + static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll().get(0); + static auto UserInfoTask = localNetworkPlayerModel->dyn__platformUserModel()->GetUserInfo(); static auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function*)>)[&](System::Threading::Tasks::Task_1* userInfoTask) { auto userInfo = userInfoTask->get_Result(); if (userInfo) { - localExtendedPlayer->platformID = userInfo->platformUserId; - localExtendedPlayer->platform = (Extensions::Platform)userInfo->platform.value; + localExtendedPlayer->platformID = userInfo->dyn_platformUserId(); + localExtendedPlayer->platform = (Extensions::Platform)userInfo->dyn_platform().value; } else getLogger().error("Failed to get local network player!"); } diff --git a/MultiQuestensions/src/UI/CenterScreenLoading.cpp b/MultiQuestensions/src/UI/CenterScreenLoading.cpp index 21898e9..09fd117 100644 --- a/MultiQuestensions/src/UI/CenterScreenLoading.cpp +++ b/MultiQuestensions/src/UI/CenterScreenLoading.cpp @@ -33,7 +33,7 @@ namespace MultiQuestensions::UI{ layout->set_minWidth(60); //vertical->set_padding(UnityEngine::RectOffset::New_ctor(0, 0, 30, 10)); - GameObject* existingLoadingControl = Resources::FindObjectsOfTypeAll()->values[0]->get_gameObject(); + GameObject* existingLoadingControl = Resources::FindObjectsOfTypeAll()[0]->get_gameObject(); GameObject* loadingControlGameObject = UnityEngine::GameObject::Instantiate(existingLoadingControl, vertical->get_transform()); loadingControl = loadingControlGameObject->GetComponent(); loadingControl->Hide(); diff --git a/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp b/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp index 5a6ebc4..524c529 100644 --- a/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp +++ b/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp @@ -62,14 +62,14 @@ namespace MultiQuestensions::UI { needSongRefresh = false; auto level = GetLevelByHash(DownloadedSongIds.at(selectedIdx)); if (level.has_value()) { - std::string songPath = to_utf8(csstrtostr(level.value()->customLevelPath)); + std::string songPath = to_utf8(csstrtostr(level.value()->get_customLevelPath())); getLogger().info("Deleting Song: %s", songPath.c_str()); DeleteSong(songPath, [&] { if (needSongRefresh) { RefreshSongs(false); } }); - if (lobbyGameStateController) lobbyGameStateController->menuRpcManager->SetIsEntitledToLevel(level.value()->get_levelID(), EntitlementsStatus::NotOwned); + if (lobbyGameStateController) lobbyGameStateController->dyn__menuRpcManager()->SetIsEntitledToLevel(level.value()->get_levelID(), EntitlementsStatus::NotOwned); } needSongRefresh = true; DownloadedSongIds.erase(DownloadedSongIds.begin() + selectedIdx); diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 98fb8ce..68197ae 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -9,6 +9,7 @@ #include "CS_DataStore.hpp" #include "GlobalNamespace/ConnectedPlayerManager.hpp" +#include "CodegenExtensions/TempBloomFilterUtil.hpp" #include "GlobalNamespace/MultiplayerLevelSelectionFlowCoordinator.hpp" #include "GlobalNamespace/CenterStageScreenController.hpp" @@ -55,10 +56,10 @@ Il2CppString* LevelIdToHash(Il2CppString* levelId) { if (Il2CppString::IsNullOrWhiteSpace(levelId)) { return nullptr; } - Array* ary = levelId->Split('_', ' '); + ArrayW ary = levelId->Split(reinterpret_cast('_'), ' '); Il2CppString* hash = nullptr; - if (ary->Length() > 2) { - hash = ary->values[2]; + if (ary.Length() > 2) { + hash = ary[2]; } return (hash != nullptr && hash->get_Length() == 40) ? hash : nullptr; } @@ -102,29 +103,29 @@ namespace MultiQuestensions { } bool AllPlayersModded() { - for (int i = 0; i < sessionManager->connectedPlayers->get_Count(); i++) { - if (!sessionManager->connectedPlayers->get_Item(i)->HasState(getModdedStateStr())) return false; + for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { + if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getModdedStateStr())) return false; } return true; } bool AllPlayersHaveNE() { - for (int i = 0; i < sessionManager->connectedPlayers->get_Count(); i++) { - if (!sessionManager->connectedPlayers->get_Item(i)->HasState(getNEStateStr())) return false; + for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { + if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getNEStateStr())) return false; } return true; } bool AllPlayersHaveME() { - for (int i = 0; i < sessionManager->connectedPlayers->get_Count(); i++) { - if (!sessionManager->connectedPlayers->get_Item(i)->HasState(getMEStateStr())) return false; + for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { + if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getMEStateStr())) return false; } return true; } bool AllPlayersHaveChroma() { - for (int i = 0; i < sessionManager->connectedPlayers->get_Count(); i++) { - if (!sessionManager->connectedPlayers->get_Item(i)->HasState(getChromaStateStr())) return false; + for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { + if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getChromaStateStr())) return false; } return true; } @@ -135,10 +136,10 @@ namespace MultiQuestensions { //using PD_ValueCollection = System::Collections::Generic::Dictionary_2::ValueCollection; MultiQuestensions::Beatmaps::PreviewBeatmapStub* GetExistingPreview(Il2CppString* levelId) { - getLogger().debug("GetExistingPreview PlayerCount: %d", sessionManager->connectedPlayers->get_Count()); - for (int i = 0; i < sessionManager->connectedPlayers->get_Count(); i++) { - ILevelGameplaySetupData* playerData = reinterpret_cast(lobbyPlayersDataModel->playersData-> - get_Item(sessionManager->connectedPlayers->get_Item(i)->get_userId())); + getLogger().debug("GetExistingPreview PlayerCount: %d", sessionManager->dyn__connectedPlayers()->get_Count()); + for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { + ILevelGameplaySetupData* playerData = reinterpret_cast(lobbyPlayersDataModel->dyn__playersData()-> + get_Item(sessionManager->dyn__connectedPlayers()->get_Item(i)->get_userId())); if (playerData->get_beatmapLevel() != nullptr && csstrtostr(playerData->get_beatmapLevel()->get_levelID()) == csstrtostr(levelId)) { getLogger().debug("GetExistingPreview type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(playerData->get_beatmapLevel())->klass).c_str()); if (il2cpp_utils::AssignableFrom(reinterpret_cast(playerData->get_beatmapLevel())->klass)) { @@ -174,11 +175,11 @@ MAKE_HOOK_MATCH(LobbyPlayersSetLocalBeatmap, &LobbyPlayersDataModel::SetLocalPla MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview = GetExistingPreview(levelId); if (preview != nullptr) { self->SetPlayerBeatmapLevel(self->get_localUserId(), reinterpret_cast(preview), beatmapDifficulty, characteristic); - self->menuRpcManager->RecommendBeatmap(BeatmapIdentifierNetSerializable::New_ctor(levelId, characteristic->get_serializedName(), beatmapDifficulty)); + self->dyn__menuRpcManager()->RecommendBeatmap(BeatmapIdentifierNetSerializable::New_ctor(levelId, characteristic->get_serializedName(), beatmapDifficulty)); return; } else { - IPreviewBeatmapLevel* localIPreview = self->beatmapLevelsModel->GetLevelPreviewForLevelId(levelId); + IPreviewBeatmapLevel* localIPreview = self->dyn__beatmapLevelsModel()->GetLevelPreviewForLevelId(levelId); if (localIPreview != nullptr) { try { using namespace MultiQuestensions::Beatmaps; @@ -187,7 +188,7 @@ MAKE_HOOK_MATCH(LobbyPlayersSetLocalBeatmap, &LobbyPlayersDataModel::SetLocalPla getLogger().debug("Check 'LobbyPlayersSetLocalBeatmap' levelID: %s", to_utf8(csstrtostr(reinterpret_cast(previewStub)->get_levelID())).c_str()); self->SetPlayerBeatmapLevel(self->get_localUserId(), reinterpret_cast(previewStub), beatmapDifficulty, characteristic); PreviewBeatmapPacket* packet = previewStub->GetPacket(characteristic->get_serializedName(), beatmapDifficulty); - self->menuRpcManager->RecommendBeatmap(BeatmapIdentifierNetSerializable::New_ctor(levelId, characteristic->get_serializedName(), beatmapDifficulty)); + self->dyn__menuRpcManager()->RecommendBeatmap(BeatmapIdentifierNetSerializable::New_ctor(levelId, characteristic->get_serializedName(), beatmapDifficulty)); packetManager->Send(packet->ToINetSerializable()); return; } @@ -210,15 +211,15 @@ MAKE_HOOK_MATCH(LobbyPlayersSelectedBeatmap, &LobbyPlayersDataModel::HandleMenuR MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview = GetExistingPreview(beatmapId->get_levelID()); if (preview != nullptr) { getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: Preview exists, SetPlayerBeatmapLevel"); - BeatmapCharacteristicSO* characteristic = self->beatmapCharacteristicCollection->GetBeatmapCharacteristicBySerializedName(beatmapId->get_beatmapCharacteristicSerializedName()); + BeatmapCharacteristicSO* characteristic = self->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(beatmapId->get_beatmapCharacteristicSerializedName()); self->SetPlayerBeatmapLevel(userId, reinterpret_cast(preview), beatmapId->get_difficulty(), characteristic); return; } else { getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: Preview doesn't exist use localPreview, SetPlayerBeatmapLevel"); - IPreviewBeatmapLevel* localPreview = self->beatmapLevelsModel->GetLevelPreviewForLevelId(beatmapId->levelID); + IPreviewBeatmapLevel* localPreview = self->dyn__beatmapLevelsModel()->GetLevelPreviewForLevelId(beatmapId->get_levelID()); if (localPreview != nullptr) { - BeatmapCharacteristicSO* characteristic = self->beatmapCharacteristicCollection->GetBeatmapCharacteristicBySerializedName(beatmapId->get_beatmapCharacteristicSerializedName()); + BeatmapCharacteristicSO* characteristic = self->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(beatmapId->get_beatmapCharacteristicSerializedName()); //self->SetPlayerBeatmapLevel(userId, localPreview, beatmapId->get_difficulty(), characteristic); LobbyPlayersSelectedBeatmap(self, userId, beatmapId); } @@ -259,7 +260,7 @@ MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController: RefreshSongs(false); DownloadedSongIds.pop_back(); }); - if (lobbyGameStateController) lobbyGameStateController->menuRpcManager->SetIsEntitledToLevel(levelOpt.value()->get_levelID(), EntitlementsStatus::NotOwned); + if (lobbyGameStateController) lobbyGameStateController->dyn__menuRpcManager()->SetIsEntitledToLevel(levelOpt.value()->get_levelID(), EntitlementsStatus::NotOwned); } } if (firstActivation) { @@ -268,7 +269,7 @@ MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController: } MAKE_HOOK_MATCH(MultiplayerLobbyConnectionController_CreateParty, &MultiplayerLobbyConnectionController::CreateParty, void, MultiplayerLobbyConnectionController* self, CreateServerFormData data) { - data.songPacks = SongPackMask::get_all() | SongPackMask(getCustomLevelSongPackMaskStr()); + data.songPacks = SongPackMask::get_all() | SongPackMask(BloomFilterUtil::ToBloomFilter(getCustomLevelSongPackMaskStr(), 2, 13)); // TODO: Figure out why the Il2CppString constructor crashes MultiplayerLobbyConnectionController_CreateParty(self, data); } @@ -281,12 +282,12 @@ MAKE_HOOK_MATCH(MultiplayerLobbyConnectionController_CreateParty, &MultiplayerLo // Show the custom levels tab in multiplayer MAKE_HOOK_MATCH(LevelSelectionNavigationController_Setup, &LevelSelectionNavigationController::Setup, void, LevelSelectionNavigationController* self, - SongPackMask songPackMask, BeatmapDifficultyMask allowedBeatmapDifficultyMask, Array* notAllowedCharacteristics, - bool hidePacksIfOneOrNone, bool hidePracticeButton, bool showPlayerStatsInDetailView, Il2CppString* actionButtonText, IBeatmapLevelPack* levelPackToBeSelectedAfterPresent, + SongPackMask songPackMask, BeatmapDifficultyMask allowedBeatmapDifficultyMask, ::ArrayW notAllowedCharacteristics, + bool hidePacksIfOneOrNone, bool hidePracticeButton, ::Il2CppString* actionButtonText, IBeatmapLevelPack* levelPackToBeSelectedAfterPresent, SelectLevelCategoryViewController::LevelCategory startLevelCategory, IPreviewBeatmapLevel* beatmapLevelToBeSelectedAfterPresent, bool enableCustomLevels) { getLogger().info("LevelSelectionNavigationController_Setup setting custom songs . . ."); - LevelSelectionNavigationController_Setup(self, songPackMask, allowedBeatmapDifficultyMask, notAllowedCharacteristics, hidePacksIfOneOrNone, hidePracticeButton, showPlayerStatsInDetailView, - actionButtonText, levelPackToBeSelectedAfterPresent, startLevelCategory, beatmapLevelToBeSelectedAfterPresent, songPackMask.Contains(getCustomLevelSongPackMaskStr())); + LevelSelectionNavigationController_Setup(self, songPackMask, allowedBeatmapDifficultyMask, notAllowedCharacteristics, hidePacksIfOneOrNone, hidePracticeButton, + actionButtonText, levelPackToBeSelectedAfterPresent, startLevelCategory, beatmapLevelToBeSelectedAfterPresent, songPackMask.Contains(BloomFilterUtil::ToBloomFilter(getCustomLevelSongPackMaskStr(), 2, 13))); } static bool isMissingLevel = false; @@ -337,7 +338,7 @@ namespace MultiQuestensions { std::vector DownloadedSongIds; MAKE_HOOK_MATCH(MultiplayerLevelLoader_LoadLevel, &MultiplayerLevelLoader::LoadLevel, void, MultiplayerLevelLoader* self, BeatmapIdentifierNetSerializable* beatmapId, GameplayModifiers* gameplayModifiers, float initialStartTime) { - std::string levelId = to_utf8(csstrtostr(beatmapId->levelID)); + std::string levelId = to_utf8(csstrtostr(beatmapId->get_levelID())); getLogger().info("MultiplayerLevelLoader_LoadLevel: %s", levelId.c_str()); MultiQuestensions::UI::CenterScreenLoading* cslInstance = MultiQuestensions::UI::CenterScreenLoading::get_Instance(); if (IsCustomLevel(levelId)) { @@ -377,7 +378,7 @@ MAKE_HOOK_MATCH(MultiplayerLevelLoader_LoadLevel, &MultiplayerLevelLoader::LoadL UI::DownloadedSongsGSM::mapQueue.push_back(hash); } getLogger().debug("Pointer Check before loading level: self='%p', beatmapId='%p', gameplayModifiers='%p'", self, beatmapId, gameplayModifiers); - self->loaderState = MultiplayerLevelLoader::MultiplayerBeatmapLoaderState::NotLoading; + self->dyn__loaderState() = MultiplayerLevelLoader::MultiplayerBeatmapLoaderState::NotLoading; //getLogger().debug("MultiplayerLevelLoader_LoadLevel, Downloaded, calling original"); MultiplayerLevelLoader_LoadLevel(self, beatmapId, gameplayModifiers, initialStartTime); return; @@ -455,11 +456,11 @@ MAKE_HOOK_MATCH(LobbyGameStateController_HandleMultiplayerLevelLoaderCountdownFi //self->dyn__multiplayerLevelLoader()->dyn__loaderState() = MultiplayerLevelLoader::MultiplayerBeatmapLoaderState::NotLoading; bool entitlementStatusOK = true; - std::string LevelID = to_utf8(csstrtostr(self->startedBeatmapId->get_levelID())); + std::string LevelID = to_utf8(csstrtostr(self->get_startedBeatmapId()->get_levelID())); // Checks each player, to see if they're in the lobby, and if they are, checks their entitlement status. MultiQuestensions::UI::CenterScreenLoading::playersReady = 0; - for (int i = 0; i < sessionManager->connectedPlayers->get_Count(); i++) { - Il2CppString* csUserID = sessionManager->connectedPlayers->get_Item(i)->get_userId(); + for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { + Il2CppString* csUserID = sessionManager->dyn__connectedPlayers()->get_Item(i)->get_userId(); std::string UserID = to_utf8(csstrtostr(csUserID)); if (self->dyn__lobbyPlayersDataModel()->GetPlayerIsInLobby(csUserID)) { if (entitlementDictionary[UserID][LevelID] != EntitlementsStatus::Ok) entitlementStatusOK = false; @@ -467,7 +468,7 @@ MAKE_HOOK_MATCH(LobbyGameStateController_HandleMultiplayerLevelLoaderCountdownFi } } getLogger().debug("[HandleMultiplayerLevelLoaderCountdownFinished] Players ready: '%d'", MultiQuestensions::UI::CenterScreenLoading::playersReady + 1); - self->menuRpcManager->SetIsEntitledToLevel(previewBeatmapLevel->get_levelID(), EntitlementsStatus::Ok); + self->dyn__menuRpcManager()->SetIsEntitledToLevel(previewBeatmapLevel->get_levelID(), EntitlementsStatus::Ok); if (entitlementStatusOK) { //if (cslInstance) cslInstance->HideLoading(); //loadingPreviewBeatmapLevel = nullptr; From 2a2a865c193a6b614ad36be2cb47ae84b1f8ddc5 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 10 Apr 2022 12:04:24 +0200 Subject: [PATCH 02/56] Commit current changes Il2CppString* to StringW --- .gitignore | 1 + .vscode/settings.json | 3 + MultiQuestensions/.gitignore | 1 + MultiQuestensions/Android.mk | 18 ++--- MultiQuestensions/MultiQuestensions.vcxproj | 4 +- MultiQuestensions/build.ps1 | 45 ++++++++---- MultiQuestensions/buildQMOD.ps1 | 22 +++--- .../include/Beatmaps/PreviewBeatmapPacket.hpp | 14 ++-- .../include/Beatmaps/PreviewBeatmapStub.hpp | 26 +++---- .../include/Extensions/ExtendedPlayer.hpp | 32 ++++----- MultiQuestensions/include/GlobalFields.hpp | 2 +- MultiQuestensions/include/Hooks/Hooks.hpp | 8 +-- MultiQuestensions/include/main.hpp | 2 +- MultiQuestensions/mod.json | 66 +++++++++++------ MultiQuestensions/mod.template.json | 21 ++++++ MultiQuestensions/qpm.json | 26 +++---- .../shared/CodegenExtensions/ColorUtility.hpp | 16 ++--- MultiQuestensions/src/Assets/Sprites.cpp | 2 +- .../src/Beatmaps/PreviewBeatmapStub.cpp | 14 ++-- .../src/Environments/LobbyAvatarNameTag.cpp | 14 ++-- .../src/Extensions/ExtendedPlayer.cpp | 16 ++--- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 16 ++--- .../src/Hooks/MaxPlayerHooks.cpp | 1 - .../NetworkPlayerEntitlementCheckerHooks.cpp | 12 ++-- .../src/Hooks/QuickplayHooks.cpp | 13 ++-- .../SessionManagerAndExtendedPlayerHooks.cpp | 20 +++--- .../src/Packets/PacketSerializer.cpp | 4 +- .../src/UI/CenterScreenLoading.cpp | 8 +-- .../src/UI/DownloadedSongsGSM.cpp | 8 +-- MultiQuestensions/src/UI/LobbySetupPanel.cpp | 2 +- MultiQuestensions/src/Utils/CustomData.cpp | 4 +- MultiQuestensions/src/main.cpp | 70 ++++++++++++------- 32 files changed, 300 insertions(+), 211 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 MultiQuestensions/mod.template.json diff --git a/.gitignore b/.gitignore index 7685831..e65d98d 100644 --- a/.gitignore +++ b/.gitignore @@ -347,3 +347,4 @@ ARM64/ ndkbuild.props /MultiQuestensions/log_timestamp *.qmod +*.cmake diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..22d790a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.sourceDirectory": "${workspaceFolder}/MultiQuestensions" +} \ No newline at end of file diff --git a/MultiQuestensions/.gitignore b/MultiQuestensions/.gitignore index cde7ff9..ed541cf 100644 --- a/MultiQuestensions/.gitignore +++ b/MultiQuestensions/.gitignore @@ -48,6 +48,7 @@ out/ [Ll]ibs/ [Oo]bj/ [Oo]bjs/ +[Bb]uild/ *.zip *.txt extern/ diff --git a/MultiQuestensions/Android.mk b/MultiQuestensions/Android.mk index 770d885..98a9790 100644 --- a/MultiQuestensions/Android.mk +++ b/MultiQuestensions/Android.mk @@ -18,13 +18,13 @@ TARGET_ARCH_ABI := $(APP_ABI) rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) -# Creating prebuilt for dependency: beatsaber-hook - version: 3.4.4 +# Creating prebuilt for dependency: beatsaber-hook - version: 3.6.1 include $(CLEAR_VARS) -LOCAL_MODULE := beatsaber-hook_3_4_4 +LOCAL_MODULE := beatsaber-hook_3_6_1 LOCAL_EXPORT_C_INCLUDES := extern/beatsaber-hook -LOCAL_SRC_FILES := extern/libbeatsaber-hook_3_4_4.so +LOCAL_SRC_FILES := extern/libbeatsaber-hook_3_6_1.so include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: custom-types - version: 0.12.7 +# Creating prebuilt for dependency: custom-types - version: 0.15.2 include $(CLEAR_VARS) LOCAL_MODULE := custom-types LOCAL_EXPORT_C_INCLUDES := extern/custom-types @@ -36,13 +36,13 @@ LOCAL_MODULE := modloader LOCAL_EXPORT_C_INCLUDES := extern/modloader LOCAL_SRC_FILES := extern/libmodloader.so include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: songloader - version: 0.7.2 +# Creating prebuilt for dependency: songloader - version: 0.8.0 include $(CLEAR_VARS) LOCAL_MODULE := songloader LOCAL_EXPORT_C_INCLUDES := extern/songloader LOCAL_SRC_FILES := extern/libsongloader.so include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: questui - version: 0.11.1 +# Creating prebuilt for dependency: questui - version: 0.12.3 include $(CLEAR_VARS) LOCAL_MODULE := questui LOCAL_EXPORT_C_INCLUDES := extern/questui @@ -54,7 +54,7 @@ LOCAL_MODULE := songdownloader LOCAL_EXPORT_C_INCLUDES := extern/songdownloader LOCAL_SRC_FILES := extern/libsongdownloader.so include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: codegen - version: 0.14.0 +# Creating prebuilt for dependency: codegen - version: 0.19.0 include $(CLEAR_VARS) LOCAL_MODULE := codegen LOCAL_EXPORT_C_INCLUDES := extern/codegen @@ -67,7 +67,7 @@ LOCAL_SRC_FILES += $(call rwildcard,src/,*.cpp) LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook,*.cpp) LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook,*.c) LOCAL_SHARED_LIBRARIES += modloader -LOCAL_SHARED_LIBRARIES += beatsaber-hook_3_4_4 +LOCAL_SHARED_LIBRARIES += beatsaber-hook_3_6_1 LOCAL_SHARED_LIBRARIES += custom-types LOCAL_SHARED_LIBRARIES += songloader LOCAL_SHARED_LIBRARIES += questui @@ -75,7 +75,7 @@ LOCAL_SHARED_LIBRARIES += songdownloader LOCAL_SHARED_LIBRARIES += codegen LOCAL_LDLIBS += -llog LOCAL_CFLAGS += -I'extern/libil2cpp/il2cpp/libil2cpp' -DID='"multiquestensions"' -DVERSION='"$(VERSION)"' -DMPEX_PROTOCOL='"$(MPEX_PROTOCOL)"' -I'./shared' -I'./extern' -isystem'extern/codegen/include' -Ofast -LOCAL_CPP_FEATURES += rtti exceptions LOCAL_CPPFLAGS += -std=c++2a LOCAL_C_INCLUDES += ./include ./src +LOCAL_CPP_FEATURES += rtti exceptions include $(BUILD_SHARED_LIBRARY) diff --git a/MultiQuestensions/MultiQuestensions.vcxproj b/MultiQuestensions/MultiQuestensions.vcxproj index f38ca26..e8ec6ee 100644 --- a/MultiQuestensions/MultiQuestensions.vcxproj +++ b/MultiQuestensions/MultiQuestensions.vcxproj @@ -115,12 +115,12 @@ - src;include;extern;extern\libil2cpp\il2cpp\libil2cpp;extern\codegen\include;extern\custom-types\shared + src;include;extern\includes;extern\includes\libil2cpp\il2cpp\libil2cpp;extern\includes\codegen\include;extern\includes\custom-types\shared ID='"Mod ID"';VERSION='"Mod Version"';MPEX_PROTOCOL='"0.6.1"' "$(NdkPath)\build\ndk-build.cmd" NDK_PROJECT_PATH=$(ProjectDir) APP_BUILD_SCRIPT=$(ProjectDir)Android.mk NDK_APPLICATION_MK=$(ProjectDir)Application.mk "$(NdkPath)\build\ndk-build.cmd" -B "$(NdkPath)\build\ndk-build.cmd" clean - src;include;extern;extern\libil2cpp\il2cpp\libil2cpp;extern\codegen\include;extern\custom-types\shared;..\android-ndk-r23\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\include\**;..\android-ndk-r23\sources\cxx-stl\system\include;..\android-ndk-r23\sources\cxx-stl\llvm-libc++\include;..\android-ndk-r23\sources\cxx-stl\llvm-libc++abi\include + src;include;extern\includes;extern\includes\libil2cpp\il2cpp\libil2cpp;extern\includes\codegen\include;extern\includes\custom-types\shared;..\android-ndk-r23\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\include\**;..\android-ndk-r23\sources\cxx-stl\system\include;..\android-ndk-r23\sources\cxx-stl\llvm-libc++\include;..\android-ndk-r23\sources\cxx-stl\llvm-libc++abi\include src;include;extern;extern\libil2cpp\il2cpp\libil2cpp;extern\codegen\include;extern\custom-types\shared diff --git a/MultiQuestensions/build.ps1 b/MultiQuestensions/build.ps1 index 808a0d8..8bd1d3c 100644 --- a/MultiQuestensions/build.ps1 +++ b/MultiQuestensions/build.ps1 @@ -1,31 +1,31 @@ Param ( +[Parameter(Mandatory=$false)][Switch]$clean, [Parameter(HelpMessage="The version the mod should be compiled with")][string]$Version, [Parameter(HelpMessage="The MpEx protocol version the mod should be compiled with")][Alias("MpEx-Protocol")][string]$MpEx_Protocol ) Write-Host $Version -$NDKPath = Get-Content $PSScriptRoot/ndkpath.txt -First 1 if ($env:VERSION) { $Version = $env:VERSION } if (!($Version)) { -$Version = "0.1.2" +$Version = "0.2.0" } if ($env:MPEX_PROTOCOL) { $MpEx_Protocol = $env:MPEX_PROTOCOL } if (!($MpEx_Protocol)) { -$MpEx_Protocol = "0.7.1" +$MpEx_Protocol = "1.0.0" } -if ((Test-Path "./extern/beatsaber-hook/src/inline-hook/And64InlineHook.cpp", "./extern/beatsaber-hook/src/inline-hook/inlineHook.c", "./extern/beatsaber-hook/src/inline-hook/relocate.c") -contains $false) { +if ((Test-Path "./extern/includes/beatsaber-hook/src/inline-hook/And64InlineHook.cpp", "./extern/includes/beatsaber-hook/src/inline-hook/inlineHook.c", "./extern/includes/beatsaber-hook/src/inline-hook/relocate.c") -contains $false) { Write-Host "Critical: Missing inline-hook" - if (!(Test-Path "./extern/beatsaber-hook/src/inline-hook/And64InlineHook.cpp")) { - Write-Host "./extern/beatsaber-hook/src/inline-hook/And64InlineHook.cpp" + if (!(Test-Path "./extern/includes/beatsaber-hook/src/inline-hook/And64InlineHook.cpp")) { + Write-Host "./extern/includes/beatsaber-hook/src/inline-hook/And64InlineHook.cpp" } - if (!(Test-Path "./extern/beatsaber-hook/src/inline-hook/inlineHook.c")) { - Write-Host "./extern/beatsaber-hook/src/inline-hook/inlineHook.c" + if (!(Test-Path "./extern/includes/beatsaber-hook/src/inline-hook/inlineHook.c")) { + Write-Host "./extern/includes/beatsaber-hook/src/inline-hook/inlineHook.c" } - if (!(Test-Path "./extern/beatsaber-hook/inline-hook/src/relocate.c")) { - Write-Host "./extern/beatsaber-hook/src/inline-hook/relocate.c" + if (!(Test-Path "./extern/includes/beatsaber-hook/inline-hook/src/relocate.c")) { + Write-Host "./extern/includes/beatsaber-hook/src/inline-hook/relocate.c" } Write-Host "Task Failed" exit 1; @@ -33,9 +33,26 @@ if ((Test-Path "./extern/beatsaber-hook/src/inline-hook/And64InlineHook.cpp", ". echo "Building MultiQuestensions Version: $Version with MpEx Protocol Version: $MpEx_Protocol" -$buildScript = "$NDKPath/build/ndk-build" -if (-not ($PSVersionTable.PSEdition -eq "Core")) { - $buildScript += ".cmd" +if ($clean.IsPresent) +{ + if (Test-Path -Path "build") + { + remove-item build -R + } } -& $buildScript NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk VERSION=$Version MPEX_PROTOCOL=$MpEx_Protocol \ No newline at end of file +$NDKPath = Get-Content $PSScriptRoot/ndkpath.txt + +if (($clean.IsPresent) -or (-not (Test-Path -Path "build"))) +{ + $out = new-item -Path build -ItemType Directory +} + +& qpm-rust package edit --version $Version + +cd build +& cmake -G "Ninja" -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DMPEX_PROTOCOL="$MpEx_Protocol" ../ +& cmake --build . -j 6 +$ExitCode = $LastExitCode +cd .. +exit $ExitCode \ No newline at end of file diff --git a/MultiQuestensions/buildQMOD.ps1 b/MultiQuestensions/buildQMOD.ps1 index abff185..c7ee591 100644 --- a/MultiQuestensions/buildQMOD.ps1 +++ b/MultiQuestensions/buildQMOD.ps1 @@ -1,9 +1,9 @@ # Builds a .qmod file for loading with QP if ($args.Count -eq 0) { -$ModID = "multiquestensions" -$BSHook = "3_4_4" -$VERSION = "0.1.2" -$BS_Version = "1.19.0" +$ModID = "MultiQuestensions" +$BSHook = "3_6_1" +$VERSION = "0.2.0" +$BS_Version = "1.21.0" $new_VERSION = Read-Host -Prompt "Input desired mod version (leave empty for default: '$VERSION')" $bs_hook_version = $BSHook.Replace("_", ".") $new_BSHook = Read-Host -Prompt "Input current bs-hook version (leave empty for default: '$bs_hook_version')" @@ -15,7 +15,7 @@ if ($new_BSHook -ne "") { } Write-Host "Compiling Mod" & $PSScriptRoot/build.ps1 -Version $VERSION -& Copy-Item "./obj/local/arm64-v8a/lib$ModID.so" -Destination "./debug-builds/libmultiquestensions_$VERSION.so" +& Copy-Item "./build/debug/lib$ModID.so" -Destination "./debug-builds/lib""$ModID""_$VERSION.so" } # TODO: Get the below working with Github Actions variables. @@ -29,13 +29,13 @@ if ($args[0] -eq "--package") { # Checks if the build was successful if ($?) { # Checks if any needed files are missing - if ((Test-Path "./libs/arm64-v8a/libbeatsaber-hook_$BSHook.so", "./libs/arm64-v8a/lib$ModID.so", "./mod.json") -contains $false) { + if ((Test-Path "./build/libbeatsaber-hook_$BSHook.so", "./build/lib$ModID.so", "./mod.json") -contains $false) { Write-Host "The following files are missing" - if (!(Test-Path "./libs/arm64-v8a/libbeatsaber-hook_$BSHook.so")) { - Write-Host "./libs/arm64-v8a/libbeatsaber-hook_$BSHook.so" + if (!(Test-Path "./build/libbeatsaber-hook_$BSHook.so")) { + Write-Host "./build/libbeatsaber-hook_$BSHook.so" } - if (!(Test-Path "./libs/arm64-v8a/lib$ModID.so")) { - Write-Host "./libs/arm64-v8a/lib$ModID.so" + if (!(Test-Path "./build/lib$ModID.so")) { + Write-Host "./build/lib$ModID.so" } if (!(Test-Path ".\mod.json")) { Write-Host ".\mod.json" @@ -44,7 +44,7 @@ if ($?) { exit 1; } else { - # If we have all files needed, go ahead and packe into qmod + # If we have all files needed, go ahead and package into qmod if ($args.Count -eq 0 -or $args[0] -eq "--package") { Write-Host "Upating mod.json" $json = Get-Content $PSScriptRoot/mod.json -raw | ConvertFrom-Json diff --git a/MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp b/MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp index b8953a6..2d2f5a9 100644 --- a/MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp +++ b/MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp @@ -18,17 +18,17 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Beatmaps, PreviewBeatmapP DECLARE_CTOR(New); // Basic Song Info/Metadata - DECLARE_INSTANCE_FIELD(Il2CppString*, levelId); - DECLARE_INSTANCE_FIELD(Il2CppString*, levelHash); - DECLARE_INSTANCE_FIELD(Il2CppString*, songName); - DECLARE_INSTANCE_FIELD(Il2CppString*, songSubName); - DECLARE_INSTANCE_FIELD(Il2CppString*, songAuthorName); - DECLARE_INSTANCE_FIELD(Il2CppString*, levelAuthorName); + DECLARE_INSTANCE_FIELD(StringW, levelId); + DECLARE_INSTANCE_FIELD(StringW, levelHash); + DECLARE_INSTANCE_FIELD(StringW, songName); + DECLARE_INSTANCE_FIELD(StringW, songSubName); + DECLARE_INSTANCE_FIELD(StringW, songAuthorName); + DECLARE_INSTANCE_FIELD(StringW, levelAuthorName); DECLARE_INSTANCE_FIELD(float, beatsPerMinute); DECLARE_INSTANCE_FIELD(float, songDuration); // Selection Info - DECLARE_INSTANCE_FIELD(Il2CppString*, characteristic); + DECLARE_INSTANCE_FIELD(StringW, characteristic); DECLARE_INSTANCE_FIELD(uint, difficulty); DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(LiteNetLib::Utils::INetSerializable*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); diff --git a/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp b/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp index 4756907..ffc68fb 100644 --- a/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp +++ b/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp @@ -25,11 +25,11 @@ namespace MultiQuestensions::Beatmaps { DECLARE_CLASS_INTERFACES(MultiQuestensions::Beatmaps, PreviewBeatmapStub, "System", "Object", sizeof(Il2CppObject), classof(GlobalNamespace::IPreviewBeatmapLevel*), - DECLARE_CTOR(FromPreviewPacket, Il2CppString* levelhash, GlobalNamespace::IPreviewBeatmapLevel* level, PreviewBeatmapPacket* lvl = nullptr); + DECLARE_CTOR(FromPreviewPacket, StringW levelhash, GlobalNamespace::IPreviewBeatmapLevel* level, PreviewBeatmapPacket* lvl = nullptr); //DECLARE_CTOR(FromPreview, Il2CppString* levelHash, GlobalNamespace::IPreviewBeatmapLevel*); //DECLARE_CTOR(FromPacket, MultiQuestensions::Beatmaps::PreviewBeatmapPacket*); - DECLARE_INSTANCE_METHOD(MultiQuestensions::Beatmaps::PreviewBeatmapPacket*, GetPacket, Il2CppString*, GlobalNamespace::BeatmapDifficulty); + DECLARE_INSTANCE_METHOD(MultiQuestensions::Beatmaps::PreviewBeatmapPacket*, GetPacket, StringW, GlobalNamespace::BeatmapDifficulty); DECLARE_INSTANCE_FIELD(GlobalNamespace::IPreviewBeatmapLevel*, _preview); DECLARE_INSTANCE_FIELD(UnityEngine::Sprite*, coverImage); @@ -37,13 +37,13 @@ DECLARE_CLASS_INTERFACES(MultiQuestensions::Beatmaps, PreviewBeatmapStub, "Syste DECLARE_INSTANCE_FIELD(bool, isDownloadable); - DECLARE_INSTANCE_FIELD(Il2CppString*, levelID); - DECLARE_INSTANCE_FIELD(Il2CppString*, levelHash); + DECLARE_INSTANCE_FIELD(StringW, levelID); + DECLARE_INSTANCE_FIELD(StringW, levelHash); - DECLARE_INSTANCE_FIELD(Il2CppString*, songName); - DECLARE_INSTANCE_FIELD(Il2CppString*, songSubName); - DECLARE_INSTANCE_FIELD(Il2CppString*, songAuthorName); - DECLARE_INSTANCE_FIELD(Il2CppString*, levelAuthorName); + DECLARE_INSTANCE_FIELD(StringW, songName); + DECLARE_INSTANCE_FIELD(StringW, songSubName); + DECLARE_INSTANCE_FIELD(StringW, songAuthorName); + DECLARE_INSTANCE_FIELD(StringW, levelAuthorName); DECLARE_INSTANCE_FIELD(float, beatsPerMinute); DECLARE_INSTANCE_FIELD(float, songDuration); @@ -56,11 +56,11 @@ DECLARE_CLASS_INTERFACES(MultiQuestensions::Beatmaps, PreviewBeatmapStub, "Syste DECLARE_INSTANCE_FIELD(GlobalNamespace::EnvironmentInfoSO*, environmentInfo); DECLARE_INSTANCE_FIELD(Array*, previewDifficultyBeatmapSets); - DECLARE_OVERRIDE_METHOD(Il2CppString*, get_levelID, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_levelID", 0)); - DECLARE_OVERRIDE_METHOD(Il2CppString*, get_songName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songName", 0)); - DECLARE_OVERRIDE_METHOD(Il2CppString*, get_songSubName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songSubName", 0)); - DECLARE_OVERRIDE_METHOD(Il2CppString*, get_songAuthorName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songAuthorName", 0)); - DECLARE_OVERRIDE_METHOD(Il2CppString*, get_levelAuthorName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_levelAuthorName", 0)); + DECLARE_OVERRIDE_METHOD(StringW, get_levelID, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_levelID", 0)); + DECLARE_OVERRIDE_METHOD(StringW, get_songName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songName", 0)); + DECLARE_OVERRIDE_METHOD(StringW, get_songSubName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songSubName", 0)); + DECLARE_OVERRIDE_METHOD(StringW, get_songAuthorName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songAuthorName", 0)); + DECLARE_OVERRIDE_METHOD(StringW, get_levelAuthorName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_levelAuthorName", 0)); DECLARE_OVERRIDE_METHOD(float, get_beatsPerMinute, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_beatsPerMinute", 0)); DECLARE_OVERRIDE_METHOD(float, get_songDuration, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songDuration", 0)); DECLARE_OVERRIDE_METHOD(float, get_songTimeOffset, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songTimeOffset", 0)); diff --git a/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp b/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp index 7c111dc..e2a00a0 100644 --- a/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp +++ b/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp @@ -35,30 +35,30 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlaye /// /// Platform User ID /// - DECLARE_INSTANCE_FIELD(Il2CppString*, platformID); - DECLARE_INSTANCE_METHOD(Il2CppString*, get_platformID); + DECLARE_INSTANCE_FIELD(StringW, platformID); + DECLARE_INSTANCE_METHOD(StringW, get_platformID); /// /// MultiplayerExtensions version reported by BSIPA. /// - DECLARE_INSTANCE_FIELD(Il2CppString*, mpexVersion); - DECLARE_INSTANCE_METHOD(Il2CppString*, get_mpexVersion); + DECLARE_INSTANCE_FIELD(StringW, mpexVersion); + DECLARE_INSTANCE_METHOD(StringW, get_mpexVersion); /// /// Player's color set in the plugin config. /// DECLARE_INSTANCE_FIELD(UnityEngine::Color, playerColor); - DECLARE_INSTANCE_FIELD(Il2CppString*, isPartyOwner); - DECLARE_INSTANCE_FIELD(Il2CppString*, hasRecommendBeatmapPermission); - DECLARE_INSTANCE_FIELD(Il2CppString*, hasRecommendModifiersPermission); - DECLARE_INSTANCE_FIELD(Il2CppString*, hasKickVotePermission); + DECLARE_INSTANCE_FIELD(StringW, isPartyOwner); + DECLARE_INSTANCE_FIELD(StringW, hasRecommendBeatmapPermission); + DECLARE_INSTANCE_FIELD(StringW, hasRecommendModifiersPermission); + DECLARE_INSTANCE_FIELD(StringW, hasKickVotePermission); DECLARE_CTOR(ExtendedPlayer_ctor, GlobalNamespace::IConnectedPlayer* player, Il2CppString* platformID, int platform, UnityEngine::Color playerColor, Il2CppString* mpexVersion); DECLARE_INSTANCE_METHOD(bool, get_isMe); - DECLARE_INSTANCE_METHOD(Il2CppString*, get_userId); - DECLARE_INSTANCE_METHOD(Il2CppString*, get_userName); + DECLARE_INSTANCE_METHOD(StringW, get_userId); + DECLARE_INSTANCE_METHOD(StringW, get_userName); DECLARE_INSTANCE_METHOD(float, get_currentLatency); DECLARE_INSTANCE_METHOD(bool, get_isConnected); DECLARE_INSTANCE_METHOD(bool, get_isConnectionOwner); @@ -67,7 +67,7 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlaye DECLARE_INSTANCE_METHOD(bool, get_isKicked); DECLARE_INSTANCE_METHOD(GlobalNamespace::MultiplayerAvatarData, get_multiplayerAvatarData); DECLARE_INSTANCE_METHOD(GlobalNamespace::DisconnectedReason, get_disconnectedReason); - DECLARE_INSTANCE_METHOD(bool, HasState, Il2CppString* state); + DECLARE_INSTANCE_METHOD(bool, HasState, StringW state); public: static const constexpr UnityEngine::Color DefaultColor{ 0.031f, 0.752f, 1.0f, 1.0f }; @@ -79,8 +79,8 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlaye Platform get_platform(); static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player); - static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player, Il2CppString* platformID, Platform platform, UnityEngine::Color playerColor); - static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player, Il2CppString* platformID, Platform platform, Il2CppString* mpexVersion, UnityEngine::Color playerColor); + static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, UnityEngine::Color playerColor); + static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, StringW mpexVersion, UnityEngine::Color playerColor); constexpr const UnityEngine::Color& get_playerColor() const { return playerColor; @@ -104,8 +104,8 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlaye DECLARE_CTOR(New); // Player and platform information - DECLARE_INSTANCE_FIELD(Il2CppString*, platformID); - DECLARE_INSTANCE_FIELD(Il2CppString*, mpexVersion); + DECLARE_INSTANCE_FIELD(StringW, platformID); + DECLARE_INSTANCE_FIELD(StringW, mpexVersion); DECLARE_INSTANCE_FIELD(UnityEngine::Color, playerColor); DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(LiteNetLib::Utils::INetSerializable*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); @@ -115,6 +115,6 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlaye public: Platform platform; - static ExtendedPlayerPacket* Init(Il2CppString* platformID, Platform platform, UnityEngine::Color playerColor); + static ExtendedPlayerPacket* Init(StringW platformID, Platform platform, UnityEngine::Color playerColor); ) #undef EPPInterfaces \ No newline at end of file diff --git a/MultiQuestensions/include/GlobalFields.hpp b/MultiQuestensions/include/GlobalFields.hpp index ca5611c..94389b6 100644 --- a/MultiQuestensions/include/GlobalFields.hpp +++ b/MultiQuestensions/include/GlobalFields.hpp @@ -14,7 +14,7 @@ namespace MultiQuestensions { extern GlobalNamespace::LobbyPlayersDataModel* lobbyPlayersDataModel; extern GlobalNamespace::LobbyGameStateController* lobbyGameStateController; - extern Il2CppString* getCustomLevelSongPackMaskStr(); + extern StringW getCustomLevelSongPackMaskStr(); } //extern System::Collections::Generic::Dictionary_2 extendedPlayers; \ No newline at end of file diff --git a/MultiQuestensions/include/Hooks/Hooks.hpp b/MultiQuestensions/include/Hooks/Hooks.hpp index c6e9895..7f2dda2 100644 --- a/MultiQuestensions/include/Hooks/Hooks.hpp +++ b/MultiQuestensions/include/Hooks/Hooks.hpp @@ -59,10 +59,10 @@ namespace MultiQuestensions { extern bool HasSong(const std::string& levelId); - extern Il2CppString* getModdedStateStr(); - extern Il2CppString* getMEStateStr(); - extern Il2CppString* getNEStateStr(); - extern Il2CppString* getChromaStateStr(); + extern StringW getModdedStateStr(); + extern StringW getMEStateStr(); + extern StringW getNEStateStr(); + extern StringW getChromaStateStr(); extern GlobalNamespace::LobbyGameStateController* lobbyGameStateController; diff --git a/MultiQuestensions/include/main.hpp b/MultiQuestensions/include/main.hpp index 43b60f3..9deb3a8 100644 --- a/MultiQuestensions/include/main.hpp +++ b/MultiQuestensions/include/main.hpp @@ -40,7 +40,7 @@ Configuration& getConfig(); Logger& getLogger(); // Utilities -Il2CppString* LevelIdToHash(Il2CppString*); +StringW LevelIdToHash(StringW); extern std::string GetHash(const std::string& levelId); diff --git a/MultiQuestensions/mod.json b/MultiQuestensions/mod.json index 7b02318..3fd299f 100644 --- a/MultiQuestensions/mod.json +++ b/MultiQuestensions/mod.json @@ -1,23 +1,45 @@ { - "_QPVersion": "0.1.1", - "name": "MultiQuestensions", - "id": "multiquestensions", - "author": "EnderdracheLP and Goobie", - "version": "0.1.2-Test", - "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.19.0", - "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to official Multiplayer.", - "modFiles": [ - "libmultiquestensions.so" - ], - "libraryFiles": [ - "libbeatsaber-hook_3_4_4.so" - ], - "dependencies": [ - { - "id": "BeatTogether", - "version": "^1.3.0", - "downloadIfMissing": "https://github.com/pythonology/BeatTogether.Quest/releases/download/v1.3.0/BeatTogether_v1.3.0.qmod" - } - ] -} + "_QPVersion": "0.1.2", + "name": "MultiQuestensions", + "id": "multiquestensions", + "author": "EnderdracheLP and Goobie", + "version": "0.2.0", + "packageId": "com.beatgames.beatsaber", + "packageVersion": "1.19.0", + "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", + "dependencies": [ + { + "version": "^1.4.0", + "id": "BeatTogether", + "downloadIfMissing": "https://github.com/pythonology/BeatTogether.Quest/releases/download/v1.4.0/BeatTogether_v1.4.0.qmod" + }, + { + "version": "^0.15.6", + "id": "custom-types", + "downloadIfMissing": "https://github.com/sc2ad/Il2CppQuestTypePatching/releases/download/v0.15.6/CustomTypes.qmod" + }, + { + "version": "^0.8.3", + "id": "songloader", + "downloadIfMissing": "https://github.com/darknight1050/SongLoader/releases/download/v0.8.3/SongLoader.qmod" + }, + { + "version": "^0.19.3", + "id": "codegen", + "downloadIfMissing": "https://github.com/sc2ad/BeatSaber-Quest-Codegen/releases/download/v0.19.3/Codegen.qmod" + }, + { + "version": "^0.13.1", + "id": "questui", + "downloadIfMissing": "https://github.com/darknight1050/questui/releases/download/v0.13.1/QuestUI.qmod" + } + ], + "modFiles": [ + "libMultiQuestensions.so" + ], + "libraryFiles": [ + "libbeatsaber-hook_3_6_7.so" + ], + "fileCopies": [], + "copyExtensions": [] +} \ No newline at end of file diff --git a/MultiQuestensions/mod.template.json b/MultiQuestensions/mod.template.json new file mode 100644 index 0000000..e340106 --- /dev/null +++ b/MultiQuestensions/mod.template.json @@ -0,0 +1,21 @@ +{ + "_QPVersion": "0.1.2", + "name": "${mod_name}", + "id": "${mod_id}", + "author": "EnderdracheLP and Goobie", + "version": "${version}", + "packageId": "com.beatgames.beatsaber", + "packageVersion": "1.19.0", + "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", + "dependencies": [ + { + "version": "^1.4.0", + "id": "BeatTogether", + "downloadIfMissing": "https://github.com/pythonology/BeatTogether.Quest/releases/download/v1.4.0/BeatTogether_v1.4.0.qmod" + } + ], + "modFiles": [], + "libraryFiles": [], + "fileCopies": [], + "copyExtensions": [] +} \ No newline at end of file diff --git a/MultiQuestensions/qpm.json b/MultiQuestensions/qpm.json index b0267c0..4fd98f3 100644 --- a/MultiQuestensions/qpm.json +++ b/MultiQuestensions/qpm.json @@ -4,14 +4,16 @@ "info": { "name": "MultiQuestensions", "id": "multiquestensions", - "version": "0.1.0", + "version": "0.2.0", "url": "", - "additionalData": {} + "additionalData": { + "overrideSoName": "libMultiQuestensions.so" + } }, "dependencies": [ { "id": "beatsaber-hook", - "versionRange": "^2.3.2", + "versionRange": "^3.6.7", "additionalData": { "extraFiles": [ "src/inline-hook" @@ -20,27 +22,22 @@ }, { "id": "codegen", - "versionRange": "^0.14.0", + "versionRange": "^0.19.3", "additionalData": {} }, { "id": "custom-types", - "versionRange": "=0.12.7", + "versionRange": "^0.15.6", "additionalData": {} }, { "id": "songloader", - "versionRange": "^0.7.1", + "versionRange": "^0.8.3", "additionalData": {} }, { "id": "questui", - "versionRange": "^0.11.1", - "additionalData": {} - }, - { - "id": "songdownloader", - "versionRange": "^0.3.2", + "versionRange": "^0.13.1", "additionalData": {} }, { @@ -52,6 +49,11 @@ "id": "cpp-semver", "versionRange": "*", "additionalData": {} + }, + { + "id": "modloader", + "versionRange": "*", + "additionalData": {} } ], "additionalData": {} diff --git a/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp b/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp index 915c48a..db437db 100644 --- a/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp +++ b/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp @@ -15,19 +15,19 @@ namespace UnityEngine { class ColorUtility { ColorUtility() = delete; public: - static bool TryParseHtmlString(Il2CppString* htmlString, Color& color) { + static bool TryParseHtmlString(StringW htmlString, Color& color) { Color32 c; bool result = DoTryParseHtmlColor(htmlString, byref(c)); color = { (float)c.r / 255.0f, (float)c.g / 255.0f, (float)c.b / 255.0f, 1 }; return result; } - static bool TryParseHtmlString(std::string htmlString, Color& color) { - return TryParseHtmlString(il2cpp_utils::newcsstr(htmlString), color); - } + //static bool TryParseHtmlString(std::string htmlString, Color& color) { + // return TryParseHtmlString(htmlString.c_str(), color); + //} - static bool DoTryParseHtmlColor(Il2CppString* htmlString, ByRef color) { - using DoTryParseHtmlColor = function_ptr_t>; + static bool DoTryParseHtmlColor(StringW htmlString, ByRef color) { + using DoTryParseHtmlColor = function_ptr_t>; static DoTryParseHtmlColor doTryParseHtmlColor = reinterpret_cast(il2cpp_functions::resolve_icall("UnityEngine.ColorUtility::DoTryParseHtmlColor")); return doTryParseHtmlColor(htmlString, byref(color)); } @@ -36,9 +36,9 @@ namespace UnityEngine { return std::clamp(static_cast(round(colorVal * 255.0f)), 0, UINT8_MAX); } - static Il2CppString* ToHtmlStringRGB(Color color) { + static StringW ToHtmlStringRGB(Color color) { Color32 color2(conv(color.r), conv(color.g), conv(color.b), 1); - return il2cpp_utils::newcsstr(string_format("#%02X%02X%02X", color2.r, color2.g, color2.b)); + return string_format("#%02X%02X%02X", color2.r, color2.g, color2.b); } static std::string ToHtmlStringRGB_CPP(Color color) { diff --git a/MultiQuestensions/src/Assets/Sprites.cpp b/MultiQuestensions/src/Assets/Sprites.cpp index aadbeae..0f6d65c 100644 --- a/MultiQuestensions/src/Assets/Sprites.cpp +++ b/MultiQuestensions/src/Assets/Sprites.cpp @@ -15,7 +15,7 @@ namespace MultiQuestensions { std::string Sprites::Steam64 = "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"; Sprite* CreateSpriteFromBase64(std::string& base64) { - ArrayW bytes = System::Convert::FromBase64String(il2cpp_utils::newcsstr(base64)); + ArrayW bytes = System::Convert::FromBase64String(base64.c_str()); Texture2D* texture = Texture2D::New_ctor(2, 2); if (ImageConversion::LoadImage(texture, bytes, false)) { return Sprite::Create(texture, UnityEngine::Rect(0.0f, 0.0f, (float)texture->get_width(), (float)texture->get_height()), UnityEngine::Vector2(0, 0), 10.0f, 0u, SpriteMeshType::Tight, UnityEngine::Vector4(0.0f, 0.0f, 0.0f, 0.0f), false); diff --git a/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp b/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp index 36dee6b..080cd56 100644 --- a/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp +++ b/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp @@ -11,7 +11,7 @@ DEFINE_TYPE(MultiQuestensions::Beatmaps, PreviewBeatmapStub); namespace MultiQuestensions::Beatmaps { - void PreviewBeatmapStub::FromPreviewPacket(Il2CppString* levelhash, GlobalNamespace::IPreviewBeatmapLevel* level, PreviewBeatmapPacket* lvl) { + void PreviewBeatmapStub::FromPreviewPacket(StringW levelhash, GlobalNamespace::IPreviewBeatmapLevel* level, PreviewBeatmapPacket* lvl) { if (levelhash && level) { getLogger().debug("PreviewBeatmapStub::FromPreview"); @@ -89,7 +89,7 @@ namespace MultiQuestensions::Beatmaps { // } //} - MultiQuestensions::Beatmaps::PreviewBeatmapPacket* PreviewBeatmapStub::GetPacket(Il2CppString* characteristic, GlobalNamespace::BeatmapDifficulty difficulty) { + MultiQuestensions::Beatmaps::PreviewBeatmapPacket* PreviewBeatmapStub::GetPacket(StringW characteristic, GlobalNamespace::BeatmapDifficulty difficulty) { getLogger().debug("Start PreviewBeatmapStub::GetPacket"); MultiQuestensions::Beatmaps::PreviewBeatmapPacket* packet = THROW_UNLESS(il2cpp_utils::New()); @@ -111,23 +111,23 @@ namespace MultiQuestensions::Beatmaps { #pragma region All the pain in form of getter functions - Il2CppString* PreviewBeatmapStub::get_levelID() { + StringW PreviewBeatmapStub::get_levelID() { return levelID; } - Il2CppString* PreviewBeatmapStub::get_songName() { + StringW PreviewBeatmapStub::get_songName() { return songName; } - Il2CppString* PreviewBeatmapStub::get_songSubName() { + StringW PreviewBeatmapStub::get_songSubName() { return songSubName; } - Il2CppString* PreviewBeatmapStub::get_songAuthorName() { + StringW PreviewBeatmapStub::get_songAuthorName() { return songAuthorName; } - Il2CppString* PreviewBeatmapStub::get_levelAuthorName() { + StringW PreviewBeatmapStub::get_levelAuthorName() { return levelAuthorName; } diff --git a/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp b/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp index 41ccd3b..c841e42 100644 --- a/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp +++ b/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp @@ -15,18 +15,18 @@ using namespace HMUI; DEFINE_TYPE(MultiQuestensions::Environments, LobbyAvatarNameTag); namespace MultiQuestensions::Environments { - static Il2CppString* BG() { - static auto* bg = il2cpp_utils::newcsstr("BG"); + static StringW BG() { + static StringW bg("BG"); return bg; } - static Il2CppString* Name() { - static auto* name = il2cpp_utils::newcsstr("Name"); + static StringW Name() { + static StringW name("Name"); return name; } - static Il2CppString* Player() { - static auto* player = il2cpp_utils::newcsstr("Player"); + static StringW Player() { + static StringW player("Player"); return player; } @@ -135,7 +135,7 @@ namespace MultiQuestensions::Environments { if (!_playerIcons.contains(slot)) { //getLogger().debug("SetIcon, create new Icon"); - auto iconObj = GameObject::New_ctor(il2cpp_utils::newcsstr(string_format("MQEPlayerIcon(%d)", (int)slot))); + auto iconObj = GameObject::New_ctor(string_format("MQEPlayerIcon(%d)", (int)slot).c_str()); iconObj->get_transform()->SetParent(_bg->get_transform(), false); iconObj->get_transform()->SetSiblingIndex((int)slot); iconObj->set_layer(5); diff --git a/MultiQuestensions/src/Extensions/ExtendedPlayer.cpp b/MultiQuestensions/src/Extensions/ExtendedPlayer.cpp index edd10ae..7e3f495 100644 --- a/MultiQuestensions/src/Extensions/ExtendedPlayer.cpp +++ b/MultiQuestensions/src/Extensions/ExtendedPlayer.cpp @@ -29,22 +29,22 @@ namespace MultiQuestensions::Extensions { ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player) { return THROW_UNLESS(il2cpp_utils::New(player, static_cast(nullptr), 3, DefaultColor, static_cast(nullptr))); } - ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player, Il2CppString* platformID, Platform platform, UnityEngine::Color playerColor) { + ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, UnityEngine::Color playerColor) { return THROW_UNLESS(il2cpp_utils::New(player, platformID, (int)platform, playerColor, static_cast(nullptr))); } - ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player, Il2CppString* platformID, Platform platform, Il2CppString* mpexVersion, UnityEngine::Color playerColor) { + ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, StringW mpexVersion, UnityEngine::Color playerColor) { return THROW_UNLESS(il2cpp_utils::New(player, platformID, (int)platform, playerColor, mpexVersion)); } #pragma endregion #pragma region Getters - Il2CppString* ExtendedPlayer::get_platformID() { + StringW ExtendedPlayer::get_platformID() { return platformID; } Platform ExtendedPlayer::get_platform() { return platform; } - Il2CppString* ExtendedPlayer::get_mpexVersion() { + StringW ExtendedPlayer::get_mpexVersion() { return mpexVersion; } @@ -52,11 +52,11 @@ namespace MultiQuestensions::Extensions { return _connectedPlayer->get_isMe(); } - Il2CppString* ExtendedPlayer::get_userId() { + StringW ExtendedPlayer::get_userId() { return _connectedPlayer->get_userId(); } - Il2CppString* ExtendedPlayer::get_userName() { + StringW ExtendedPlayer::get_userName() { return _connectedPlayer->get_userName(); } @@ -92,7 +92,7 @@ namespace MultiQuestensions::Extensions { return _connectedPlayer->get_disconnectedReason(); } - bool ExtendedPlayer::HasState(Il2CppString* state) { + bool ExtendedPlayer::HasState(StringW state) { return _connectedPlayer->HasState(state); } #pragma endregion @@ -130,7 +130,7 @@ namespace MultiQuestensions::Extensions { getLogger().debug("Deserialize ExtendedPlayerPacket done"); } - ExtendedPlayerPacket* ExtendedPlayerPacket::Init(Il2CppString* platformID, Platform platform, UnityEngine::Color playerColor) + ExtendedPlayerPacket* ExtendedPlayerPacket::Init(StringW platformID, Platform platform, UnityEngine::Color playerColor) { auto extendedPlayer = THROW_UNLESS(il2cpp_utils::New()); diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index 72c9c4a..c411a08 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -51,7 +51,7 @@ namespace MultiQuestensions { MultiplayerLobbyAvatarManager* _avatarManager; - Dictionary_2* _refPlayerIdToAvatarMap; + Dictionary_2* _refPlayerIdToAvatarMap; #pragma endregion #pragma region LobbyAvatarPlaceLigting @@ -190,7 +190,7 @@ namespace MultiQuestensions { #pragma endregion #pragma region LobbyAvatarNameTag - MultiplayerLobbyAvatarController* GetAvatarController(Il2CppString* userId) + MultiplayerLobbyAvatarController* GetAvatarController(StringW userId) { //getLogger().debug("Start GetAvatarController: _refPlayerIdToAvatarMap"); if (_refPlayerIdToAvatarMap == nullptr && _avatarManager) @@ -209,10 +209,10 @@ namespace MultiQuestensions { return nullptr; } - GameObject* GetAvatarCaptionObject(Il2CppString* userId) + GameObject* GetAvatarCaptionObject(StringW userId) { auto avatarController = GetAvatarController(userId); - if (avatarController) return avatarController->get_transform()->Find(il2cpp_utils::newcsstr("AvatarCaption"))->get_gameObject(); + if (avatarController) return avatarController->get_transform()->Find("AvatarCaption")->get_gameObject(); else return nullptr; } @@ -232,7 +232,7 @@ namespace MultiQuestensions { //getLogger().debug("CreateOrUpdateNameTag player type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); if (!(il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass) || il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass))) { - getLogger().error("CreateOrUpdateNameTag unknown type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); + getLogger().error("REPORT TO ENDER: CreateOrUpdateNameTag unknown type: %s, this shouldn't happen!!!", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); return; } @@ -256,9 +256,9 @@ namespace MultiQuestensions { } void HandleLobbyAvatarCreated(IConnectedPlayer* player) { - const std::string userId = to_utf8(csstrtostr(player->get_userId())); - if (_extendedPlayers.contains(userId)) - player = reinterpret_cast(_extendedPlayers.at(userId)->get_self()); + //const std::string userId = player->get_userId(); + if (_extendedPlayers.contains(player->get_userId())) + player = reinterpret_cast(_extendedPlayers.at(player->get_userId())->get_self()); CreateOrUpdateNameTag(player); } diff --git a/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp b/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp index 201fd3e..9971fee 100644 --- a/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp @@ -24,7 +24,6 @@ namespace MultiQuestensions { auto* takeResult = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), Enumerable_Take, reinterpret_cast*>(resultsData), 5); - static auto* Enumerable_ToList_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "ToList", 1)); static auto* Enumerable_ToList = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_ToList_Generic, { classof(MultiplayerPlayerResultsData*) })); List* newResultsData = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), diff --git a/MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp b/MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp index 2249fe8..1e5ee64 100644 --- a/MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp +++ b/MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp @@ -39,9 +39,9 @@ namespace MultiQuestensions { } // Subscribe this method to 'menuRpcManager.setIsEntitledToLevelEvent' when on NetworkPlayerEntitlementChecker.Start, unsub on destroy - static void HandleEntitlementReceived(Il2CppString* userId, Il2CppString* levelId, EntitlementsStatus entitlement) { - std::string cUserId = to_utf8(csstrtostr(userId)); - std::string cLevelId = to_utf8(csstrtostr(levelId)); + static void HandleEntitlementReceived(StringW userId, StringW levelId, EntitlementsStatus entitlement) { + std::string cUserId = userId; + std::string cLevelId = levelId; getLogger().debug("[HandleEntitlementReceived] Received Entitlement from user '%s' for level '%s' with status '%s'", cUserId.c_str(), @@ -85,9 +85,9 @@ namespace MultiQuestensions { } #pragma region Hooks - MAKE_HOOK_MATCH(NetworkPlayerEntitlementChecker_GetEntitlementStatus, &NetworkPlayerEntitlementChecker::GetEntitlementStatus, Task_1*, NetworkPlayerEntitlementChecker* self, Il2CppString* levelIdCS) { + MAKE_HOOK_MATCH(NetworkPlayerEntitlementChecker_GetEntitlementStatus, &NetworkPlayerEntitlementChecker::GetEntitlementStatus, Task_1*, NetworkPlayerEntitlementChecker* self, StringW levelIdCS) { missingLevelText.clear(); - std::string levelId = to_utf8(csstrtostr(levelIdCS)); + std::string levelId = levelIdCS; getLogger().info("NetworkPlayerEntitlementChecker_GetEntitlementStatus: %s", levelId.c_str()); if (IsCustomLevel(levelId)) { if (HasSong(levelId)) { @@ -161,7 +161,7 @@ namespace MultiQuestensions { // }); //self->rpcManager->add_setIsEntitledToLevelEvent(entitlementAction); self->dyn__rpcManager()->add_setIsEntitledToLevelEvent( - il2cpp_utils::MakeDelegate*>(classof(System::Action_3<::Il2CppString*, ::Il2CppString*, EntitlementsStatus>*), (std::function) [&](Il2CppString* userId, Il2CppString* beatmapId, EntitlementsStatus status) { + il2cpp_utils::MakeDelegate*>(classof(System::Action_3<::StringW, ::StringW, EntitlementsStatus>*), (std::function) [&](StringW userId, StringW beatmapId, EntitlementsStatus status) { HandleEntitlementReceived(userId, beatmapId, status); })); NetworkPlayerEntitlementChecker_Start(self); diff --git a/MultiQuestensions/src/Hooks/QuickplayHooks.cpp b/MultiQuestensions/src/Hooks/QuickplayHooks.cpp index 3477d56..ad0157a 100644 --- a/MultiQuestensions/src/Hooks/QuickplayHooks.cpp +++ b/MultiQuestensions/src/Hooks/QuickplayHooks.cpp @@ -7,8 +7,9 @@ #include "GlobalNamespace/MasterServerQuickPlaySetupData_QuickPlaySongPacksOverride_LocalizedCustomPackName.hpp" #include "GlobalNamespace/MasterServerQuickPlaySetupData_QuickPlaySongPacksOverride.hpp" #include "GlobalNamespace/MasterServerQuickPlaySetupData.hpp" +#include "GlobalNamespace/BloomFilterUtil.hpp" -#include "CodegenExtensions/TempBloomFilterUtil.hpp" +//#include "CodegenExtensions/TempBloomFilterUtil.hpp" //#include "GlobalNamespace/MasterServerQuickPlaySetupModel.hpp" #include "GlobalNamespace/SongPackMaskModelSO.hpp" @@ -42,7 +43,7 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(MultiplayerModeSelectionFlowCoordinator_HandleJoinQuickPlayViewControllerDidFinish, &MultiplayerModeSelectionFlowCoordinator::HandleJoinQuickPlayViewControllerDidFinish, void, MultiplayerModeSelectionFlowCoordinator* self, bool success) { - Il2CppString* levelPackName = self->dyn__joinQuickPlayViewController()->dyn__multiplayerModeSettings()->dyn_quickPlaySongPackMaskSerializedName(); + StringW levelPackName = self->dyn__joinQuickPlayViewController()->dyn__multiplayerModeSettings()->dyn_quickPlaySongPackMaskSerializedName(); if (success && self->dyn__songPackMaskModel()->ToSongPackMask( levelPackName @@ -50,10 +51,10 @@ namespace MultiQuestensions { BloomFilterUtil::ToBloomFilter(getCustomLevelSongPackMaskStr(), 2, 13)) ) { self->dyn__simpleDialogPromptViewController()->Init( - il2cpp_utils::newcsstr("Custom Song Quickplay"), - il2cpp_utils::newcsstr("This category includes songs of varying difficulty.\nIt may be more enjoyable to play in a private lobby with friends."), - il2cpp_utils::newcsstr("Continue"), - il2cpp_utils::newcsstr("Cancel"), + "Custom Song Quickplay", + "This category includes songs of varying difficulty.\nIt may be more enjoyable to play in a private lobby with friends.", + "Continue", + "Cancel", il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function)[self, success](int btnId) { switch (btnId) { diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp index 7ba4911..8381eb4 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp @@ -23,7 +23,7 @@ using namespace GlobalNamespace; // Handles a PreviewBeatmapPacket used to transmit data about a custom song. static void HandlePreviewBeatmapPacket(MultiQuestensions::Beatmaps::PreviewBeatmapPacket* packet, GlobalNamespace::IConnectedPlayer* player) { - getLogger().debug("'%s' selected song '%s'", to_utf8(csstrtostr(player->get_userId())).c_str(), to_utf8(csstrtostr(packet->levelHash)).c_str()); + getLogger().debug("'%s' selected song '%s'", std::string(player->get_userId()).c_str(), std::string(packet->levelHash).c_str()); IPreviewBeatmapLevel* localPreview = lobbyPlayersDataModel->dyn__beatmapLevelsModel()->GetLevelPreviewForLevelId(packet->levelId); MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview; try { @@ -109,14 +109,14 @@ static void HandleExtendedPlayerPacket(MultiQuestensions::Extensions::ExtendedPl } else { getLogger().info("Received 'ExtendedPlayerPacket' from '%s' with platformID: '%s' mpexVersion: '%s'", - to_utf8(csstrtostr(player->get_userId())).c_str(), - to_utf8(csstrtostr(packet->platformID)).c_str(), - to_utf8(csstrtostr(packet->mpexVersion)).c_str() + std::string(player->get_userId()).c_str(), + std::string(packet->platformID).c_str(), + std::string(packet->mpexVersion).c_str() ); Extensions::ExtendedPlayer* extendedPlayer; try { extendedPlayer = Extensions::ExtendedPlayer::CS_ctor(player, packet->platformID, packet->platform, packet->mpexVersion, packet->playerColor); - if (to_utf8(csstrtostr(extendedPlayer->mpexVersion)) != MPEX_PROTOCOL) + if (std::string(extendedPlayer->mpexVersion) != MPEX_PROTOCOL) { getLogger().warning( "###################################################################\r\n" @@ -124,8 +124,8 @@ static void HandleExtendedPlayerPacket(MultiQuestensions::Extensions::ExtendedPl "The player '%s' is using MpEx protocol version %s while you are using MpEx protocol " MPEX_PROTOCOL "\r\n" "For best compatibility all players should use a compatible version of MultiplayerExtensions/MultiQuestensions.\r\n" "###################################################################", - to_utf8(csstrtostr(player->get_userName())).c_str(), - to_utf8(csstrtostr(extendedPlayer->mpexVersion)).c_str() + std::string(player->get_userName()).c_str(), + std::string(extendedPlayer->mpexVersion).c_str() ); } } @@ -153,7 +153,7 @@ void HandlePlayerConnected(IConnectedPlayer* player) { try { getLogger().debug("HandlePlayerConnected"); if (player) { - const std::string userId = to_utf8(csstrtostr(player->get_userId())); + const std::string userId = player->get_userId(); getLogger().info("Player '%s' joined", userId.c_str()); getLogger().debug("Sending ExtendedPlayerPacket"); if (localExtendedPlayer->get_platformID() != nullptr) @@ -173,10 +173,10 @@ void HandlePlayerConnected(IConnectedPlayer* player) { } void HandlePlayerDisconnected(IConnectedPlayer* player) { - getLogger().info("Player '%s' left", to_utf8(csstrtostr(player->get_userId())).c_str()); + getLogger().info("Player '%s' left", std::string(player->get_userId()).c_str()); getLogger().debug("Reseting platform lights"); SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); - _extendedPlayers.erase(to_utf8(csstrtostr(player->get_userId())).c_str()); + _extendedPlayers.erase(std::string(player->get_userId()).c_str()); } //void HandleDisconnect(DisconnectedReason* reason) { diff --git a/MultiQuestensions/src/Packets/PacketSerializer.cpp b/MultiQuestensions/src/Packets/PacketSerializer.cpp index 88847f0..53fe680 100644 --- a/MultiQuestensions/src/Packets/PacketSerializer.cpp +++ b/MultiQuestensions/src/Packets/PacketSerializer.cpp @@ -21,7 +21,7 @@ namespace MultiQuestensions { Il2CppReflectionType* packetType = il2cpp_utils::GetSystemType(il2cpp_functions::object_get_class(reinterpret_cast(packet))); getLogger().debug("Serialize packetType is: %s", to_utf8(csstrtostr(packetType->ToString())).c_str()); getLogger().debug("Registered types check: %s", registeredTypes[packetType].c_str()); - writer->Put(il2cpp_utils::newcsstr(registeredTypes[packetType])); + writer->Put(StringW(registeredTypes[packetType])); //writer->Put(packetType->ToString()); getLogger().debug("Writer Put"); getLogger().debug("Nullptr checking: packet: %p, writer: %p", packet, writer); @@ -32,7 +32,7 @@ namespace MultiQuestensions { void PacketSerializer::Deserialize(LiteNetLib::Utils::NetDataReader* reader, int length, GlobalNamespace::IConnectedPlayer* data) { getLogger().debug("PacketSerializer::Deserialize"); int prevPosition = reader->get_Position(); - std::string packetType = to_utf8(csstrtostr(reader->GetString())); + std::string packetType = reader->GetString(); getLogger().debug("packetType: %s", packetType.c_str()); length -= reader->get_Position() - prevPosition; getLogger().debug("length: %d", length); diff --git a/MultiQuestensions/src/UI/CenterScreenLoading.cpp b/MultiQuestensions/src/UI/CenterScreenLoading.cpp index 09fd117..8619a19 100644 --- a/MultiQuestensions/src/UI/CenterScreenLoading.cpp +++ b/MultiQuestensions/src/UI/CenterScreenLoading.cpp @@ -54,8 +54,8 @@ namespace MultiQuestensions::UI{ getLogger().info("CenterScreenLoading::ShowLoading, players ready (%d of %d)", readyPlayers, maxPlayers); if (loadingControl) { - loadingControl->ShowLoading(il2cpp_utils::newcsstr(string_format("%d of %d players ready...", - readyPlayers, maxPlayers))); + loadingControl->ShowLoading(string_format("%d of %d players ready...", + readyPlayers, maxPlayers).c_str()); } } @@ -84,8 +84,8 @@ namespace MultiQuestensions::UI{ else if (screenController->get_countdownShown() && gameStateController && sessionManager->get_syncTime() >= gameStateController->get_startTime() && gameStateController->get_levelStartInitiated()) { if (loadingControl) - loadingControl->ShowLoading(il2cpp_utils::newcsstr(string_format("%d of %d players ready...", - playersReady + 1, sessionManager ? sessionManager->get_connectedPlayerCount() + 1 : 1))); + loadingControl->ShowLoading(string_format("%d of %d players ready...", + playersReady + 1, sessionManager ? sessionManager->get_connectedPlayerCount() + 1 : 1).c_str()); } else { diff --git a/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp b/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp index 524c529..226ef38 100644 --- a/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp +++ b/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp @@ -34,15 +34,15 @@ namespace MultiQuestensions::UI { if (cover && level) { // "" + map.GetMetadata().GetSongAuthorName() + "" + " [" + map.GetMetadata().GetLevelAuthorName() + "]" list->data.emplace_back(CustomListTableData::CustomCellInfo{ - level->get_songName() ? to_utf8(csstrtostr(level->get_songName())) : "Error: songName null", - (level->get_songAuthorName() ? to_utf8(csstrtostr(level->get_songAuthorName())) : std::string()) + " [" + (level->get_levelAuthorName() ? to_utf8(csstrtostr(level->get_levelAuthorName())) : std::string()) + "]", + level->get_songName() ? std::string(level->get_songName()) : "Error: songName null", + (level->get_songAuthorName() ? std::string(level->get_songAuthorName()) : std::string()) + " [" + (level->get_levelAuthorName() ? std::string(level->get_levelAuthorName()) : std::string()) + "]", cover }); } else if (level) { list->data.emplace_back(CustomListTableData::CustomCellInfo{ - level->get_songName() ? to_utf8(csstrtostr(level->get_songName())) : "Error: songName null", - (level->get_songAuthorName() ? to_utf8(csstrtostr(level->get_songAuthorName())) : std::string()) + " [" + (level->get_levelAuthorName() ? to_utf8(csstrtostr(level->get_levelAuthorName())) : std::string()) + "]", + level->get_songName() ? std::string(level->get_songName()) : "Error: songName null", + (level->get_songAuthorName() ? std::string(level->get_songAuthorName()) : std::string()) + " [" + (level->get_levelAuthorName() ? std::string(level->get_levelAuthorName()) : std::string()) + "]", level->get_defaultCoverImage() }); } else getLogger().error("Nullptr in UI: cover '%p', level '%p'", cover, level); diff --git a/MultiQuestensions/src/UI/LobbySetupPanel.cpp b/MultiQuestensions/src/UI/LobbySetupPanel.cpp index 0382747..4d7505a 100644 --- a/MultiQuestensions/src/UI/LobbySetupPanel.cpp +++ b/MultiQuestensions/src/UI/LobbySetupPanel.cpp @@ -60,7 +60,7 @@ namespace MultiQuestensions::UI { { -40, 0 })->set_alignment(TMPro::TextAlignmentOptions::Left); getLogger().warning("Chroma outdated"); } - else getLogger().debug("Chroma not installed or version compatible"); + else getLogger().debug("Chroma not installed or version incompatible"); // diff --git a/MultiQuestensions/src/Utils/CustomData.cpp b/MultiQuestensions/src/Utils/CustomData.cpp index 7249116..86f0e62 100644 --- a/MultiQuestensions/src/Utils/CustomData.cpp +++ b/MultiQuestensions/src/Utils/CustomData.cpp @@ -47,7 +47,7 @@ namespace MultiQuestensions::Utils { } } } - if (dB["_customData"].HasMember("_suggestions") && dB["_customData"]["_suggestions"].IsArray() && + /*if (dB["_customData"].HasMember("_suggestions") && dB["_customData"]["_suggestions"].IsArray() && !dB["_customData"]["_suggestions"].Empty()) { for (auto& sug : dB["_customData"]["_suggestions"].GetArray()) { getLogger().debug("Found suggestion: %s", sug.GetString()); @@ -58,7 +58,7 @@ namespace MultiQuestensions::Utils { } getLogger().debug("Checking bools 'All players have chroma': %s, 'MatchesVersion': %s 'Combined check': %s", AllPlayersHaveChroma() ? "true" : "false", MatchesVersion(ChromaID, ChromaVersionRange) ? "true" : "false", (!AllPlayersHaveChroma() || !MatchesVersion(ChromaID, ChromaVersionRange)) ? "true" : "false"); } - } + }*/ } else getLogger().warning("No _customData or _requirements/_suggestions empty/not an array"); } diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 68197ae..98421bd 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -14,6 +14,9 @@ #include "GlobalNamespace/MultiplayerLevelSelectionFlowCoordinator.hpp" #include "GlobalNamespace/CenterStageScreenController.hpp" +// For Hooking Debug Loggers +#include "GlobalNamespace/BGNetDebug.hpp" + #include "beatsaber-hook/shared/utils/il2cpp-utils.hpp" #include "custom-types/shared/register.hpp" #include "questui/shared/QuestUI.hpp" @@ -52,16 +55,16 @@ Logger& getLogger() { // Converts a levelId to a levelHash -Il2CppString* LevelIdToHash(Il2CppString* levelId) { +StringW LevelIdToHash(StringW levelId) { if (Il2CppString::IsNullOrWhiteSpace(levelId)) { return nullptr; } - ArrayW ary = levelId->Split(reinterpret_cast('_'), ' '); - Il2CppString* hash = nullptr; + ArrayW ary = levelId->Split(std::initializer_list{ '_' }, ' '); + StringW hash = nullptr; if (ary.Length() > 2) { hash = ary[2]; } - return (hash != nullptr && hash->get_Length() == 40) ? hash : nullptr; + return (hash != nullptr && hash->get_Length() == 40) ? hash : StringW(); } @@ -77,28 +80,28 @@ namespace MultiQuestensions { std::string moddedState = "modded"; - Il2CppString* getCustomLevelSongPackMaskStr() { - static Il2CppString* songPackMaskStr = il2cpp_utils::newcsstr("custom_levelpack_CustomLevels"); + StringW getCustomLevelSongPackMaskStr() { + static StringW songPackMaskStr("custom_levelpack_CustomLevels"); return songPackMaskStr; } - Il2CppString* getModdedStateStr() { - static Il2CppString* moddedStateStr = il2cpp_utils::newcsstr("modded"); + StringW getModdedStateStr() { + static StringW moddedStateStr("modded"); return moddedStateStr; } - Il2CppString* getMEStateStr() { - static Il2CppString* moddedStateStr = il2cpp_utils::newcsstr("ME_Installed"); + StringW getMEStateStr() { + static StringW moddedStateStr("ME_Installed"); return moddedStateStr; } - Il2CppString* getNEStateStr() { - static Il2CppString* moddedStateStr = il2cpp_utils::newcsstr("ME_Installed"); + StringW getNEStateStr() { + static StringW moddedStateStr("ME_Installed"); return moddedStateStr; } - Il2CppString* getChromaStateStr() { - static Il2CppString* moddedStateStr = il2cpp_utils::newcsstr("Chroma_Installed"); + StringW getChromaStateStr() { + static StringW moddedStateStr("Chroma_Installed"); return moddedStateStr; } @@ -167,11 +170,11 @@ MAKE_HOOK_MATCH(LobbyPlayersActivate, &LobbyPlayersDataModel::Activate, void, Lo } // LobbyPlayersDataModel SetLocalPlayerBeatmapLevel -MAKE_HOOK_MATCH(LobbyPlayersSetLocalBeatmap, &LobbyPlayersDataModel::SetLocalPlayerBeatmapLevel, void, LobbyPlayersDataModel* self, Il2CppString* levelId, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO* characteristic) { +MAKE_HOOK_MATCH(LobbyPlayersSetLocalBeatmap, &LobbyPlayersDataModel::SetLocalPlayerBeatmapLevel, void, LobbyPlayersDataModel* self, StringW levelId, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO* characteristic) { - Il2CppString* hash = LevelIdToHash(levelId); - if (hash != nullptr) { - getLogger().info("Local user selected song '%s'.", to_utf8(csstrtostr(hash)).c_str()); + StringW hash = LevelIdToHash(levelId); + if (hash.convert() != nullptr) { + getLogger().info("Local user selected song '%s'.", std::string(hash).c_str()); MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview = GetExistingPreview(levelId); if (preview != nullptr) { self->SetPlayerBeatmapLevel(self->get_localUserId(), reinterpret_cast(preview), beatmapDifficulty, characteristic); @@ -185,7 +188,7 @@ MAKE_HOOK_MATCH(LobbyPlayersSetLocalBeatmap, &LobbyPlayersDataModel::SetLocalPla using namespace MultiQuestensions::Beatmaps; PreviewBeatmapStub* previewStub = THROW_UNLESS(il2cpp_utils::New(hash, localIPreview, static_cast(nullptr))); //MultiQuestensions::Beatmaps::PreviewBeatmapStub* previewStub = MultiQuestensions::Beatmaps::PreviewBeatmapStub::New_ctor(hash, localIPreview); - getLogger().debug("Check 'LobbyPlayersSetLocalBeatmap' levelID: %s", to_utf8(csstrtostr(reinterpret_cast(previewStub)->get_levelID())).c_str()); + getLogger().debug("Check 'LobbyPlayersSetLocalBeatmap' levelID: %s", std::string(reinterpret_cast(previewStub)->get_levelID()).c_str()); self->SetPlayerBeatmapLevel(self->get_localUserId(), reinterpret_cast(previewStub), beatmapDifficulty, characteristic); PreviewBeatmapPacket* packet = previewStub->GetPacket(characteristic->get_serializedName(), beatmapDifficulty); self->dyn__menuRpcManager()->RecommendBeatmap(BeatmapIdentifierNetSerializable::New_ctor(levelId, characteristic->get_serializedName(), beatmapDifficulty)); @@ -206,8 +209,8 @@ std::string GetHash(const std::string& levelId) { } // LobbyPlayersDataModel HandleMenuRpcManagerSelectedBeatmap (DONT REMOVE THIS, without it a player's selected map will be cleared) -MAKE_HOOK_MATCH(LobbyPlayersSelectedBeatmap, &LobbyPlayersDataModel::HandleMenuRpcManagerRecommendBeatmap, void, LobbyPlayersDataModel* self, Il2CppString* userId, BeatmapIdentifierNetSerializable* beatmapId) { - getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: LevelID: %s", to_utf8(csstrtostr(beatmapId->get_levelID())).c_str()); +MAKE_HOOK_MATCH(LobbyPlayersSelectedBeatmap, &LobbyPlayersDataModel::HandleMenuRpcManagerRecommendBeatmap, void, LobbyPlayersDataModel* self, StringW userId, BeatmapIdentifierNetSerializable* beatmapId) { + getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: LevelID: %s", std::string(beatmapId->get_levelID()).c_str()); MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview = GetExistingPreview(beatmapId->get_levelID()); if (preview != nullptr) { getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: Preview exists, SetPlayerBeatmapLevel"); @@ -283,7 +286,7 @@ MAKE_HOOK_MATCH(MultiplayerLobbyConnectionController_CreateParty, &MultiplayerLo // Show the custom levels tab in multiplayer MAKE_HOOK_MATCH(LevelSelectionNavigationController_Setup, &LevelSelectionNavigationController::Setup, void, LevelSelectionNavigationController* self, SongPackMask songPackMask, BeatmapDifficultyMask allowedBeatmapDifficultyMask, ::ArrayW notAllowedCharacteristics, - bool hidePacksIfOneOrNone, bool hidePracticeButton, ::Il2CppString* actionButtonText, IBeatmapLevelPack* levelPackToBeSelectedAfterPresent, + bool hidePacksIfOneOrNone, bool hidePracticeButton, ::StringW actionButtonText, IBeatmapLevelPack* levelPackToBeSelectedAfterPresent, SelectLevelCategoryViewController::LevelCategory startLevelCategory, IPreviewBeatmapLevel* beatmapLevelToBeSelectedAfterPresent, bool enableCustomLevels) { getLogger().info("LevelSelectionNavigationController_Setup setting custom songs . . ."); LevelSelectionNavigationController_Setup(self, songPackMask, allowedBeatmapDifficultyMask, notAllowedCharacteristics, hidePacksIfOneOrNone, hidePracticeButton, @@ -294,7 +297,7 @@ static bool isMissingLevel = false; // This hook makes sure to grey-out the play button so that players can't start a level that someone doesn't have. // This prevents crashes. -MAKE_HOOK_MATCH(LobbySetupViewController_SetPlayersMissingLevelText , &LobbySetupViewController::SetPlayersMissingLevelText, void, LobbySetupViewController* self, Il2CppString* playersMissingLevelText) { +MAKE_HOOK_MATCH(LobbySetupViewController_SetPlayersMissingLevelText , &LobbySetupViewController::SetPlayersMissingLevelText, void, LobbySetupViewController* self, StringW playersMissingLevelText) { getLogger().info("LobbySetupViewController_SetPlayersMissingLevelText"); if (!missingLevelText.empty()) { getLogger().info("Disabling start game as entitlements missing level text exists . . ."); @@ -460,7 +463,7 @@ MAKE_HOOK_MATCH(LobbyGameStateController_HandleMultiplayerLevelLoaderCountdownFi // Checks each player, to see if they're in the lobby, and if they are, checks their entitlement status. MultiQuestensions::UI::CenterScreenLoading::playersReady = 0; for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - Il2CppString* csUserID = sessionManager->dyn__connectedPlayers()->get_Item(i)->get_userId(); + StringW csUserID = sessionManager->dyn__connectedPlayers()->get_Item(i)->get_userId(); std::string UserID = to_utf8(csstrtostr(csUserID)); if (self->dyn__lobbyPlayersDataModel()->GetPlayerIsInLobby(csUserID)) { if (entitlementDictionary[UserID][LevelID] != EntitlementsStatus::Ok) entitlementStatusOK = false; @@ -577,6 +580,21 @@ extern "C" void setup(ModInfo& info) { getLogger().info("Completed setup!"); } +MAKE_HOOK_MATCH(BGNetDebug_Log, &GlobalNamespace::BGNetDebug::Log, void, StringW message) { + getLogger().WithContext("BGNetDebug::Log").debug("%s", std::string(message).c_str()); + BGNetDebug_Log(message); +} + +MAKE_HOOK_MATCH(BGNetDebug_LogError, &GlobalNamespace::BGNetDebug::LogError, void, StringW message) { + getLogger().WithContext("BGNetDebug::LogError").error("%s", std::string(message).c_str()); + BGNetDebug_LogError(message); +} + +MAKE_HOOK_MATCH(BGNetDebug_LogWarning, &GlobalNamespace::BGNetDebug::LogWarning, void, StringW message) { + getLogger().WithContext("BGNetDebug::LogWarning").warning("%s", std::string(message).c_str()); + BGNetDebug_LogWarning(message); +} + // Called later on in the game loading - a good time to install function hooks extern "C" void load() { il2cpp_functions::Init(); @@ -615,6 +633,10 @@ extern "C" void load() { //INSTALL_HOOK(getLogger(), MenuRpcManager_InvokeStartLevel); //INSTALL_HOOK(getLogger(), LobbyGameStateController_HandleMenuRpcManagerSetCountdownEndTime); //INSTALL_HOOK(getLogger(), ConnectedPlayerManager_HandleSyncTimePacket); + + INSTALL_HOOK(getLogger(), BGNetDebug_Log); + INSTALL_HOOK(getLogger(), BGNetDebug_LogError); + INSTALL_HOOK(getLogger(), BGNetDebug_LogWarning); #pragma endregion From 62ac0d9f39777f2356f533ac3660452672a8b226 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:36:23 +0200 Subject: [PATCH 03/56] Add oculus-debugger configuration --- .vscode/launch.json | 72 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 7a9dfa0..f18feed 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,12 +4,76 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { - "type": "pwa-chrome", + "name": "Launch Beat Saber", + "type": "fb-lldb", "request": "launch", - "name": "Launch Chrome against localhost", - "url": "http://localhost:8080", - "webRoot": "${workspaceFolder}" + "android": { + "application": { + "package": "com.beatgames.beatsaber", + "activity": "com.unity3d.player.UnityPlayerActivity" + }, + "lldbConfig": { + "sourceMaps": [ + "\\home\\runner\\work\\MultiplayerCore.Quest\\MultiplayerCore.Quest\\ ${workspaceFolder}/../", + "/home/runner/work/MultiplayerCore.Quest/MultiplayerCore.Quest/ ${workspaceFolder}/../", + "\\home\\runner\\work\\MultiQuestensions\\MultiQuestensions\\ ${workspaceFolder}/MultiQuestensions/", + "/home/runner/work/MultiQuestensions/ ${workspaceFolder}/MultiQuestensions/", + "/home/runner/work/SongDownloader/ ${workspaceFolder}/../", + "/home/runner/work/SongDownloader/SongDownloader/shared ${workspaceFolder}/extern/includes/SongDownloader/shared", + "/home/runner/work/SongLoader/ ${workspaceFolder}/../", + "/home/runner/work/SongLoader/SongLoader/shared ${workspaceFolder}/extern/includes/SongLoader/shared", + "/home/runner/work/questui/ ${workspaceFolder}/../", + "/home/runner/work/questui/questui/shared ${workspaceFolder}/extern/includes/questui/shared", + "/home/runner/work/beatsaber-hook/ ${workspaceFolder}/../", + "/home/runner/work/beatsaber-hook/beatsaber-hook/ ${workspaceFolder}/extern/includes/beatsaber-hook/", + "/home/runner/work/custom-types/ ${workspaceFolder}/../", + "/home/runner/work/Il2CppQuestTypePatching/Il2CppQuestTypePatching/shared ${workspaceFolder}/extern/includes/custom-types/shared" + ], + "librarySearchPaths": [ + "${workspaceFolder}/build/debug/", + "${workspaceFolder}/extern/libs/", + "${workspaceFolder}/../Symbols/", + "${workspaceFolder}/../MultiplayerCore.Quest/build/debug/", + ] + } + } + }, + { + "name": "Attach to running Beat Saber Instance", + "type": "fb-lldb", + "request": "attach", + "android": { + "application": { + "package": "com.beatgames.beatsaber", + "activity": "com.unity3d.player.UnityPlayerActivity" + }, + "lldbConfig": { + "sourceMaps": [ + "\\home\\runner\\work\\MultiplayerCore.Quest\\MultiplayerCore.Quest\\ ${workspaceFolder}/../", + "/home/runner/work/MultiplayerCore.Quest/MultiplayerCore.Quest/ ${workspaceFolder}/../", + "\\home\\runner\\work\\MultiQuestensions\\MultiQuestensions\\ ${workspaceFolder}/MultiQuestensions/", + "/home/runner/work/MultiQuestensions/ ${workspaceFolder}/MultiQuestensions/", + "/home/runner/work/SongDownloader/ ${workspaceFolder}/../", + "/home/runner/work/SongDownloader/SongDownloader/shared ${workspaceFolder}/extern/includes/SongDownloader/shared", + "/home/runner/work/SongLoader/ ${workspaceFolder}/../", + "/home/runner/work/SongLoader/SongLoader/shared ${workspaceFolder}/extern/includes/SongLoader/shared", + "/home/runner/work/questui/ ${workspaceFolder}/../", + "/home/runner/work/questui/questui/shared ${workspaceFolder}/extern/includes/questui/shared", + "/home/runner/work/beatsaber-hook/ ${workspaceFolder}/../", + "/home/runner/work/beatsaber-hook/beatsaber-hook/ ${workspaceFolder}/extern/includes/beatsaber-hook/", + "/home/runner/work/custom-types/ ${workspaceFolder}/../", + "/home/runner/work/Il2CppQuestTypePatching/Il2CppQuestTypePatching/shared ${workspaceFolder}/extern/includes/custom-types/shared" + ], + "librarySearchPaths": [ + "${workspaceFolder}/build/debug/", + "${workspaceFolder}/extern/libs/", + "${workspaceFolder}/../Symbols/", + "${workspaceFolder}/../MultiplayerCore.Quest/build/debug/", + ] + } + } } ] } \ No newline at end of file From 3b198ed838749c63b135e8c2bfffc87dbff9fed3 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:36:41 +0200 Subject: [PATCH 04/56] Add vscode workspace file --- MultiQuestensions.code-workspace | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 MultiQuestensions.code-workspace diff --git a/MultiQuestensions.code-workspace b/MultiQuestensions.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/MultiQuestensions.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file From 140ae356d17cccd51c899edbb48bf43b041a925a Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:36:51 +0200 Subject: [PATCH 05/56] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e65d98d..c02ccb5 100644 --- a/.gitignore +++ b/.gitignore @@ -348,3 +348,4 @@ ndkbuild.props /MultiQuestensions/log_timestamp *.qmod *.cmake +/build/ From 4fe6da59005b79b31fb6c135b7ee8cd25be98f6d Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:37:23 +0200 Subject: [PATCH 06/56] Update workflow file and build scripts --- .github/workflows/ndk-build.yml | 7 +++---- MultiQuestensions/build.ps1 | 10 ++++------ MultiQuestensions/buildQMOD.ps1 | 1 - MultiQuestensions/mod.template.json | 7 ++++++- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ndk-build.yml b/.github/workflows/ndk-build.yml index 064f1d6..d9ca253 100644 --- a/.github/workflows/ndk-build.yml +++ b/.github/workflows/ndk-build.yml @@ -39,10 +39,9 @@ on: - '!.gitignore' env: - module_id: multiquestensions - version: 0.1.1-Dev-${{ github.run_number }} - bs_hook: 2_3_2 - BS_Version: 1.17.1 + module_id: MultiQuestensions + version: 0.2.0-Dev-${{ github.run_number }} + BS_Version: 1.21.0 #ndkname: android-ndk-r23 jobs: diff --git a/MultiQuestensions/build.ps1 b/MultiQuestensions/build.ps1 index 8bd1d3c..3025e13 100644 --- a/MultiQuestensions/build.ps1 +++ b/MultiQuestensions/build.ps1 @@ -31,7 +31,7 @@ if ((Test-Path "./extern/includes/beatsaber-hook/src/inline-hook/And64InlineHook exit 1; } -echo "Building MultiQuestensions Version: $Version with MpEx Protocol Version: $MpEx_Protocol" +Write-Output "Building MultiQuestensions Version: $Version with MpEx Protocol Version: $MpEx_Protocol" if ($clean.IsPresent) { @@ -41,18 +41,16 @@ if ($clean.IsPresent) } } -$NDKPath = Get-Content $PSScriptRoot/ndkpath.txt - if (($clean.IsPresent) -or (-not (Test-Path -Path "build"))) { - $out = new-item -Path build -ItemType Directory + (new-item -Path build -ItemType Directory) | Out-Null } & qpm-rust package edit --version $Version -cd build +Set-Location build & cmake -G "Ninja" -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DMPEX_PROTOCOL="$MpEx_Protocol" ../ & cmake --build . -j 6 $ExitCode = $LastExitCode -cd .. +Set-Location .. exit $ExitCode \ No newline at end of file diff --git a/MultiQuestensions/buildQMOD.ps1 b/MultiQuestensions/buildQMOD.ps1 index c7ee591..a037a67 100644 --- a/MultiQuestensions/buildQMOD.ps1 +++ b/MultiQuestensions/buildQMOD.ps1 @@ -1,7 +1,6 @@ # Builds a .qmod file for loading with QP if ($args.Count -eq 0) { $ModID = "MultiQuestensions" -$BSHook = "3_6_1" $VERSION = "0.2.0" $BS_Version = "1.21.0" $new_VERSION = Read-Host -Prompt "Input desired mod version (leave empty for default: '$VERSION')" diff --git a/MultiQuestensions/mod.template.json b/MultiQuestensions/mod.template.json index e340106..e1e70d0 100644 --- a/MultiQuestensions/mod.template.json +++ b/MultiQuestensions/mod.template.json @@ -5,13 +5,18 @@ "author": "EnderdracheLP and Goobie", "version": "${version}", "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.19.0", + "packageVersion": "1.21.0", "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", "dependencies": [ { "version": "^1.4.0", "id": "BeatTogether", "downloadIfMissing": "https://github.com/pythonology/BeatTogether.Quest/releases/download/v1.4.0/BeatTogether_v1.4.0.qmod" + }, + { + "version": "^1.0.0", + "id": "MultiplayerCore.Quest", + "downloadIfMissing": "https://github.com/EnderdracheLP/MultiplayerCore.Quest/releases/download/v1.0.0/MultiplayerCore.qmod" } ], "modFiles": [], From 7c04ee87a47a094cd90de56718bcf3d96df655fd Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:37:36 +0200 Subject: [PATCH 07/56] Update qpm.json --- MultiQuestensions/qpm.json | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/MultiQuestensions/qpm.json b/MultiQuestensions/qpm.json index 4fd98f3..d229882 100644 --- a/MultiQuestensions/qpm.json +++ b/MultiQuestensions/qpm.json @@ -3,7 +3,7 @@ "dependenciesDir": "extern", "info": { "name": "MultiQuestensions", - "id": "multiquestensions", + "id": "MultiQuestensions", "version": "0.2.0", "url": "", "additionalData": { @@ -13,7 +13,7 @@ "dependencies": [ { "id": "beatsaber-hook", - "versionRange": "^3.6.7", + "versionRange": "=3.7.4", "additionalData": { "extraFiles": [ "src/inline-hook" @@ -22,17 +22,12 @@ }, { "id": "codegen", - "versionRange": "^0.19.3", + "versionRange": "^0.22.0", "additionalData": {} }, { "id": "custom-types", - "versionRange": "^0.15.6", - "additionalData": {} - }, - { - "id": "songloader", - "versionRange": "^0.8.3", + "versionRange": "^0.15.9", "additionalData": {} }, { @@ -45,11 +40,6 @@ "versionRange": "^0.2.3", "additionalData": {} }, - { - "id": "cpp-semver", - "versionRange": "*", - "additionalData": {} - }, { "id": "modloader", "versionRange": "*", From a0f43906ff654edfbe75ca2cc6d682052dddad95 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:37:53 +0200 Subject: [PATCH 08/56] Add Config.hpp --- MultiQuestensions/include/Config.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 MultiQuestensions/include/Config.hpp diff --git a/MultiQuestensions/include/Config.hpp b/MultiQuestensions/include/Config.hpp new file mode 100644 index 0000000..0421148 --- /dev/null +++ b/MultiQuestensions/include/Config.hpp @@ -0,0 +1,16 @@ +#pragma once +#include "UnityEngine/Color.hpp" + +namespace MultiQuestensions { + struct Config { + static constexpr UnityEngine::Color DefaultPlayerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f, 1.0f); + + bool Hologram = true; + bool LagReducer = false; + bool MissLighting = true; + UnityEngine::Color PlayerColor = DefaultPlayerColor; + UnityEngine::Color MissColor = UnityEngine::Color(1, 0, 0, 1); + }; + + extern Config config; +} \ No newline at end of file From 7cb6796693c5c1b66406148d4342cc0dd2ec27d8 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:39:19 +0200 Subject: [PATCH 09/56] Remove unused files --- .../include/Beatmaps/PreviewBeatmapPacket.hpp | 40 --- .../include/Beatmaps/PreviewBeatmapStub.hpp | 81 ------ MultiQuestensions/include/CS_DataStore.hpp | 27 -- .../Environments/LobbyAvatarNameTag.hpp | 36 --- .../Environments/LobbyAvatarPlaceLighting.hpp | 25 -- .../include/Extensions/ExtendedPlayer.hpp | 120 --------- .../include/Packets/Callback.hpp | 63 ----- .../include/Packets/PacketManager.hpp | 62 ----- .../include/Packets/PacketSerializer.hpp | 79 ------ .../include/UI/CenterScreenLoading.hpp | 28 -- .../include/UI/DownloadedSongsGSM.hpp | 37 --- .../CodegenExtensions/TempBloomFilterUtil.hpp | 14 - MultiQuestensions/shared/Utils/CustomData.hpp | 7 - .../shared/Utils/SemVerChecker.hpp | 39 --- .../src/Beatmaps/PreviewBeatmapPacket.cpp | 58 ----- .../src/Beatmaps/PreviewBeatmapStub.cpp | 176 ------------- MultiQuestensions/src/CS_DataStore.cpp | 35 --- .../src/Environments/LobbyAvatarNameTag.cpp | 176 ------------- .../Environments/LobbyAvatarPlaceLighting.cpp | 73 ------ .../src/Extensions/ExtendedPlayer.cpp | 144 ----------- .../src/Hooks/MaxPlayerHooks.cpp | 209 --------------- .../NetworkPlayerEntitlementCheckerHooks.cpp | 183 -------------- .../src/Hooks/QuickplayHooks.cpp | 116 --------- .../SessionManagerAndExtendedPlayerHooks.cpp | 239 ------------------ .../src/Packets/PacketManager.cpp | 43 ---- .../src/Packets/PacketSerializer.cpp | 79 ------ .../src/UI/CenterScreenLoading.cpp | 98 ------- .../src/UI/DownloadedSongsGSM.cpp | 159 ------------ MultiQuestensions/src/Utils/CustomData.cpp | 73 ------ 29 files changed, 2519 deletions(-) delete mode 100644 MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp delete mode 100644 MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp delete mode 100644 MultiQuestensions/include/CS_DataStore.hpp delete mode 100644 MultiQuestensions/include/Environments/LobbyAvatarNameTag.hpp delete mode 100644 MultiQuestensions/include/Environments/LobbyAvatarPlaceLighting.hpp delete mode 100644 MultiQuestensions/include/Extensions/ExtendedPlayer.hpp delete mode 100644 MultiQuestensions/include/Packets/Callback.hpp delete mode 100644 MultiQuestensions/include/Packets/PacketManager.hpp delete mode 100644 MultiQuestensions/include/Packets/PacketSerializer.hpp delete mode 100644 MultiQuestensions/include/UI/CenterScreenLoading.hpp delete mode 100644 MultiQuestensions/include/UI/DownloadedSongsGSM.hpp delete mode 100644 MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp delete mode 100644 MultiQuestensions/shared/Utils/CustomData.hpp delete mode 100644 MultiQuestensions/shared/Utils/SemVerChecker.hpp delete mode 100644 MultiQuestensions/src/Beatmaps/PreviewBeatmapPacket.cpp delete mode 100644 MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp delete mode 100644 MultiQuestensions/src/CS_DataStore.cpp delete mode 100644 MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp delete mode 100644 MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp delete mode 100644 MultiQuestensions/src/Extensions/ExtendedPlayer.cpp delete mode 100644 MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp delete mode 100644 MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp delete mode 100644 MultiQuestensions/src/Hooks/QuickplayHooks.cpp delete mode 100644 MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp delete mode 100644 MultiQuestensions/src/Packets/PacketManager.cpp delete mode 100644 MultiQuestensions/src/Packets/PacketSerializer.cpp delete mode 100644 MultiQuestensions/src/UI/CenterScreenLoading.cpp delete mode 100644 MultiQuestensions/src/UI/DownloadedSongsGSM.cpp delete mode 100644 MultiQuestensions/src/Utils/CustomData.cpp diff --git a/MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp b/MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp deleted file mode 100644 index 2d2f5a9..0000000 --- a/MultiQuestensions/include/Beatmaps/PreviewBeatmapPacket.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "main.hpp" -#include "custom-types/shared/types.hpp" -#include "custom-types/shared/macros.hpp" - -#include "LiteNetLib/Utils/NetDataReader.hpp" -#include "LiteNetLib/Utils/NetDataWriter.hpp" -#include "LiteNetLib/Utils/INetSerializable.hpp" -#include "GlobalNamespace/ThreadStaticPacketPool_1.hpp" -#include "GlobalNamespace/PacketPool_1.hpp" -#include "GlobalNamespace/IPoolablePacket.hpp" - -#define PBPInterfaces { classof(LiteNetLib::Utils::INetSerializable*), classof(GlobalNamespace::IPoolablePacket*) } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Beatmaps, PreviewBeatmapPacket, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, - Il2CppObject, "MultiQuestensions::Beatmaps", - PBPInterfaces, 0, nullptr, - DECLARE_CTOR(New); - - // Basic Song Info/Metadata - DECLARE_INSTANCE_FIELD(StringW, levelId); - DECLARE_INSTANCE_FIELD(StringW, levelHash); - DECLARE_INSTANCE_FIELD(StringW, songName); - DECLARE_INSTANCE_FIELD(StringW, songSubName); - DECLARE_INSTANCE_FIELD(StringW, songAuthorName); - DECLARE_INSTANCE_FIELD(StringW, levelAuthorName); - DECLARE_INSTANCE_FIELD(float, beatsPerMinute); - DECLARE_INSTANCE_FIELD(float, songDuration); - - // Selection Info - DECLARE_INSTANCE_FIELD(StringW, characteristic); - DECLARE_INSTANCE_FIELD(uint, difficulty); - - DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(LiteNetLib::Utils::INetSerializable*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); - DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(LiteNetLib::Utils::INetSerializable*), "Deserialize", 1), LiteNetLib::Utils::NetDataReader* reader); - DECLARE_OVERRIDE_METHOD(void, Release, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPoolablePacket*), "Release", 0)); - public: - LiteNetLib::Utils::INetSerializable* ToINetSerializable() noexcept { return reinterpret_cast(this); } -) -#undef PBPInterfaces \ No newline at end of file diff --git a/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp b/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp deleted file mode 100644 index ffc68fb..0000000 --- a/MultiQuestensions/include/Beatmaps/PreviewBeatmapStub.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include "main.hpp" -#include "custom-types/shared/types.hpp" -#include "custom-types/shared/macros.hpp" - -#include "PreviewBeatmapPacket.hpp" -#include "System/Threading/CancellationToken.hpp" -#include "System/Threading/Tasks/Task_1.hpp" -#include "System/Func_2.hpp" -#include "UnityEngine/Sprite.hpp" -#include "UnityEngine/AudioClip.hpp" -#include "UnityEngine/Texture2D.hpp" -#include "UnityEngine/Rect.hpp" -#include "UnityEngine/Vector2.hpp" -#include "UnityEngine/Vector4.hpp" -#include "UnityEngine/SpriteMeshType.hpp" - -#include "GlobalNamespace/EnvironmentInfoSO.hpp" -#include "GlobalNamespace/PreviewDifficultyBeatmapSet.hpp" - -namespace MultiQuestensions::Beatmaps { - enum class DownloadableState { True, False, Unchecked }; -} - -DECLARE_CLASS_INTERFACES(MultiQuestensions::Beatmaps, PreviewBeatmapStub, "System", "Object", sizeof(Il2CppObject), - classof(GlobalNamespace::IPreviewBeatmapLevel*), - - DECLARE_CTOR(FromPreviewPacket, StringW levelhash, GlobalNamespace::IPreviewBeatmapLevel* level, PreviewBeatmapPacket* lvl = nullptr); - //DECLARE_CTOR(FromPreview, Il2CppString* levelHash, GlobalNamespace::IPreviewBeatmapLevel*); - //DECLARE_CTOR(FromPacket, MultiQuestensions::Beatmaps::PreviewBeatmapPacket*); - - DECLARE_INSTANCE_METHOD(MultiQuestensions::Beatmaps::PreviewBeatmapPacket*, GetPacket, StringW, GlobalNamespace::BeatmapDifficulty); - - DECLARE_INSTANCE_FIELD(GlobalNamespace::IPreviewBeatmapLevel*, _preview); - DECLARE_INSTANCE_FIELD(UnityEngine::Sprite*, coverImage); - DECLARE_INSTANCE_FIELD(bool, isDownloaded); - DECLARE_INSTANCE_FIELD(bool, isDownloadable); - - - DECLARE_INSTANCE_FIELD(StringW, levelID); - DECLARE_INSTANCE_FIELD(StringW, levelHash); - - DECLARE_INSTANCE_FIELD(StringW, songName); - DECLARE_INSTANCE_FIELD(StringW, songSubName); - DECLARE_INSTANCE_FIELD(StringW, songAuthorName); - DECLARE_INSTANCE_FIELD(StringW, levelAuthorName); - DECLARE_INSTANCE_FIELD(float, beatsPerMinute); - DECLARE_INSTANCE_FIELD(float, songDuration); - - DECLARE_INSTANCE_FIELD(float, songTimeOffset); - DECLARE_INSTANCE_FIELD(float, previewDuration); - DECLARE_INSTANCE_FIELD(float, previewStartTime); - DECLARE_INSTANCE_FIELD(float, shuffle); - DECLARE_INSTANCE_FIELD(float, shufflePeriod); - DECLARE_INSTANCE_FIELD(GlobalNamespace::EnvironmentInfoSO*, allDirectionsEnvironmentInfo); - DECLARE_INSTANCE_FIELD(GlobalNamespace::EnvironmentInfoSO*, environmentInfo); - DECLARE_INSTANCE_FIELD(Array*, previewDifficultyBeatmapSets); - - DECLARE_OVERRIDE_METHOD(StringW, get_levelID, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_levelID", 0)); - DECLARE_OVERRIDE_METHOD(StringW, get_songName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songName", 0)); - DECLARE_OVERRIDE_METHOD(StringW, get_songSubName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songSubName", 0)); - DECLARE_OVERRIDE_METHOD(StringW, get_songAuthorName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songAuthorName", 0)); - DECLARE_OVERRIDE_METHOD(StringW, get_levelAuthorName, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_levelAuthorName", 0)); - DECLARE_OVERRIDE_METHOD(float, get_beatsPerMinute, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_beatsPerMinute", 0)); - DECLARE_OVERRIDE_METHOD(float, get_songDuration, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songDuration", 0)); - DECLARE_OVERRIDE_METHOD(float, get_songTimeOffset, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_songTimeOffset", 0)); - DECLARE_OVERRIDE_METHOD(float, get_previewDuration, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_previewDuration", 0)); - DECLARE_OVERRIDE_METHOD(float, get_previewStartTime, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_previewStartTime", 0)); - DECLARE_OVERRIDE_METHOD(float, get_shuffle, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_shuffle", 0)); - DECLARE_OVERRIDE_METHOD(float, get_shufflePeriod, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_shufflePeriod", 0)); - DECLARE_OVERRIDE_METHOD(GlobalNamespace::EnvironmentInfoSO*, get_allDirectionsEnvironmentInfo, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_allDirectionsEnvironmentInfo", 0)); - DECLARE_OVERRIDE_METHOD(GlobalNamespace::EnvironmentInfoSO*, get_environmentInfo, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_environmentInfo", 0)); - DECLARE_OVERRIDE_METHOD(Array*, get_previewDifficultyBeatmapSets, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "get_previewDifficultyBeatmapSets", 0)); - - DECLARE_OVERRIDE_METHOD(System::Threading::Tasks::Task_1*, GetCoverImageAsync, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "GetCoverImageAsync", 1), System::Threading::CancellationToken cancellationToken); - //DECLARE_OVERRIDE_METHOD(System::Threading::Tasks::Task_1*, GetPreviewAudioClipAsync, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPreviewBeatmapLevel*), "GetPreviewAudioClipAsync", 1), System::Threading::CancellationToken cancellationToken); - - // C++ Definitions - private: - DownloadableState _downloadable; -) \ No newline at end of file diff --git a/MultiQuestensions/include/CS_DataStore.hpp b/MultiQuestensions/include/CS_DataStore.hpp deleted file mode 100644 index 5f9034a..0000000 --- a/MultiQuestensions/include/CS_DataStore.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include "custom-types/shared/macros.hpp" -#include -#include "GlobalNamespace/IPreviewBeatmapLevel.hpp" -#include "GlobalNamespace/BeatmapDifficulty.hpp" -#include "GlobalNamespace/BeatmapCharacteristicSO.hpp" -#include "GlobalNamespace/IDifficultyBeatmap.hpp" -#include "GlobalNamespace/GameplayModifiers.hpp" - -DECLARE_CLASS_CODEGEN(MultiQuestensions, DataStore, Il2CppObject, - - DECLARE_CTOR(New, GlobalNamespace::IPreviewBeatmapLevel*, GlobalNamespace::BeatmapCharacteristicSO*, GlobalNamespace::IDifficultyBeatmap*, GlobalNamespace::GameplayModifiers*); - - DECLARE_INSTANCE_FIELD(GlobalNamespace::IPreviewBeatmapLevel*, loadingPreviewBeatmapLevel); - DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapCharacteristicSO*, loadingBeatmapCharacteristic); - DECLARE_INSTANCE_FIELD(GlobalNamespace::IDifficultyBeatmap*, loadingDifficultyBeatmap); - DECLARE_INSTANCE_FIELD(GlobalNamespace::GameplayModifiers*, loadingGameplayModifiers); - - static DataStore* instance; - -public: - std::optional loadingBeatmapDifficulty; - - static DataStore* get_Instance(); - static DataStore* CS_Ctor(GlobalNamespace::IPreviewBeatmapLevel* previewBeatmap, GlobalNamespace::BeatmapCharacteristicSO* beatmapCharacteristic, GlobalNamespace::IDifficultyBeatmap* difficultyBeatmap, GlobalNamespace::GameplayModifiers* gameplayModifiers, GlobalNamespace::BeatmapDifficulty beatmapDifficulty); - static void Clear(); -) \ No newline at end of file diff --git a/MultiQuestensions/include/Environments/LobbyAvatarNameTag.hpp b/MultiQuestensions/include/Environments/LobbyAvatarNameTag.hpp deleted file mode 100644 index c67a53b..0000000 --- a/MultiQuestensions/include/Environments/LobbyAvatarNameTag.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include "custom-types/shared/macros.hpp" -#include "Extensions/ExtendedPlayer.hpp" -#include "UnityEngine/MonoBehaviour.hpp" -#include "HMUI/ImageView.hpp" -#include "HMUI/CurvedTextMeshPro.hpp" -#include "GlobalNamespace/IConnectedPlayer.hpp" -#include "UnityEngine/Sprite.hpp" -#include - -DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, LobbyAvatarNameTag, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(GlobalNamespace::IConnectedPlayer*, _playerInfo); - - DECLARE_INSTANCE_FIELD(HMUI::ImageView*, _bg); - DECLARE_INSTANCE_FIELD(HMUI::CurvedTextMeshPro*, _nameText); - - DECLARE_CTOR(New); - - DECLARE_INSTANCE_METHOD(void, Awake); - DECLARE_INSTANCE_METHOD(void, OnEnable); - - DECLARE_INSTANCE_METHOD(void, SetPlayerInfo, GlobalNamespace::IConnectedPlayer* player); - DECLARE_INSTANCE_METHOD(void, SetExtendedPlayerInfo, MultiQuestensions::Extensions::ExtendedPlayer* extendedPlayer); - DECLARE_INSTANCE_METHOD(void, SetSimplePlayerInfo, GlobalNamespace::IConnectedPlayer* simplePlayer); - - enum PlayerIconSlot { - Platform = 0 - }; - - bool _enabled; - - std::map _playerIcons; - - void SetIcon(PlayerIconSlot slot, UnityEngine::Sprite* sprite); - void RemoveIcon(PlayerIconSlot slot); -) \ No newline at end of file diff --git a/MultiQuestensions/include/Environments/LobbyAvatarPlaceLighting.hpp b/MultiQuestensions/include/Environments/LobbyAvatarPlaceLighting.hpp deleted file mode 100644 index dd0f1ad..0000000 --- a/MultiQuestensions/include/Environments/LobbyAvatarPlaceLighting.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "custom-types/shared/macros.hpp" -#include "UnityEngine/MonoBehaviour.hpp" -#include "GlobalNamespace/TubeBloomPrePassLight.hpp" -#include "UnityEngine/Color.hpp" - -DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, LobbyAvatarPlaceLighting, UnityEngine::MonoBehaviour, - std::vector lights; - DECLARE_INSTANCE_FIELD(float, smoothTime); - DECLARE_INSTANCE_FIELD_DEFAULT(UnityEngine::Color, targetColor, UnityEngine::Color::get_black()); - DECLARE_INSTANCE_FIELD_DEFAULT(UnityEngine::Color, TargetColor, targetColor); - - DECLARE_CTOR(New); - - DECLARE_INSTANCE_METHOD(void, OnEnable); - DECLARE_INSTANCE_METHOD(void, OnDisable); - DECLARE_INSTANCE_METHOD(void, Update); - DECLARE_INSTANCE_METHOD(UnityEngine::Color, GetColor); - DECLARE_INSTANCE_METHOD(bool, IsColorVeryCloseToColor, UnityEngine::Color color0, UnityEngine::Color color1); - -public: - void SetColor(const UnityEngine::Color& color, bool immediate); -private: - void SetColor(const UnityEngine::Color& color); -) \ No newline at end of file diff --git a/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp b/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp deleted file mode 100644 index e2a00a0..0000000 --- a/MultiQuestensions/include/Extensions/ExtendedPlayer.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once -#include "custom-types/shared/macros.hpp" -#include "GlobalNamespace/IConnectedPlayer.hpp" -#include "UnityEngine/Color.hpp" -#include "GlobalNamespace/MultiplayerAvatarData.hpp" -#include "GlobalNamespace/DisconnectedReason.hpp" - -#include "LiteNetLib/Utils/NetDataReader.hpp" -#include "LiteNetLib/Utils/NetDataWriter.hpp" -#include "LiteNetLib/Utils/INetSerializable.hpp" -#include "GlobalNamespace/ThreadStaticPacketPool_1.hpp" -#include "GlobalNamespace/PacketPool_1.hpp" -#include "GlobalNamespace/IPoolablePacket.hpp" - -#include - -namespace MultiQuestensions::Extensions { - enum class Platform - { - Unknown = 0, - Steam = 1, - OculusPC = 2, - OculusQuest = 3, - PS4 = 4 - }; -} - -#define EPInterfaces { classof(GlobalNamespace::IConnectedPlayer*) } -___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlayer, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, - Il2CppObject, "MultiplayerExtensions.Extensions", - EPInterfaces, 0, nullptr, - - DECLARE_INSTANCE_FIELD(GlobalNamespace::IConnectedPlayer*, _connectedPlayer); - - /// - /// Platform User ID - /// - DECLARE_INSTANCE_FIELD(StringW, platformID); - DECLARE_INSTANCE_METHOD(StringW, get_platformID); - - /// - /// MultiplayerExtensions version reported by BSIPA. - /// - DECLARE_INSTANCE_FIELD(StringW, mpexVersion); - DECLARE_INSTANCE_METHOD(StringW, get_mpexVersion); - - /// - /// Player's color set in the plugin config. - /// - DECLARE_INSTANCE_FIELD(UnityEngine::Color, playerColor); - - DECLARE_INSTANCE_FIELD(StringW, isPartyOwner); - DECLARE_INSTANCE_FIELD(StringW, hasRecommendBeatmapPermission); - DECLARE_INSTANCE_FIELD(StringW, hasRecommendModifiersPermission); - DECLARE_INSTANCE_FIELD(StringW, hasKickVotePermission); - - DECLARE_CTOR(ExtendedPlayer_ctor, GlobalNamespace::IConnectedPlayer* player, Il2CppString* platformID, int platform, UnityEngine::Color playerColor, Il2CppString* mpexVersion); - - DECLARE_INSTANCE_METHOD(bool, get_isMe); - DECLARE_INSTANCE_METHOD(StringW, get_userId); - DECLARE_INSTANCE_METHOD(StringW, get_userName); - DECLARE_INSTANCE_METHOD(float, get_currentLatency); - DECLARE_INSTANCE_METHOD(bool, get_isConnected); - DECLARE_INSTANCE_METHOD(bool, get_isConnectionOwner); - DECLARE_INSTANCE_METHOD(float, get_offsetSyncTime); - DECLARE_INSTANCE_METHOD(int, get_sortIndex); - DECLARE_INSTANCE_METHOD(bool, get_isKicked); - DECLARE_INSTANCE_METHOD(GlobalNamespace::MultiplayerAvatarData, get_multiplayerAvatarData); - DECLARE_INSTANCE_METHOD(GlobalNamespace::DisconnectedReason, get_disconnectedReason); - DECLARE_INSTANCE_METHOD(bool, HasState, StringW state); - -public: - static const constexpr UnityEngine::Color DefaultColor{ 0.031f, 0.752f, 1.0f, 1.0f }; - - /// - /// Platform - /// - Platform platform = Platform::OculusQuest; - Platform get_platform(); - - static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player); - static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, UnityEngine::Color playerColor); - static ExtendedPlayer* CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, StringW mpexVersion, UnityEngine::Color playerColor); - - constexpr const UnityEngine::Color& get_playerColor() const { - return playerColor; - } - - constexpr bool HasState_CPP(std::string& state) const { - return _connectedPlayer->HasState(il2cpp_utils::newcsstr(state)); - } - - constexpr ExtendedPlayer* get_self() { - return this; - } - -) -#undef EPInterfaces - -#define EPPInterfaces { classof(LiteNetLib::Utils::INetSerializable*), classof(GlobalNamespace::IPoolablePacket*) } -___DECLARE_TYPE_WRAPPER_INHERITANCE(MultiQuestensions::Extensions, ExtendedPlayerPacket, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, - Il2CppObject, "MultiplayerExtensions.Extensions", - EPPInterfaces, 0, nullptr, - DECLARE_CTOR(New); - - // Player and platform information - DECLARE_INSTANCE_FIELD(StringW, platformID); - DECLARE_INSTANCE_FIELD(StringW, mpexVersion); - DECLARE_INSTANCE_FIELD(UnityEngine::Color, playerColor); - - DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(LiteNetLib::Utils::INetSerializable*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); - DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(LiteNetLib::Utils::INetSerializable*), "Deserialize", 1), LiteNetLib::Utils::NetDataReader* reader); - DECLARE_OVERRIDE_METHOD(void, Release, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::IPoolablePacket*), "Release", 0)); - - public: - Platform platform; - - static ExtendedPlayerPacket* Init(StringW platformID, Platform platform, UnityEngine::Color playerColor); -) -#undef EPPInterfaces \ No newline at end of file diff --git a/MultiQuestensions/include/Packets/Callback.hpp b/MultiQuestensions/include/Packets/Callback.hpp deleted file mode 100644 index 7e01a77..0000000 --- a/MultiQuestensions/include/Packets/Callback.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include "main.hpp" - -#include "Beatmaps/PreviewBeatmapPacket.hpp" -#include "GlobalNamespace/ThreadStaticPacketPool_1.hpp" -#include "GlobalNamespace/PacketPool_1.hpp" -#include "LiteNetLib/Utils/NetDataReader.hpp" - -template -using PacketCallback = void (*)(T, GlobalNamespace::IConnectedPlayer*); - -namespace MultiQuestensions { - class CallbackBase { - public: - virtual ~CallbackBase() {}; - virtual void Invoke(LiteNetLib::Utils::NetDataReader* reader, int size, GlobalNamespace::IConnectedPlayer* player) = 0; - }; - - template class CallbackWrapper : public CallbackBase { - private: - PacketCallback action = nullptr; - - public: - CallbackWrapper(PacketCallback callback) { - action = callback; - } - - void Invoke(LiteNetLib::Utils::NetDataReader* reader, int size, GlobalNamespace::IConnectedPlayer* player) { - getLogger().debug("Running Invoke creating packet"); - //TPacket packet = THROW_UNLESS(il2cpp_utils::New()); - //getLogger().debug("Assigning from ThreadStaticPacketPool"); - //packet = GlobalNamespace::ThreadStaticPacketPool_1::get_pool()->Obtain(); - TPacket packet = GlobalNamespace::ThreadStaticPacketPool_1::get_pool()->Obtain(); - if (packet == nullptr) { - reader->SkipBytes(size); - } - else { - try { - packet->Deserialize(reader); - } - catch (const std::exception& e) { - getLogger().debug("Exception Deserializing Packet"); - getLogger().error("REPORT TO ENDER: %s", e.what()); - } - catch (...) { - getLogger().debug("REPORT TO ENDER: Unknown exception Deserializing Packet"); - } - } - if (action != nullptr) { - try { - action(packet, player); - } - catch (const std::exception& e) { - getLogger().error("Exception running action"); - getLogger().error("REPORT TO ENDER: %s", e.what()); - } - catch (...) { - getLogger().debug("REPORT TO ENDER: Unknown exception Deserializing Packet"); - } - } - } - }; -} \ No newline at end of file diff --git a/MultiQuestensions/include/Packets/PacketManager.hpp b/MultiQuestensions/include/Packets/PacketManager.hpp deleted file mode 100644 index b60508a..0000000 --- a/MultiQuestensions/include/Packets/PacketManager.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include "main.hpp" -#include "Callback.hpp" -#include "PacketSerializer.hpp" - -#include -#include -#include "GlobalNamespace/MultiplayerSessionManager_MessageType.hpp" -#include "GlobalNamespace/PacketPool_1.hpp" - -namespace MultiQuestensions { - class PacketManager { - private: - GlobalNamespace::MultiplayerSessionManager* _sessionManager; - PacketSerializer* packetSerializer; - - public: - PacketManager(GlobalNamespace::MultiplayerSessionManager* sessionManager); - void Send(LiteNetLib::Utils::INetSerializable* message); - void SendUnreliable(LiteNetLib::Utils::INetSerializable* message); - - template - void RegisterCallback(std::string identifier, PacketCallback callback) { - CallbackWrapper* newCallback = new CallbackWrapper(callback); - if (identifier.empty()) { - getLogger().error("Cannot register callback: Identifier null."); - return; - } - else { - packetSerializer->RegisterCallback(identifier, newCallback); - } - } - - template - void RegisterCallback(PacketCallback callback) { - Il2CppReflectionType* packetType = csTypeOf(TPacket); - if (packetType == nullptr) { - getLogger().info("Packet Type null."); - return; - } - - std::string identifier = to_utf8(csstrtostr(packetType->ToString())); - int pos = 0; - while ((pos = identifier.find("::")) != std::string::npos) - { - identifier.replace(pos, 2, "."); - pos++; - } - - RegisterCallback(identifier, callback); - } - - template - void UnregisterCallback() { - packetSerializer->UnregisterCallback(); - } - - void UnregisterCallback(std::string identifier); - }; - - extern PacketManager* packetManager; -} \ No newline at end of file diff --git a/MultiQuestensions/include/Packets/PacketSerializer.hpp b/MultiQuestensions/include/Packets/PacketSerializer.hpp deleted file mode 100644 index ff19f85..0000000 --- a/MultiQuestensions/include/Packets/PacketSerializer.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include "main.hpp" -#include "Callback.hpp" -#include "custom-types/shared/types.hpp" -#include "custom-types/shared/macros.hpp" - -#include -#include "System/Action_3.hpp" -#include "LiteNetLib/Utils/NetDataWriter.hpp" -#include "System/Collections/Generic/Dictionary_2.hpp" -#include "System/Collections/Generic/List_1.hpp" -#include "GlobalNamespace/INetworkPacketSubSerializer_1.hpp" -#include "GlobalNamespace/IConnectedPlayer.hpp" -#include "System/Type.hpp" - -/*DECLARE_CLASS_INTERFACES(Il2CppNamespace, MyCustomBeatmapLevelPackCollection, "System", "Object", sizeof(Il2CppObject), - il2cpp_utils::GetClassFromName("", "IBeatmapLevelPackCollection"), - DECLARE_INSTANCE_FIELD(Il2CppArray*, wrappedArr); - - DECLARE_OVERRIDE_METHOD(Il2CppArray*, get_beatmapLevelPacks, il2cpp_utils::FindMethod("", "IBeatmapLevelPackCollection", "get_beatmapLevelPacks")); - DECLARE_CTOR(ctor, Il2CppArray* originalArray); - REGISTER_FUNCTION(MyCustomBeatmapLevelPackCollection, - modLogger().debug("Registering MyCustomBeatmapLevelPackCollection!"); - REGISTER_METHOD(get_beatmapLevelPacks); - REGISTER_METHOD(ctor); - REGISTER_FIELD(wrappedArr); - ) -)*/ - -using CallbackDictionary = std::map; -using TypeDictionary = std::map; - -DECLARE_CLASS_INTERFACES(MultiQuestensions, PacketSerializer, "System", "Object", sizeof(Il2CppObject), - classof(GlobalNamespace::INetworkPacketSubSerializer_1*), - DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::INetworkPacketSubSerializer_1*), "Serialize", 2), LiteNetLib::Utils::NetDataWriter* writer, LiteNetLib::Utils::INetSerializable* packet); - DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::INetworkPacketSubSerializer_1*), "Deserialize", 3), LiteNetLib::Utils::NetDataReader* reader, int length, GlobalNamespace::IConnectedPlayer* data); - DECLARE_OVERRIDE_METHOD(bool, HandlesType, il2cpp_utils::FindMethodUnsafe(classof(GlobalNamespace::INetworkPacketSubSerializer_1*), "HandlesType", 1), Il2CppReflectionType* type); - - //DECLARE_INSTANCE_METHOD(void, Serialize, LiteNetLib::Utils::NetDataWriter* writer, LiteNetLib::Utils::INetSerializable* packet); - //DECLARE_INSTANCE_METHOD(void, Deserialize, LiteNetLib::Utils::NetDataReader* reader, int length, GlobalNamespace::IConnectedPlayer* data); - //DECLARE_INSTANCE_METHOD(bool, HandlesType, Il2CppReflectionType* type); - - DECLARE_CTOR(Construct); - DECLARE_DTOR(Deconstruct); - - //REGISTER_FUNCTION(PacketSerializer, - // REGISTER_METHOD(Serialize); - // REGISTER_METHOD(Deserialize); - // REGISTER_METHOD(HandlesType); - // REGISTER_METHOD(Construct); - //) - - private: - CallbackDictionary packetHandlers; - TypeDictionary registeredTypes; - - public: - template - void RegisterCallback(std::string identifier, CallbackWrapper* callback) { - registeredTypes[csTypeOf(TPacket)] = identifier; - packetHandlers[identifier] = callback; - } - - template - void UnregisterCallback() { - getLogger().debug("UnregisterCallback called"); - - auto it = registeredTypes.find(csTypeOf(TPacket)); - if (it != registeredTypes.end()) registeredTypes.erase(it); - - auto itr = packetHandlers.find(csTypeOf(TPacket)->ToString()); - if (itr != packetHandlers.end()) { - delete itr->second; - packetHandlers.erase(itr); - } - } - - void UnregisterCallback(std::string identifier); -) \ No newline at end of file diff --git a/MultiQuestensions/include/UI/CenterScreenLoading.hpp b/MultiQuestensions/include/UI/CenterScreenLoading.hpp deleted file mode 100644 index 9267a7d..0000000 --- a/MultiQuestensions/include/UI/CenterScreenLoading.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "custom-types/shared/macros.hpp" -#include "UnityEngine/MonoBehaviour.hpp" -#include "GlobalNamespace/LoadingControl.hpp" -#include "GlobalNamespace/CenterStageScreenController.hpp" - -DECLARE_CLASS_CODEGEN(MultiQuestensions::UI, CenterScreenLoading, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(GlobalNamespace::LoadingControl*, loadingControl); - DECLARE_INSTANCE_FIELD(GlobalNamespace::CenterStageScreenController*, screenController); - DECLARE_INSTANCE_FIELD(GlobalNamespace::LobbyGameStateController*, gameStateController); - - DECLARE_INSTANCE_METHOD(void, Awake); - DECLARE_INSTANCE_METHOD(void, OnDisable); - DECLARE_INSTANCE_METHOD(void, ShowLoading); - // Note: downloadingProgress 1.0f = Full - DECLARE_INSTANCE_METHOD(void, ShowDownloadingProgress, float downloadingProgress); - //DECLARE_INSTANCE_METHOD(void, HideLoading); - DECLARE_INSTANCE_METHOD(void, FixedUpdate); - - bool isDownloading; - - static CenterScreenLoading* instance; -public: - static int playersReady; - static CenterScreenLoading* get_Instance() { return instance; } - static void HideLoading(); - //static void UpdatePlayersReady(int playerReady); -) diff --git a/MultiQuestensions/include/UI/DownloadedSongsGSM.hpp b/MultiQuestensions/include/UI/DownloadedSongsGSM.hpp deleted file mode 100644 index 21dd6a4..0000000 --- a/MultiQuestensions/include/UI/DownloadedSongsGSM.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "custom-types/shared/macros.hpp" -#include "UnityEngine/MonoBehaviour.hpp" -#include "questui/shared/CustomTypes/Components/List/CustomListTableData.hpp" -#include "HMUI/CurvedTextMeshPro.hpp" -#include "HMUI/ImageView.hpp" -#include "HMUI/ModalView.hpp" - -#include "GlobalNamespace/CustomPreviewBeatmapLevel.hpp" -#include "System/Threading/Tasks/Task_1.hpp" -#include "UnityEngine/Sprite.hpp" - - -DECLARE_CLASS_CODEGEN(MultiQuestensions::UI, DownloadedSongsGSM, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(HMUI::ModalView*, modal); - DECLARE_INSTANCE_FIELD(QuestUI::CustomListTableData*, list); - DECLARE_INSTANCE_FIELD(GlobalNamespace::CustomPreviewBeatmapLevel*, lastDownloaded); - - DECLARE_INSTANCE_METHOD(void, DidActivate, bool firstActivation); - DECLARE_INSTANCE_METHOD(void, OnEnable); - DECLARE_INSTANCE_METHOD(void, Refresh); - DECLARE_INSTANCE_METHOD(void, CreateCell, System::Threading::Tasks::Task_1* coverTask, GlobalNamespace::CustomPreviewBeatmapLevel* level); - DECLARE_INSTANCE_METHOD(void, Delete); - - static DownloadedSongsGSM* instance; - - int selectedIdx; - bool needSongRefresh; - public: - static DownloadedSongsGSM* get_Instance() { return instance; } - - static std::vector mapQueue; - -public: - void InsertCell(std::string hash); - -) \ No newline at end of file diff --git a/MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp b/MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp deleted file mode 100644 index eedcf03..0000000 --- a/MultiQuestensions/shared/CodegenExtensions/TempBloomFilterUtil.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -namespace GlobalNamespace { - class BloomFilterUtil : public ::Il2CppObject { - public: - template - static T ToBloomFilter(::Il2CppString* value, int hashCount, int hashBits) { - //static_assert(std::is_base_of_v, std::remove_pointer_t>); - static auto ___internal__logger = ::Logger::get().WithContext("GlobalNamespace::BloomFilterUtil::ToBloomFilter"); - static auto* ___internal__method = THROW_UNLESS((::il2cpp_utils::FindMethod("", "BloomFilterUtil", "ToBloomFilter", std::vector{::il2cpp_utils::il2cpp_type_check::il2cpp_no_arg_class::get()}, ::std::vector{::il2cpp_utils::ExtractType(value), ::il2cpp_utils::ExtractType(hashCount), ::il2cpp_utils::ExtractType(hashBits)}))); - static auto* ___generic__method = THROW_UNLESS(::il2cpp_utils::MakeGenericMethod(___internal__method, std::vector{::il2cpp_utils::il2cpp_type_check::il2cpp_no_arg_class::get()})); - return ::il2cpp_utils::RunMethodRethrow(static_cast(nullptr), ___generic__method, value, hashCount, hashBits); - } - }; -} diff --git a/MultiQuestensions/shared/Utils/CustomData.hpp b/MultiQuestensions/shared/Utils/CustomData.hpp deleted file mode 100644 index 5642c28..0000000 --- a/MultiQuestensions/shared/Utils/CustomData.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include -#include "GlobalNamespace/CustomPreviewBeatmapLevel.hpp" - -namespace MultiQuestensions::Utils { - bool HasRequirement(const std::optional& beatmapOpt); -} diff --git a/MultiQuestensions/shared/Utils/SemVerChecker.hpp b/MultiQuestensions/shared/Utils/SemVerChecker.hpp deleted file mode 100644 index ca075f0..0000000 --- a/MultiQuestensions/shared/Utils/SemVerChecker.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "main.hpp" -#include "cpp-semver/shared/cpp-semver.hpp" - -namespace MultiQuestensions::Utils { - static const std::string ChromaID = "Chroma"; - static const std::string ChromaVersionRange = ">=2.5.7"; - - static bool IsInstalled(std::string const& modName) { - auto const modList = Modloader::getMods(); - auto modInfo = modList.find(modName); - return (modInfo != modList.end()); - } - - static bool MatchesVersion(std::string const& modName, std::string const& versionRange) { - auto const modList = Modloader::getMods(); - auto modLoaded = Modloader::requireMod(modName); - try { - if (modLoaded) { - auto modInfo = modList.find(modName); - if (modInfo != modList.end()) { - - getLogger().debug("Checking %s version '%s'", modName.c_str(), modInfo->second.info.version.c_str()); - if (semver::satisfies(modInfo->second.info.version, versionRange)) { - getLogger().debug("%s version valid", modName.c_str()); - return true; - } - getLogger().debug("%s version outdated", modName.c_str()); - // mod is outdated - } - } - return false; - } - catch (const semver::semver_error &e) { - getLogger().error("SemVer Exception checking %s: %s", modName.c_str(), e.what()); - return false; - } - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/Beatmaps/PreviewBeatmapPacket.cpp b/MultiQuestensions/src/Beatmaps/PreviewBeatmapPacket.cpp deleted file mode 100644 index 6e81c67..0000000 --- a/MultiQuestensions/src/Beatmaps/PreviewBeatmapPacket.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "Beatmaps/PreviewBeatmapPacket.hpp" -#include "custom-types/shared/register.hpp" -#include "GlobalNamespace/VarIntExtensions.hpp" - -DEFINE_TYPE(MultiQuestensions::Beatmaps, PreviewBeatmapPacket); - -namespace MultiQuestensions::Beatmaps { - - //void PreviewBeatmapPacket::New_ctor() {} - //PreviewBeatmapPacket::PreviewBeatmapPacket() {} - void PreviewBeatmapPacket::New() {} - - void PreviewBeatmapPacket::Release() { - getLogger().debug("PreviewBeatmapPacket::Release"); - GlobalNamespace::ThreadStaticPacketPool_1::get_pool()->Release(this); - } - - void PreviewBeatmapPacket::Serialize(LiteNetLib::Utils::NetDataWriter* writer) { - getLogger().debug("PreviewBeatmapPacket::Serialize"); - - writer->Put(levelId); - writer->Put(levelHash); - writer->Put(songName); - writer->Put(songSubName); - writer->Put(songAuthorName); - writer->Put(levelAuthorName); - writer->Put(beatsPerMinute); - writer->Put(songDuration); - - writer->Put(characteristic); - GlobalNamespace::VarIntExtensions::PutVarUInt(writer, difficulty); - //writer->Put(difficulty); - } - - void PreviewBeatmapPacket::Deserialize(LiteNetLib::Utils::NetDataReader* reader) { - getLogger().debug("PreviewBeatmapPacket::Deserialize"); - - levelId = reader->GetString(); - //getLogger().debug("levelID: %s", to_utf8(csstrtostr(levelId)).c_str()); - levelHash = reader->GetString(); - //getLogger().debug("levelHash: %s", to_utf8(csstrtostr(levelHash)).c_str()); - songName = reader->GetString(); - songSubName = reader->GetString(); - songAuthorName = reader->GetString(); - levelAuthorName = reader->GetString(); - //getLogger().debug("songName: %s\n songSubName: %s\n songAuthorName: %s\n levelAuthorName: %s", - // to_utf8(csstrtostr(songName)).c_str(), - // to_utf8(csstrtostr(songSubName)).c_str(), - // to_utf8(csstrtostr(songAuthorName)).c_str(), - // to_utf8(csstrtostr(levelAuthorName)).c_str()); - beatsPerMinute = reader->GetFloat(); - songDuration = reader->GetFloat(); - - characteristic = reader->GetString(); - difficulty = GlobalNamespace::VarIntExtensions::GetVarUInt(reader); - getLogger().debug("Deserialize PreviewBeatmapPacket done"); - } -} diff --git a/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp b/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp deleted file mode 100644 index 080cd56..0000000 --- a/MultiQuestensions/src/Beatmaps/PreviewBeatmapStub.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "Beatmaps/PreviewBeatmapStub.hpp" -#include "beatsaber-hook/shared/utils/il2cpp-utils.hpp" -#include "System/Threading/Tasks/TaskStatus.hpp" -#include "UnityEngine/ImageConversion.hpp" -#include "GlobalNamespace/MediaAsyncLoader.hpp" -#include "songdownloader/shared/BeatSaverAPI.hpp" -#include "questui/shared/CustomTypes/Components/MainThreadScheduler.hpp" -#include - -DEFINE_TYPE(MultiQuestensions::Beatmaps, PreviewBeatmapStub); - -namespace MultiQuestensions::Beatmaps { - - void PreviewBeatmapStub::FromPreviewPacket(StringW levelhash, GlobalNamespace::IPreviewBeatmapLevel* level, PreviewBeatmapPacket* lvl) { - if (levelhash && level) { - getLogger().debug("PreviewBeatmapStub::FromPreview"); - - _preview = level; - isDownloaded = true; - _downloadable = DownloadableState::Unchecked; - - levelID = level->get_levelID(); - levelHash = levelhash; - //getLogger().debug("levelID: %s, levelHash: %s", to_utf8(csstrtostr(levelID)).c_str(), to_utf8(csstrtostr(levelHash)).c_str()); - - songName = level->get_songName(); - songSubName = level->get_songSubName(); - songAuthorName = level->get_songAuthorName(); - levelAuthorName = level->get_levelAuthorName(); - //getLogger().debug("songName: %s, songSubName: %s, songAuthorName: %s, levelAuthorName: %s", to_utf8(csstrtostr(songName)).c_str(), to_utf8(csstrtostr(songSubName)).c_str(), to_utf8(csstrtostr(songAuthorName)).c_str(), to_utf8(csstrtostr(levelAuthorName)).c_str()); - - beatsPerMinute = level->get_beatsPerMinute(); - songDuration = level->get_songDuration(); - //getLogger().debug("beatsPerMinute: %f, songDuration: %f", beatsPerMinute, songDuration); - } - else { - getLogger().debug("PreviewBeatmapStub::FromPacket"); - - //getLogger().debug("Set downloadstates"); - isDownloaded = false; - _downloadable = DownloadableState::Unchecked; - - //getLogger().debug("Get levelId and Hash"); - levelID = lvl->levelId; - levelHash = lvl->levelHash; - //levelHash = LevelIdToHash(levelID)/*packet->levelHash*/; - //getLogger().debug("levelID: %s\n Hash: %s", - // to_utf8(csstrtostr(levelID)).c_str(), - // to_utf8(csstrtostr(levelHash)).c_str()); - //getLogger().debug("SongInfo strings"); - songName = lvl->songName; - songSubName = lvl->songSubName; - songAuthorName = lvl->songAuthorName; - levelAuthorName = lvl->levelAuthorName; - //getLogger().debug("songName: %s\n songSubName: %s\n songAuthorName: %s\n levelAuthorName: %s", - // to_utf8(csstrtostr(songName)).c_str(), - // to_utf8(csstrtostr(songSubName)).c_str(), - // to_utf8(csstrtostr(songAuthorName)).c_str(), - // to_utf8(csstrtostr(levelAuthorName)).c_str()); - - //getLogger().debug("SongInfo floats"); - beatsPerMinute = lvl->beatsPerMinute; - songDuration = lvl->songDuration; - //getLogger().debug("beatsPerMinute: %f\n songDuration: %f", - // beatsPerMinute, - // songDuration); - } - - } - - System::Threading::Tasks::Task_1* PreviewBeatmapStub::GetCoverImageAsync(System::Threading::CancellationToken cancellationToken) { - if (_preview) { - getLogger().debug("Use localPreview"); - return _preview->GetCoverImageAsync(cancellationToken); - } - if (coverImage) - return System::Threading::Tasks::Task_1::New_ctor(coverImage); - else { - return System::Threading::Tasks::Task_1::New_ctor(static_cast(nullptr)); - } - } - - //System::Threading::Tasks::Task_1* PreviewBeatmapStub::GetPreviewAudioClipAsync(System::Threading::CancellationToken cancellationToken) { - // if (_preview) { - // return _preview->GetPreviewAudioClipAsync(cancellationToken); - // } - // else { - // return nullptr; - // } - //} - - MultiQuestensions::Beatmaps::PreviewBeatmapPacket* PreviewBeatmapStub::GetPacket(StringW characteristic, GlobalNamespace::BeatmapDifficulty difficulty) { - getLogger().debug("Start PreviewBeatmapStub::GetPacket"); - MultiQuestensions::Beatmaps::PreviewBeatmapPacket* packet = THROW_UNLESS(il2cpp_utils::New()); - - packet->levelId = levelID; - packet->levelHash = levelHash; - - packet->songName = songName; - packet->songSubName = songSubName; - packet->songAuthorName = songAuthorName; - packet->levelAuthorName = levelAuthorName; - - packet->beatsPerMinute = beatsPerMinute; - packet->songDuration = songDuration; - - packet->characteristic = characteristic; - packet->difficulty = difficulty; - return packet; - } - -#pragma region All the pain in form of getter functions - - StringW PreviewBeatmapStub::get_levelID() { - return levelID; - } - - StringW PreviewBeatmapStub::get_songName() { - return songName; - } - - StringW PreviewBeatmapStub::get_songSubName() { - return songSubName; - } - - StringW PreviewBeatmapStub::get_songAuthorName() { - return songAuthorName; - } - - StringW PreviewBeatmapStub::get_levelAuthorName() { - return levelAuthorName; - } - - float PreviewBeatmapStub::get_beatsPerMinute() { - return beatsPerMinute; - } - - float PreviewBeatmapStub::get_songDuration() { - return songDuration; - } - - float PreviewBeatmapStub::get_songTimeOffset() { - return songTimeOffset; - } - - float PreviewBeatmapStub::get_previewDuration() { - return previewDuration; - } - - float PreviewBeatmapStub::get_previewStartTime() { - return previewStartTime; - } - - float PreviewBeatmapStub::get_shuffle() { - return shuffle; - } - - float PreviewBeatmapStub::get_shufflePeriod() { - return shufflePeriod; - } - - GlobalNamespace::EnvironmentInfoSO* PreviewBeatmapStub::get_allDirectionsEnvironmentInfo() { - return allDirectionsEnvironmentInfo; - } - - GlobalNamespace::EnvironmentInfoSO* PreviewBeatmapStub::get_environmentInfo() { - return environmentInfo; - } - - Array* PreviewBeatmapStub::get_previewDifficultyBeatmapSets() { - return previewDifficultyBeatmapSets; - } - -#pragma endregion - -} \ No newline at end of file diff --git a/MultiQuestensions/src/CS_DataStore.cpp b/MultiQuestensions/src/CS_DataStore.cpp deleted file mode 100644 index 95ff462..0000000 --- a/MultiQuestensions/src/CS_DataStore.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "main.hpp" -#include "CS_DataStore.hpp" - -DEFINE_TYPE(MultiQuestensions, DataStore); - -namespace MultiQuestensions { - void DataStore::New(GlobalNamespace::IPreviewBeatmapLevel* previewBeatmap, GlobalNamespace::BeatmapCharacteristicSO* beatmapCharacteristic, GlobalNamespace::IDifficultyBeatmap* difficultyBeatmap, GlobalNamespace::GameplayModifiers* gameplayModifiers) { - loadingPreviewBeatmapLevel = previewBeatmap; - loadingBeatmapCharacteristic = beatmapCharacteristic; - loadingDifficultyBeatmap = difficultyBeatmap; - loadingGameplayModifiers = gameplayModifiers; - } - - DataStore* DataStore::instance; - - DataStore* DataStore::get_Instance() { - return instance; - } - - DataStore* DataStore::CS_Ctor(GlobalNamespace::IPreviewBeatmapLevel* previewBeatmap, GlobalNamespace::BeatmapCharacteristicSO* beatmapCharacteristic, GlobalNamespace::IDifficultyBeatmap* difficultyBeatmap, GlobalNamespace::GameplayModifiers* gameplayModifiers, GlobalNamespace::BeatmapDifficulty beatmapDifficulty) { - instance = THROW_UNLESS(il2cpp_utils::New(previewBeatmap, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers)); - instance->loadingBeatmapDifficulty = beatmapDifficulty; - return instance; - } - - void DataStore::Clear() { - if (instance) { - instance->loadingPreviewBeatmapLevel = nullptr; - instance->loadingBeatmapCharacteristic = nullptr; - instance->loadingDifficultyBeatmap = nullptr; - instance->loadingGameplayModifiers = nullptr; - instance->loadingBeatmapDifficulty = std::nullopt; - } - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp b/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp deleted file mode 100644 index c841e42..0000000 --- a/MultiQuestensions/src/Environments/LobbyAvatarNameTag.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "main.hpp" -#include "Environments/LobbyAvatarNameTag.hpp" -#include "Assets/Sprites.hpp" -#include "UnityEngine/CanvasRenderer.hpp" -#include "UnityEngine/RectTransform.hpp" -#include "UnityEngine/UI/HorizontalLayoutGroup.hpp" -#include "GlobalNamespace/ConnectedPlayerName.hpp" -#include "UnityEngine/Object.hpp" -using MultiQuestensions::Extensions::ExtendedPlayer; -using namespace GlobalNamespace; -using namespace UnityEngine::UI; -using namespace UnityEngine; -using namespace HMUI; - -DEFINE_TYPE(MultiQuestensions::Environments, LobbyAvatarNameTag); - -namespace MultiQuestensions::Environments { - static StringW BG() { - static StringW bg("BG"); - return bg; - } - - static StringW Name() { - static StringW name("Name"); - return name; - } - - static StringW Player() { - static StringW player("Player"); - return player; - } - - - void LobbyAvatarNameTag::New() { - _enabled = false; - _playerInfo = nullptr; - _playerIcons.clear(); - } - - void LobbyAvatarNameTag::Awake() { - // Get references - _bg = get_transform()->Find(BG())->GetComponent(); - _nameText = get_transform()->Find(Name())->GetComponent(); - - // Add horizontal layout to bg - HorizontalLayoutGroup* _; - if (!_bg->TryGetComponent(ByRef(_))) - { - auto hLayout = _bg->get_gameObject()->AddComponent(); - hLayout->set_childAlignment(TextAnchor::MiddleCenter); - hLayout->set_childForceExpandWidth(false); - hLayout->set_childForceExpandHeight(false); - hLayout->set_childScaleWidth(false); - hLayout->set_childScaleHeight(false); - hLayout->set_spacing(4); - } - - // Re-nest name onto bg - _nameText->get_transform()->SetParent(_bg->get_transform(), false); - - // Take control of name tag - ConnectedPlayerName* nativeNameScript; - if (_nameText->TryGetComponent(ByRef(nativeNameScript))) - Object::Destroy(nativeNameScript); - _nameText->set_text(Player()); - } - - void LobbyAvatarNameTag::OnEnable() - { - _enabled = true; - - if (_playerInfo != nullptr) - SetPlayerInfo(_playerInfo); - } - - #pragma region Set Player Info - void LobbyAvatarNameTag::SetPlayerInfo(IConnectedPlayer* player) - { - if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) - SetExtendedPlayerInfo(reinterpret_cast(player)); - else - SetSimplePlayerInfo(player); - } - - void LobbyAvatarNameTag::SetExtendedPlayerInfo(ExtendedPlayer* extendedPlayer) - { - _playerInfo = reinterpret_cast(extendedPlayer); - - if (!_enabled) - return; - - _nameText->set_text(extendedPlayer->get_userName()); - _nameText->set_color(extendedPlayer->get_playerColor()); - - //getLogger().debug("SetExtendedPlayerInfo platform: %d", (int)extendedPlayer->get_platform()); - - switch (extendedPlayer->get_platform()) - { - case Extensions::Platform::Steam: - SetIcon(PlayerIconSlot::Platform, Sprites::IconSteam64()); - break; - case Extensions::Platform::OculusQuest: - case Extensions::Platform::OculusPC: - SetIcon(PlayerIconSlot::Platform, Sprites::IconOculus64()); - break; - default: - RemoveIcon(PlayerIconSlot::Platform); - break; - } - } - - void LobbyAvatarNameTag::SetSimplePlayerInfo(IConnectedPlayer* simplePlayer) - { - _playerInfo = simplePlayer; - - if (!_enabled) - return; - - _nameText->set_text(simplePlayer->get_userName()); - _nameText->set_color(Color::get_white()); - - RemoveIcon(PlayerIconSlot::Platform); - } - #pragma endregion - - #pragma region Set Icons - void LobbyAvatarNameTag::SetIcon(PlayerIconSlot slot, Sprite* sprite) - { - getLogger().debug("SetIcon Sprite %p", sprite); - - if (!_enabled) - return; - - HMUI::ImageView* imageView; - if (!_playerIcons.contains(slot)) - { - //getLogger().debug("SetIcon, create new Icon"); - auto iconObj = GameObject::New_ctor(string_format("MQEPlayerIcon(%d)", (int)slot).c_str()); - iconObj->get_transform()->SetParent(_bg->get_transform(), false); - iconObj->get_transform()->SetSiblingIndex((int)slot); - iconObj->set_layer(5); - - iconObj->AddComponent(); - - imageView = iconObj->AddComponent(); - imageView->set_maskable(true); - imageView->set_fillCenter(true); - imageView->set_preserveAspect(true); - imageView->set_material(_bg->get_material()); // No Glow Billboard material - _playerIcons.insert_or_assign(slot, imageView); - - auto rectTransform = iconObj->GetComponent(); - rectTransform->set_localScale({ 3.2f, 3.2f, 0.0f }); - } - else imageView = _playerIcons.at(slot); - - imageView->set_sprite(sprite); - - _nameText->get_transform()->SetSiblingIndex(999); - } - - void LobbyAvatarNameTag::RemoveIcon(PlayerIconSlot slot) - { - //getLogger().debug("RemoveIcon"); - - if (!_enabled) - return; - if (_playerIcons.contains(slot)) - { - HMUI::ImageView* imageView = _playerIcons[slot]; - GameObject::Destroy(imageView->get_gameObject()); - _playerIcons.erase(slot); - } - } - #pragma endregion -} \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp b/MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp deleted file mode 100644 index 4611318..0000000 --- a/MultiQuestensions/src/Environments/LobbyAvatarPlaceLighting.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "main.hpp" -#include "Environments/LobbyAvatarPlaceLighting.hpp" -#include "UnityEngine/Time.hpp" -using namespace GlobalNamespace; -using namespace UnityEngine; - -DEFINE_TYPE(MultiQuestensions::Environments, LobbyAvatarPlaceLighting); - -namespace MultiQuestensions::Environments { - - void LobbyAvatarPlaceLighting::New() { - smoothTime = 2.0f; - } - - void LobbyAvatarPlaceLighting::OnEnable() { - auto lightsArr = this->GetComponentsInChildren(); - for (int i = 0; i < lightsArr.Length(); i++) { - this->lights.emplace_back(lightsArr.get(i)); - } - } - - void LobbyAvatarPlaceLighting::OnDisable() { - lights.clear(); - } - - inline static Color Lerp(Color const& a, Color const& b, float const& t) - { - float t_clamp = std::clamp(t, 0.0f, 1.0f); - return Color(a.r + (b.r - a.r) * t_clamp, a.g + (b.g - a.g) * t_clamp, a.b + (b.b - a.b) * t_clamp, a.a + (b.a - a.a) * t_clamp); - } - - void LobbyAvatarPlaceLighting::Update() { - Color current = GetColor(); - - if (current == targetColor) - return; - - SetColor(targetColor); - - if (IsColorVeryCloseToColor(current, targetColor)) - SetColor(targetColor); - else - //SetColor(Color::Lerp(current, targetColor, Time::get_deltaTime() * smoothTime)); - SetColor(Lerp(current, targetColor, Time::get_deltaTime() * smoothTime)); - } - - void LobbyAvatarPlaceLighting::SetColor(const Color& color, bool immediate) { - targetColor = color; - - if (immediate) - { - SetColor(color); - } - } - - Color LobbyAvatarPlaceLighting::GetColor() { - if (lights.size() > 0) - return lights[0]->get_color(); - return Color::get_black(); - } - - bool LobbyAvatarPlaceLighting::IsColorVeryCloseToColor(Color color0, Color color1) - { - return (fabs(color0.r - color1.r) < 0.002f && fabs(color0.g - color1.g) < 0.002f && fabs(color0.b - color1.b) < 0.002f && fabs(color0.a - color1.a) < 0.002f); - } - - void LobbyAvatarPlaceLighting::SetColor(const Color& color) { - for (TubeBloomPrePassLight* light : lights) { - light->set_color(color); - light->Refresh(); - } - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/Extensions/ExtendedPlayer.cpp b/MultiQuestensions/src/Extensions/ExtendedPlayer.cpp deleted file mode 100644 index 7e3f495..0000000 --- a/MultiQuestensions/src/Extensions/ExtendedPlayer.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "Extensions/ExtendedPlayer.hpp" -#include "CodegenExtensions/ColorUtility.hpp" - -DEFINE_TYPE(MultiQuestensions::Extensions, ExtendedPlayer) - -DEFINE_TYPE(MultiQuestensions::Extensions, ExtendedPlayerPacket) - -namespace MultiQuestensions::Extensions { - - static Il2CppString* MQE_Protocol() { - static Il2CppString* protocol = il2cpp_utils::newcsstr(MPEX_PROTOCOL); - return protocol; - } - -#pragma region ExtendedPlayer - void ExtendedPlayer::ExtendedPlayer_ctor(GlobalNamespace::IConnectedPlayer* player, Il2CppString* platformID, int platform, UnityEngine::Color playerColor, Il2CppString* mpexVersion) { - getLogger().debug("Creating ExtendedPlayer"); - _connectedPlayer = player; - if (mpexVersion) this->mpexVersion = mpexVersion; - else this->mpexVersion = MQE_Protocol(); - if (platformID) { - this->platformID = platformID; - this->platform = (Platform)platform; - this->playerColor = playerColor; - } - getLogger().debug("Finished Creating ExtendedPlayer"); - } - - ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player) { - return THROW_UNLESS(il2cpp_utils::New(player, static_cast(nullptr), 3, DefaultColor, static_cast(nullptr))); - } - ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, UnityEngine::Color playerColor) { - return THROW_UNLESS(il2cpp_utils::New(player, platformID, (int)platform, playerColor, static_cast(nullptr))); - } - ExtendedPlayer* ExtendedPlayer::CS_ctor(GlobalNamespace::IConnectedPlayer* player, StringW platformID, Platform platform, StringW mpexVersion, UnityEngine::Color playerColor) { - return THROW_UNLESS(il2cpp_utils::New(player, platformID, (int)platform, playerColor, mpexVersion)); - } -#pragma endregion - -#pragma region Getters - StringW ExtendedPlayer::get_platformID() { - return platformID; - } - Platform ExtendedPlayer::get_platform() { - return platform; - } - StringW ExtendedPlayer::get_mpexVersion() { - return mpexVersion; - } - - bool ExtendedPlayer::get_isMe() { - return _connectedPlayer->get_isMe(); - } - - StringW ExtendedPlayer::get_userId() { - return _connectedPlayer->get_userId(); - } - - StringW ExtendedPlayer::get_userName() { - return _connectedPlayer->get_userName(); - } - - float ExtendedPlayer::get_currentLatency() { - return _connectedPlayer->get_currentLatency(); - } - - bool ExtendedPlayer::get_isConnected() { - return _connectedPlayer->get_isConnected(); - } - - bool ExtendedPlayer::get_isConnectionOwner() { - return _connectedPlayer->get_isConnectionOwner(); - } - - float ExtendedPlayer::get_offsetSyncTime() { - return _connectedPlayer->get_offsetSyncTime(); - } - - int ExtendedPlayer::get_sortIndex() { - return _connectedPlayer->get_sortIndex(); - } - - bool ExtendedPlayer::get_isKicked() { - return _connectedPlayer->get_isKicked(); - } - - GlobalNamespace::MultiplayerAvatarData ExtendedPlayer::get_multiplayerAvatarData() { - return _connectedPlayer->get_multiplayerAvatarData(); - } - - GlobalNamespace::DisconnectedReason ExtendedPlayer::get_disconnectedReason() { - return _connectedPlayer->get_disconnectedReason(); - } - - bool ExtendedPlayer::HasState(StringW state) { - return _connectedPlayer->HasState(state); - } -#pragma endregion - -#pragma region ExtendedPlayerPacket - void ExtendedPlayerPacket::New() {} - - void ExtendedPlayerPacket::Release() { - getLogger().debug("ExtendedPlayerPacket::Release"); - GlobalNamespace::ThreadStaticPacketPool_1::get_pool()->Release(this); - } - - void ExtendedPlayerPacket::Serialize(LiteNetLib::Utils::NetDataWriter* writer) { - getLogger().debug("ExtendedPlayerPacket::Serialize"); - - writer->Put(platformID); - writer->Put(mpexVersion); - writer->Put(UnityEngine::ColorUtility::ToHtmlStringRGB(playerColor)); - //writer->Put(Il2CppString::Concat(il2cpp_utils::newcsstr("#"), UnityEngine::ColorUtility::ToHtmlStringRGB(playerColor))); - writer->Put((int)platform); - getLogger().debug("Serialize ExtendedPlayerPacket done"); - } - - void ExtendedPlayerPacket::Deserialize(LiteNetLib::Utils::NetDataReader* reader) { - getLogger().debug("ExtendedPlayerPacket::Deserialize"); - - platformID = reader->GetString(); - mpexVersion = reader->GetString(); - if (!UnityEngine::ColorUtility::TryParseHtmlString(reader->GetString(), playerColor)) - this->playerColor = ExtendedPlayer::DefaultColor; - if (reader->get_AvailableBytes() >= 4) // Verify this works when the platform int exists. - this->platform = (Platform)reader->GetInt(); - else - this->platform = Platform::Unknown; - getLogger().debug("Deserialize ExtendedPlayerPacket done"); - } - - ExtendedPlayerPacket* ExtendedPlayerPacket::Init(StringW platformID, Platform platform, UnityEngine::Color playerColor) - { - auto extendedPlayer = THROW_UNLESS(il2cpp_utils::New()); - - extendedPlayer->platformID = platformID; - extendedPlayer->platform = (Platform)platform; - extendedPlayer->playerColor = playerColor; - extendedPlayer->mpexVersion = MQE_Protocol(); - return extendedPlayer; - } -#pragma endregion -} \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp b/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp deleted file mode 100644 index 9971fee..0000000 --- a/MultiQuestensions/src/Hooks/MaxPlayerHooks.cpp +++ /dev/null @@ -1,209 +0,0 @@ -#include "main.hpp" -#include "Hooks/Hooks.hpp" -//#include "UnityEngine/Debug.hpp" -#include "GlobalNamespace/MultiplayerOutroAnimationController.hpp" -#include "GlobalNamespace/CreateServerFormController.hpp" -#include "GlobalNamespace/FormattedFloatListSettingsController.hpp" - -using namespace GlobalNamespace; -using namespace System; -using namespace System::Collections::Generic; -using namespace System::Linq; -using namespace UnityEngine; -using namespace UnityEngine::Playables; -using namespace UnityEngine::Timeline; - -namespace MultiQuestensions { - - int targetIterations = 0; - - MAKE_HOOK_MATCH(MultiplayerResultsPyramidPatch, &MultiplayerResultsPyramidView::SetupResults, void, MultiplayerResultsPyramidView* self, IReadOnlyList_1* resultsData, UnityEngine::Transform* badgeStartTransform, UnityEngine::Transform* badgeMidTransform) { - try { - static auto* Enumerable_Take_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "Take", 2)); - static auto* Enumerable_Take = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_Take_Generic, { classof(MultiplayerPlayerResultsData*) })); - auto* takeResult = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_Take, reinterpret_cast*>(resultsData), 5); - - static auto* Enumerable_ToList_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "ToList", 1)); - static auto* Enumerable_ToList = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_ToList_Generic, { classof(MultiplayerPlayerResultsData*) })); - List* newResultsData = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_ToList, takeResult); - - //List* newResultsData = Enumerable::ToList(Enumerable::Take(reinterpret_cast*>(resultsData), 5)); - MultiplayerResultsPyramidPatch(self, (IReadOnlyList_1*)newResultsData, badgeStartTransform, badgeMidTransform); - } - catch (const std::runtime_error& e) { - getLogger().critical("REPORT TO ENDER: Hook MultiplayerResultsPyramidPatch File " __FILE__ " at Line %d: %s", __LINE__, e.what()); - MultiplayerResultsPyramidPatch(self, resultsData, badgeStartTransform, badgeMidTransform); - } - } - - MAKE_HOOK_MATCH(IntroAnimationPatch, &MultiplayerIntroAnimationController::PlayIntroAnimation, void, MultiplayerIntroAnimationController* self, float maxDesiredIntroAnimationDuration, Action* onCompleted) { - PlayableDirector* realDirector = self->dyn__introPlayableDirector(); - if (targetIterations == 0) - { - targetIterations = floor((reinterpret_cast*>(self->dyn__multiplayerPlayersManager()->dyn__allActiveAtGameStartPlayers())->get_Count() - 1) / 4) + 1; - } - try { - // Run animation one time for each set of 4 players - if (targetIterations != 1) { - // Create duplicated animations - GameObject* newPlayableGameObject = GameObject::New_ctor(); - self->dyn__introPlayableDirector() = newPlayableGameObject->AddComponent(); - - using SetPlayableAsset = function_ptr_t; - static SetPlayableAsset setPlayableAsset = reinterpret_cast(il2cpp_functions::resolve_icall("UnityEngine.Playables.PlayableDirector::SetPlayableAsset")); - setPlayableAsset(self->dyn__introPlayableDirector(), realDirector->get_playableAsset()); - - // Mute duplicated animations except one (otherwise audio is very loud) - TimelineAsset* mutedTimeline = reinterpret_cast(self->dyn__introPlayableDirector()->get_playableAsset()); - - static auto* Enumerable_ToList_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "ToList", 1)); - static auto* Enumerable_ToList = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_ToList_Generic, { classof(TrackAsset*) })); - - //List* outputTracks = Enumerable::ToList(animationTimeline->GetOutputTracks()); - List* outputTracks = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_ToList, mutedTimeline->GetOutputTracks()); - - for (int i = 0; i < outputTracks->get_Count(); i++) { - TrackAsset* currentTrack = outputTracks->get_Item(i); - bool isAudio = il2cpp_utils::AssignableFrom(reinterpret_cast(currentTrack)->klass); - currentTrack->set_muted(isAudio); - } - } - - self->dyn__bindingFinished() = false; - IntroAnimationPatch(self, maxDesiredIntroAnimationDuration, onCompleted); - // Reset director to real director - self->dyn__introPlayableDirector() = realDirector; - targetIterations--; - if (targetIterations != 0) - self->PlayIntroAnimation(maxDesiredIntroAnimationDuration, onCompleted); - } - catch (const std::runtime_error& e) { - // Reset director to real director - self->dyn__introPlayableDirector() = realDirector; - getLogger().critical("REPORT TO ENDER: Hook IntroAnimationPatch Exception: %s", e.what()); - IntroAnimationPatch(self, maxDesiredIntroAnimationDuration, onCompleted); - } - } - - enum CalculatePlayerIndexSequencePatchType { - None, BindTimeline, BindOutroTimeline - }; - - CalculatePlayerIndexSequencePatchType cpispt = None; - - MAKE_HOOK_MATCH(MultiplayerIntroAnimationController_BindTimeline, &MultiplayerIntroAnimationController::BindTimeline, void, MultiplayerIntroAnimationController* self) { - getLogger().debug("Start: MultiplayerIntroAnimationController_BindTimeline"); - cpispt = BindTimeline; - MultiplayerIntroAnimationController_BindTimeline(self); - } - - MAKE_HOOK_MATCH(MultiplayerOutroAnimationController_BindOutroTimeline, &MultiplayerOutroAnimationController::BindOutroTimeline, void, MultiplayerOutroAnimationController* self) { - getLogger().debug("Start: MultiplayerOutroAnimationController_BindOutroTimeline"); - cpispt = BindOutroTimeline; - MultiplayerOutroAnimationController_BindOutroTimeline(self); - } - - MAKE_HOOK_MATCH(MultiplayerPlayersManager_get_allActiveAtGameStartPlayers, &MultiplayerPlayersManager::get_allActiveAtGameStartPlayers, IReadOnlyList_1*, MultiplayerPlayersManager* self) { - getLogger().debug("Start: MultiplayerPlayersManager_get_allActiveAtGameStartPlayers"); - static auto* Enumerable_ToList_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "ToList", 1)); - static auto* Enumerable_ToList = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_ToList_Generic, { classof(IConnectedPlayer*) })); - - static auto* Enumerable_Take_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "Take", 2)); - static auto* Enumerable_Take = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_Take_Generic, { classof(IConnectedPlayer*) })); - - if (cpispt == BindTimeline) { - cpispt = None; - try { - List_1* listActivePlayers = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_ToList, reinterpret_cast*>(self->dyn__allActiveAtGameStartPlayers())); - //List* listActivePlayers = Enumerable::ToList(reinterpret_cast*>(allActivePlayer)); - IConnectedPlayer* localPlayer = nullptr; - - // Check if active players contains local player and remove local player - for (int i = 0; i < listActivePlayers->get_Count(); i++) { - IConnectedPlayer* currentPlayer = listActivePlayers->get_Item(i); - if (currentPlayer->get_isMe()) { - listActivePlayers->RemoveAt(i); - localPlayer = currentPlayer; - } - } - - // Skip x amount of players and then take 4 - static auto* Enumerable_Skip_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "Skip", 2)); - static auto* Enumerable_Skip = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_Skip_Generic, { classof(IConnectedPlayer*) })); - auto* skipResult = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_Skip, reinterpret_cast*>(listActivePlayers), (targetIterations - 1) * 4); - - auto* takeResult = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_Take, skipResult, 4); - - List_1* selectedActivePlayers = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_ToList, takeResult); - - //List_1* selectedActivePlayers = Enumerable::ToList(Enumerable::Take(Enumerable::Skip(reinterpret_cast*>(listActivePlayers), (targetIterations - 1) * 4), 4)); - //List_1* selectedActivePlayers = Enumerable::ToList(Enumerable::Take(skipResult, 4)); - - // Add back local player if not null - if (targetIterations == 1 && localPlayer != nullptr) { - selectedActivePlayers->Add(localPlayer); - } - - getLogger().debug("Finish: MultiplayerPlayersManager_get_allActiveAtGameStartPlayers"); - - //return new list of players - return reinterpret_cast*>(selectedActivePlayers); - } - catch (const std::runtime_error& e) { - getLogger().critical("REPORT TO ENDER: Hook MultiplayerPlayersManager_get_allActiveAtGameStartPlayers Exception: %s", e.what()); - } - } - else if (cpispt == BindOutroTimeline) { - cpispt = None; - - auto* result = il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_Take, reinterpret_cast*>(self->dyn__allActiveAtGameStartPlayers()), 4); - - return reinterpret_cast*>(il2cpp_utils::RunMethodThrow*, false>(static_cast(nullptr), - Enumerable_ToList, result)); - } - cpispt = None; - return self->dyn__allActiveAtGameStartPlayers(); - } - - MAKE_HOOK_MATCH(CreateServerFormController_get_formData, &CreateServerFormController::get_formData, CreateServerFormData, CreateServerFormController* self) { - CreateServerFormData result = CreateServerFormController_get_formData(self); - result.maxPlayers = std::clamp(self->dyn__maxPlayersList()->get_value(), 2, std::clamp(getConfig().config["MaxPlayers"].GetInt(), 2, 100)); - return result; - } - - MAKE_HOOK_MATCH(CreateServerFormController_Setup, &CreateServerFormController::Setup, void, CreateServerFormController* self, int selectedNumberOfPlayers, bool netDiscoverable) { - try { - std::vector rangeVec; - static auto* Enumerable_ToArray_Generic = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(Enumerable*), "ToArray", 1)); - static auto* Enumerable_ToArray = THROW_UNLESS(il2cpp_utils::MakeGenericMethod(Enumerable_ToArray_Generic, { classof(int) })); - il2cpp_utils::RunMethodThrow<::Array*, false>(static_cast(nullptr), - Enumerable_ToArray, Enumerable::Range(2, std::clamp(getConfig().config["MaxPlayers"].GetInt(), 2, 100) - 1))->copy_to(rangeVec); - //Enumerable::ToArray(Enumerable::Range(2, 9))->copy_to(rangeVec); - std::vector resultVec(rangeVec.begin(), rangeVec.end()); - self->dyn__maxPlayersList()->dyn__values() = il2cpp_utils::vectorToArray(resultVec); - } catch (const std::runtime_error& e) { - getLogger().critical("REPORT TO ENDER: Hook CreateServerFormController_Setup Exception: %s", e.what()); - } - CreateServerFormController_Setup(self, selectedNumberOfPlayers, netDiscoverable); - } - - void Hooks::MaxPlayerHooks() { - INSTALL_HOOK(getLogger(), MultiplayerResultsPyramidPatch); - INSTALL_HOOK(getLogger(), IntroAnimationPatch); - INSTALL_HOOK(getLogger(), MultiplayerIntroAnimationController_BindTimeline); - INSTALL_HOOK(getLogger(), MultiplayerOutroAnimationController_BindOutroTimeline); - - INSTALL_HOOK_ORIG(getLogger(), MultiplayerPlayersManager_get_allActiveAtGameStartPlayers); - INSTALL_HOOK(getLogger(), CreateServerFormController_get_formData); - INSTALL_HOOK(getLogger(), CreateServerFormController_Setup); - - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp b/MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp deleted file mode 100644 index 1e5ee64..0000000 --- a/MultiQuestensions/src/Hooks/NetworkPlayerEntitlementCheckerHooks.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "main.hpp" -#include "Hooks/Hooks.hpp" -#include "Utils/CustomData.hpp" -#include "CS_DataStore.hpp" -using namespace GlobalNamespace; -using namespace System::Threading::Tasks; - -std::string missingLevelText; - -namespace MultiQuestensions { - -#pragma region Fields - std::map> entitlementDictionary; - - //static std::multimap entitlementDictionary; - - GlobalNamespace::IPreviewBeatmapLevel* loadingPreviewBeatmapLevel; - GlobalNamespace::BeatmapDifficulty loadingBeatmapDifficulty; - GlobalNamespace::BeatmapCharacteristicSO* loadingBeatmapCharacteristic; - GlobalNamespace::IDifficultyBeatmap* loadingDifficultyBeatmap; - GlobalNamespace::GameplayModifiers* loadingGameplayModifiers; - - //System::Action_3<::Il2CppString*, ::Il2CppString*, EntitlementsStatus>* entitlementAction; -#pragma endregion - - // For debugging purposes - const char* entitlementText(EntitlementsStatus entitlement) { - switch (entitlement.value) { - case EntitlementsStatus::Unknown: - return "Unknown"; - case EntitlementsStatus::NotOwned: - return "NotOwned"; - case EntitlementsStatus::NotDownloaded: - return "NotDownloaded"; - case EntitlementsStatus::Ok: - return "Ok"; - } - return ""; - } - - // Subscribe this method to 'menuRpcManager.setIsEntitledToLevelEvent' when on NetworkPlayerEntitlementChecker.Start, unsub on destroy - static void HandleEntitlementReceived(StringW userId, StringW levelId, EntitlementsStatus entitlement) { - std::string cUserId = userId; - std::string cLevelId = levelId; - - getLogger().debug("[HandleEntitlementReceived] Received Entitlement from user '%s' for level '%s' with status '%s'", - cUserId.c_str(), - cLevelId.c_str(), - entitlementText(entitlement) - ); - - if (entitlement == EntitlementsStatus::NotOwned && MultiQuestensions::Utils::HasRequirement(RuntimeSongLoader::API::GetLevelById(cLevelId))) { - IConnectedPlayer* player = sessionManager->GetPlayerByUserId(userId); - if (player) { - if (!player->HasState(getMEStateStr())) - missingLevelText = "One or more players are missing the following Requirement: Mapping Extensions"; - else if (!player->HasState(getNEStateStr())) - missingLevelText = "One or more players are missing the following Requirement: Noodle Extensions"; - else if (!player->HasState(getChromaStateStr())) - missingLevelText = "One or more players are missing the following Requirement: Chroma"; - } - else { - missingLevelText = "Error Checking Requirement: Player not found"; - } - } - entitlementDictionary[cUserId][cLevelId] = entitlement.value; - if (lobbyGameStateController != nullptr && lobbyGameStateController->get_state() == MultiplayerLobbyState::GameStarting) { - DataStore* instance = DataStore::get_Instance(); - if (instance && instance->loadingPreviewBeatmapLevel && instance->loadingBeatmapCharacteristic && instance->loadingDifficultyBeatmap && instance->loadingGameplayModifiers && instance->loadingBeatmapDifficulty) { - getLogger().debug("[HandleEntitlementReceived] GameStarting, running 'HandleMultiplayerLevelLoaderCountdownFinished'"); - lobbyGameStateController->HandleMultiplayerLevelLoaderCountdownFinished(instance->loadingPreviewBeatmapLevel, instance->loadingBeatmapDifficulty.value(), instance->loadingBeatmapCharacteristic, instance->loadingDifficultyBeatmap, instance->loadingGameplayModifiers); - return; - } - else if (lobbyGameStateController->dyn__multiplayerLevelLoader()) { - getLogger().debug("[HandleEntitlementReceived] GameStarting, DataStore empty trying to run 'HandleMultiplayerLevelLoaderCountdownFinished' with lvlLoader Data"); - MultiplayerLevelLoader* lvlLoader = lobbyGameStateController->dyn__multiplayerLevelLoader(); - if (lvlLoader->dyn__previewBeatmapLevel() && lvlLoader->dyn__beatmapId() && lvlLoader->dyn__beatmapCharacteristic() && lvlLoader->dyn__difficultyBeatmap() && lvlLoader->dyn__gameplayModifiers()) { - lobbyGameStateController->HandleMultiplayerLevelLoaderCountdownFinished(lvlLoader->dyn__previewBeatmapLevel(), lvlLoader->dyn__beatmapId()->get_difficulty(), lvlLoader->dyn__beatmapCharacteristic(), lvlLoader->dyn__difficultyBeatmap(), lvlLoader->dyn__gameplayModifiers()); - return; - } - } - getLogger().error("[HandleEntitlementReceived] GameStarting but level data not available"); - //getLogger().debug("[HandleEntitlementReceived] checking pointers: loadingPreviewBeatmapLevel='%p', loadingBeatmapDifficulty set to '%d', loadingBeatmapCharacteristic='%p', loadingDifficultyBeatmap='%p', loadingGameplayModifiers='%p'", loadingPreviewBeatmapLevel, static_cast(loadingBeatmapDifficulty), loadingBeatmapCharacteristic, loadingDifficultyBeatmap, loadingGameplayModifiers); - } - } - -#pragma region Hooks - MAKE_HOOK_MATCH(NetworkPlayerEntitlementChecker_GetEntitlementStatus, &NetworkPlayerEntitlementChecker::GetEntitlementStatus, Task_1*, NetworkPlayerEntitlementChecker* self, StringW levelIdCS) { - missingLevelText.clear(); - std::string levelId = levelIdCS; - getLogger().info("NetworkPlayerEntitlementChecker_GetEntitlementStatus: %s", levelId.c_str()); - if (IsCustomLevel(levelId)) { - if (HasSong(levelId)) { - //std::optional level = RuntimeSongLoader::API::GetLevelById(levelId); - if (MultiQuestensions::Utils::HasRequirement(RuntimeSongLoader::API::GetLevelById(levelId))) - return Task_1::New_ctor(EntitlementsStatus::Ok); - else return Task_1::New_ctor(EntitlementsStatus::NotOwned); - } - else { - auto task = Task_1::New_ctor(); - BeatSaver::API::GetBeatmapByHashAsync(GetHash(levelId), - [task, levelId](std::optional beatmaps) { - QuestUI::MainThreadScheduler::Schedule( - [task, beatmaps, levelId] { - if (beatmaps.has_value()) { - // TODO: Server side check, possibly something better mod side as well, this would just prevent downloading - // Possibly taking a look at this https://github.com/BSMGPink/PinkCore/blob/master/include/Utils/RequirementUtils.hpp - //for (auto& beatmap : beatmaps->GetVersions()) { - auto& beatmap = beatmaps->GetVersions().front(); - std::string mapHash = beatmap.GetHash(); - std::transform(mapHash.begin(), mapHash.end(), mapHash.begin(), toupper); - if (mapHash == GetHash(levelId)) { - for (auto& diff : beatmap.GetDiffs()) { - if (diff.GetChroma() && !AllPlayersHaveChroma() && Modloader::getMods().find("Chroma") != Modloader::getMods().end()) { - task->TrySetResult(EntitlementsStatus::NotOwned); - getLogger().warning("Map contains Chroma difficulty and Chroma is installed, returning NotOwned as Chroma currently causes issues in Multiplayer"); - missingLevelText = "Chroma Requirement block, please uninstall Chroma"; - return; - } - else if (diff.GetNE() && !AllPlayersHaveNE() && Modloader::getMods().find("NoodleExtensions") == Modloader::getMods().end()) { - task->TrySetResult(EntitlementsStatus::NotOwned); - getLogger().warning("Map contains NE difficulty but NoodleExtensions doesn't seem to be installed, returning NotOwned"); - missingLevelText = "You or another Player is Missing the following Requirement: Noodle Extensions"; - return; - } - else if (diff.GetME() && !AllPlayersHaveME() && Modloader::getMods().find("MappingExtensions") == Modloader::getMods().end()) { - task->TrySetResult(EntitlementsStatus::NotOwned); - getLogger().warning("Map contains ME difficulty but MappingExtensions doesn't seem to be installed, returning NotOwned"); - missingLevelText = "You or another Player is Missing the following Requirement: Mapping Extensions"; - return; - } - } - task->TrySetResult(EntitlementsStatus::NotDownloaded); - return; - } - else { - getLogger().error("Hash returned by BeatSaver doesn't match requested hash: Expected: '%s' got '%s'", GetHash(levelId).c_str(), mapHash.c_str()); - missingLevelText = string_format("Hash returned by BeatSaver doesn't match requested hash: Expected: '%s' got '%s'", GetHash(levelId).c_str(), mapHash.c_str()); - } - //} - task->TrySetResult(EntitlementsStatus::NotOwned); - } - else { - task->TrySetResult(EntitlementsStatus::NotOwned); - } - } - ); - } - ); - return task; - } - } - else { - return NetworkPlayerEntitlementChecker_GetEntitlementStatus(self, levelIdCS); - } - } - - MAKE_HOOK_MATCH(NetworkPlayerEntitlementChecker_Start, &NetworkPlayerEntitlementChecker::Start, void, NetworkPlayerEntitlementChecker* self) { - //entitlementAction = il2cpp_utils::MakeDelegate*>(classof(System::Action_3<::Il2CppString*, ::Il2CppString*, EntitlementsStatus>*), (std::function) [&](Il2CppString* userId, Il2CppString* beatmapId, EntitlementsStatus status) { - // HandleEntitlementReceived(userId, beatmapId, status); - // }); - //self->rpcManager->add_setIsEntitledToLevelEvent(entitlementAction); - self->dyn__rpcManager()->add_setIsEntitledToLevelEvent( - il2cpp_utils::MakeDelegate*>(classof(System::Action_3<::StringW, ::StringW, EntitlementsStatus>*), (std::function) [&](StringW userId, StringW beatmapId, EntitlementsStatus status) { - HandleEntitlementReceived(userId, beatmapId, status); - })); - NetworkPlayerEntitlementChecker_Start(self); - } - - // Causes crash when being called - //MAKE_HOOK_MATCH(NetworkPlayerEntitlementChecker_OnDestroy, &NetworkPlayerEntitlementChecker::OnDestroy, void, NetworkPlayerEntitlementChecker* self) { - // if (entitlementAction) - // self->rpcManager->remove_setIsEntitledToLevelEvent(entitlementAction); - // NetworkPlayerEntitlementChecker_OnDestroy(self); - //} -#pragma endregion - - void Hooks::NetworkplayerEntitlementChecker() { - INSTALL_HOOK_ORIG(getLogger(), NetworkPlayerEntitlementChecker_GetEntitlementStatus); - INSTALL_HOOK(getLogger(), NetworkPlayerEntitlementChecker_Start); - //INSTALL_HOOK(getLogger(), NetworkPlayerEntitlementChecker_OnDestroy); - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/QuickplayHooks.cpp b/MultiQuestensions/src/Hooks/QuickplayHooks.cpp deleted file mode 100644 index ad0157a..0000000 --- a/MultiQuestensions/src/Hooks/QuickplayHooks.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "main.hpp" -#include "Hooks/Hooks.hpp" -#include "GlobalFields.hpp" - -#include "GlobalNamespace/MasterServerQuickPlaySetupData_QuickPlaySongPacksOverride_PredefinedPack.hpp" -#include "GlobalNamespace/MasterServerQuickPlaySetupData_QuickPlaySongPacksOverride_LocalizedCustomPack.hpp" -#include "GlobalNamespace/MasterServerQuickPlaySetupData_QuickPlaySongPacksOverride_LocalizedCustomPackName.hpp" -#include "GlobalNamespace/MasterServerQuickPlaySetupData_QuickPlaySongPacksOverride.hpp" -#include "GlobalNamespace/MasterServerQuickPlaySetupData.hpp" -#include "GlobalNamespace/BloomFilterUtil.hpp" - -//#include "CodegenExtensions/TempBloomFilterUtil.hpp" - -//#include "GlobalNamespace/MasterServerQuickPlaySetupModel.hpp" -#include "GlobalNamespace/SongPackMaskModelSO.hpp" - -#include "GlobalNamespace/MultiplayerModeSelectionFlowCoordinator.hpp" -#include "GlobalNamespace/JoinQuickPlayViewController.hpp" -#include "GlobalNamespace/SimpleDialogPromptViewController.hpp" -#include "GlobalNamespace/MultiplayerModeSettings.hpp" - -#include "HMUI/ViewController_AnimationDirection.hpp" -#include "HMUI/ViewController_AnimationType.hpp" - -#include "Polyglot/Localization.hpp" -#include "Polyglot/LanguageExtensions.hpp" - -#include "GlobalNamespace/QuickPlaySongPacksDropdown.hpp" - -using namespace GlobalNamespace; - -using MSQSD_QPSPO_PredefinedPack = MasterServerQuickPlaySetupData::QuickPlaySongPacksOverride::PredefinedPack; -using MSQSD_QPSPO_LocalizedCustomPack = MasterServerQuickPlaySetupData::QuickPlaySongPacksOverride::LocalizedCustomPack; -using MSQD_QPSPO_LocalizedCustomPackName = MasterServerQuickPlaySetupData::QuickPlaySongPacksOverride::LocalizedCustomPackName; - -bool gotSongPackOverrides = false; - -namespace MultiQuestensions { - // Check for our custom packs - MAKE_HOOK_MATCH(QuickPlaySongPacksDropdown_LazyInit, &QuickPlaySongPacksDropdown::LazyInit, void, QuickPlaySongPacksDropdown* self) { - gotSongPackOverrides = (self->dyn__quickPlaySongPacksOverride() != nullptr); - QuickPlaySongPacksDropdown_LazyInit(self); - } - - MAKE_HOOK_MATCH(MultiplayerModeSelectionFlowCoordinator_HandleJoinQuickPlayViewControllerDidFinish, &MultiplayerModeSelectionFlowCoordinator::HandleJoinQuickPlayViewControllerDidFinish, void, MultiplayerModeSelectionFlowCoordinator* self, bool success) { - StringW levelPackName = self->dyn__joinQuickPlayViewController()->dyn__multiplayerModeSettings()->dyn_quickPlaySongPackMaskSerializedName(); - if (success && - self->dyn__songPackMaskModel()->ToSongPackMask( - levelPackName - ).Contains( - BloomFilterUtil::ToBloomFilter(getCustomLevelSongPackMaskStr(), 2, 13)) - ) { - self->dyn__simpleDialogPromptViewController()->Init( - "Custom Song Quickplay", - "This category includes songs of varying difficulty.\nIt may be more enjoyable to play in a private lobby with friends.", - "Continue", - "Cancel", - il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function)[self, success](int btnId) { - switch (btnId) - { - default: - case 0: // Continue - MultiplayerModeSelectionFlowCoordinator_HandleJoinQuickPlayViewControllerDidFinish(self, success); - return; - case 1: // Cancel - //self->DismissViewController(self->dyn__simpleDialogPromptViewController(), HMUI::ViewController::AnimationDirection::Vertical, nullptr, false); - self->ReplaceTopViewController(self->dyn__joinQuickPlayViewController(), nullptr, HMUI::ViewController::AnimationType::In, HMUI::ViewController::AnimationDirection::Vertical); - return; - } - } - ) - ); - self->ReplaceTopViewController(self->dyn__simpleDialogPromptViewController(), nullptr, HMUI::ViewController::AnimationType::In, HMUI::ViewController::AnimationDirection::Vertical); - } else MultiplayerModeSelectionFlowCoordinator_HandleJoinQuickPlayViewControllerDidFinish(self, success); - } - - //MAKE_HOOK_MATCH(MasterServerQuickPlaySetupModel_GetQuickPlaySetupInternal, &MasterServerQuickPlaySetupModel::GetQuickPlaySetupInternal, System::Threading::Tasks::Task_1*, MasterServerQuickPlaySetupModel* self) { - // getLogger().debug("MasterServerQuickPlaySetupModel::GetQuickPlaySetupInternal"); - // using T1_MasterServerQuickplaySetupData = System::Threading::Tasks::Task_1*; - // T1_MasterServerQuickplaySetupData result = MasterServerQuickPlaySetupModel_GetQuickPlaySetupInternal(self); - // auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function)[result] { - // MasterServerQuickPlaySetupData* data = result->get_ResultOnSuccess(); - // if (data) { - // MasterServerQuickPlaySetupData::QuickPlaySongPacksOverride* overrides = data->dyn_quickPlayAvailablePacksOverride(); - // getLogger().debug("MasterServerQuickplaySetupData: hasOverride: '%s', Check _quickPlayAvailablePacksOverride Pointer: '%p'", data->get_hasOverride() ? "true" : "false", overrides); - // using PredefinedPack = MasterServerQuickPlaySetupData::QuickPlaySongPacksOverride::PredefinedPack; - // for (int i = 0; i < overrides->dyn_predefinedPackIds()->get_Count(); i++) { - // PredefinedPack* pack = overrides->dyn_predefinedPackIds()->get_Item(i); - // getLogger().debug("predefinedPackIds: order: '%d', packId: '%s'", pack->dyn_order(), to_utf8(csstrtostr(pack->dyn_packId())).c_str()); - // } - // using LocalizedCustomPack = MasterServerQuickPlaySetupData::QuickPlaySongPacksOverride::LocalizedCustomPack; - // for (int i = 0; i < overrides->dyn_localizedCustomPacks()->get_Count(); i++) { - // LocalizedCustomPack* pack = overrides->dyn_localizedCustomPacks()->get_Item(i); - // getLogger().debug("predefinedPackIds: order: '%d', serializedName: '%s'", pack->dyn_order(), to_utf8(csstrtostr(pack->dyn_serializedName())).c_str()); - // for (int j = 0; j < pack->dyn_packIds()->get_Count(); j++) { - // getLogger().debug("predefinedPackIds packId '%d': packId: '%s'", j, to_utf8(csstrtostr(pack->dyn_packIds()->get_Item(j))).c_str()); - // } - // } - // } - // else { - // getLogger().debug("MasterServerQuickPlaySetupModel::GetQuickPlaySetupInternal: Task does not have Results"); - // } - // } - // ); - // reinterpret_cast(result)->ContinueWith(action); - - // return result; - //} - - void Hooks::QuickplayHooks() { - INSTALL_HOOK(getLogger(), QuickPlaySongPacksDropdown_LazyInit); - INSTALL_HOOK(getLogger(), MultiplayerModeSelectionFlowCoordinator_HandleJoinQuickPlayViewControllerDidFinish); - //INSTALL_HOOK(getLogger(), MasterServerQuickPlaySetupModel_GetQuickPlaySetupInternal); - } -} - diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp deleted file mode 100644 index 8381eb4..0000000 --- a/MultiQuestensions/src/Hooks/SessionManagerAndExtendedPlayerHooks.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include "main.hpp" -#include "Hooks/Hooks.hpp" -#include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" -#include "GlobalFields.hpp" -#include "Hooks/EnvironmentAndAvatarHooks.hpp" -#include "UI/CenterScreenLoading.hpp" -#include "Utils/SemVerChecker.hpp" - -#include "Beatmaps/PreviewBeatmapStub.hpp" - -#include "GlobalNamespace/IPlatformUserModel.hpp" -#include "GlobalNamespace/LocalNetworkPlayerModel.hpp" -#include "UnityEngine/Resources.hpp" -#include "GlobalNamespace/UserInfo.hpp" - -#include "CodegenExtensions/ColorUtility.hpp" - -#include "questui/shared/BeatSaberUI.hpp" -#include "questui/shared/CustomTypes/Components/MainThreadScheduler.hpp" -#include "songdownloader/shared/BeatSaverAPI.hpp" -using namespace MultiQuestensions; -using namespace GlobalNamespace; - -// Handles a PreviewBeatmapPacket used to transmit data about a custom song. -static void HandlePreviewBeatmapPacket(MultiQuestensions::Beatmaps::PreviewBeatmapPacket* packet, GlobalNamespace::IConnectedPlayer* player) { - getLogger().debug("'%s' selected song '%s'", std::string(player->get_userId()).c_str(), std::string(packet->levelHash).c_str()); - IPreviewBeatmapLevel* localPreview = lobbyPlayersDataModel->dyn__beatmapLevelsModel()->GetLevelPreviewForLevelId(packet->levelId); - MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview; - try { - if (localPreview == nullptr) { - Il2CppString* nullString = nullptr; - IPreviewBeatmapLevel* nullLvl = nullptr; - preview = THROW_UNLESS(il2cpp_utils::New(nullString, nullLvl, packet)); - getLogger().info("Try getting CoverImage from BeatSaver"); - std::string levelid = to_utf8(csstrtostr(preview->get_levelID())); - BeatSaver::API::GetBeatmapByHashAsync(GetHash(levelid), - [preview, player, packet](std::optional beatmap) { - if (beatmap.has_value()) { - BeatSaver::API::GetCoverImageAsync(*beatmap, [preview, player, packet](std::vector bytes) { - QuestUI::MainThreadScheduler::Schedule([packet, player, preview, bytes] { - if (packet && player && preview && lobbyPlayersDataModel) { - preview->coverImage = QuestUI::BeatSaberUI::VectorToSprite(bytes); - BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(packet->characteristic); - lobbyPlayersDataModel->SetPlayerBeatmapLevel(player->get_userId(), reinterpret_cast(preview), packet->difficulty, characteristic); - } - else { - getLogger().error("Error nullptr: packet='%p', player='%p', preview='%p', lobbyPlayersDataModel='%p'", packet, player, preview, lobbyPlayersDataModel); - } - } - ); - } - ); - } - else { - QuestUI::MainThreadScheduler::Schedule([packet, player, preview] { - if (packet && player && preview) { - BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(packet->characteristic); - lobbyPlayersDataModel->SetPlayerBeatmapLevel(player->get_userId(), reinterpret_cast(preview), packet->difficulty, characteristic); - } - else { - getLogger().error("Error nullptr: packet='%p', player='%p', preview='%p', lobbyPlayersDataModel='%p'", packet, player, preview, lobbyPlayersDataModel); - } - } - ); - } - } - ); - return; - } - else { - MultiQuestensions::Beatmaps::PreviewBeatmapPacket* nullpacket = nullptr; - preview = THROW_UNLESS(il2cpp_utils::New(packet->levelHash, localPreview, nullpacket)); - } - BeatmapCharacteristicSO* characteristic = lobbyPlayersDataModel->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(packet->characteristic); - //getLogger().debug("Check difficulty as unsigned int: %u", packet->difficulty); - lobbyPlayersDataModel->SetPlayerBeatmapLevel(player->get_userId(), reinterpret_cast(preview), packet->difficulty, characteristic); - } - catch (const std::runtime_error& e) { - getLogger().error("REPORT TO ENDER: %s", e.what()); - } - catch (...) { - getLogger().debug("REPORT TO ENDER: Unknown exception in HandlePreviewBeatmapPacket"); - } -} - - -std::map> _extendedPlayers; -//System::Collections::Generic::Dictionary_2* extendedPlayers; -//SafePtr*> extendedPlayersSPTR; -//SafePtr localExtendedPlayerSPTR; -SafePtr localExtendedPlayer; -IPlatformUserModel* platformUserModel; - -static void HandleExtendedPlayerPacket(MultiQuestensions::Extensions::ExtendedPlayerPacket* packet, IConnectedPlayer* player) { - const std::string userId = to_utf8(csstrtostr(player->get_userId())); - //if (extendedPlayers->ContainsKey(player->get_userId())) { - if (_extendedPlayers.contains(userId)) { - SafePtr extendedPlayer = _extendedPlayers.at(userId); - //Extensions::ExtendedPlayer* extendedPlayer = extendedPlayers->get_Item(player->get_userId()); - extendedPlayer->_connectedPlayer = player; - extendedPlayer->platformID = packet->platformID; - extendedPlayer->platform = packet->platform; - extendedPlayer->playerColor = packet->playerColor; - extendedPlayer->mpexVersion = packet->mpexVersion; - - // Updates Color and NameTag - SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); - CreateOrUpdateNameTag(reinterpret_cast(extendedPlayer->get_self())); - } - else { - getLogger().info("Received 'ExtendedPlayerPacket' from '%s' with platformID: '%s' mpexVersion: '%s'", - std::string(player->get_userId()).c_str(), - std::string(packet->platformID).c_str(), - std::string(packet->mpexVersion).c_str() - ); - Extensions::ExtendedPlayer* extendedPlayer; - try { - extendedPlayer = Extensions::ExtendedPlayer::CS_ctor(player, packet->platformID, packet->platform, packet->mpexVersion, packet->playerColor); - if (std::string(extendedPlayer->mpexVersion) != MPEX_PROTOCOL) - { - getLogger().warning( - "###################################################################\r\n" - "Different MultiplayerExtensions protocol detected!\r\n" - "The player '%s' is using MpEx protocol version %s while you are using MpEx protocol " MPEX_PROTOCOL "\r\n" - "For best compatibility all players should use a compatible version of MultiplayerExtensions/MultiQuestensions.\r\n" - "###################################################################", - std::string(player->get_userName()).c_str(), - std::string(extendedPlayer->mpexVersion).c_str() - ); - } - } - catch (const std::runtime_error& e) { - getLogger().error("REPORT TO ENDER: Exception while trying to create ExtendedPlayer: %s", e.what()); - } - if (extendedPlayer) { - _extendedPlayers.emplace(userId, extendedPlayer); - //extendedPlayers->Add(player->get_userId(), extendedPlayer); - //if (!extendedPlayersSPTR) extendedPlayersSPTR = extendedPlayers; - - //getLogger().debug("SetPlayerPlaceColor"); - SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); - //getLogger().debug("CreateOrUpdateNameTag"); - // This packet is usually received before the avatar is actually created - CreateOrUpdateNameTag(reinterpret_cast(extendedPlayer->get_self())); - getLogger().debug("ExtendedPlayerPacket done"); - - //extendedPlayerConnectedEvent::Invoke(extendedPlayer); - } - } -} - -void HandlePlayerConnected(IConnectedPlayer* player) { - try { - getLogger().debug("HandlePlayerConnected"); - if (player) { - const std::string userId = player->get_userId(); - getLogger().info("Player '%s' joined", userId.c_str()); - getLogger().debug("Sending ExtendedPlayerPacket"); - if (localExtendedPlayer->get_platformID() != nullptr) - { - Extensions::ExtendedPlayerPacket* localPlayerPacket = Extensions::ExtendedPlayerPacket::Init(localExtendedPlayer->get_platformID(), localExtendedPlayer->get_platform(), localExtendedPlayer->get_playerColor()); - //getLogger().debug("LocalPlayer Color is, R: %f G: %f B: %f", localPlayerPacket->playerColor.r, localPlayerPacket->playerColor.g, localPlayerPacket->playerColor.b); - packetManager->Send(reinterpret_cast(localPlayerPacket)); - } - getLogger().debug("ExtendedPlayerPacket sent"); - - SetPlayerPlaceColor(player, Extensions::ExtendedPlayer::DefaultColor, false); - } - } - catch (const std::runtime_error& e) { - getLogger().error("REPORT TO ENDER: %s", e.what()); - } -} - -void HandlePlayerDisconnected(IConnectedPlayer* player) { - getLogger().info("Player '%s' left", std::string(player->get_userId()).c_str()); - getLogger().debug("Reseting platform lights"); - SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); - _extendedPlayers.erase(std::string(player->get_userId()).c_str()); -} - -//void HandleDisconnect(DisconnectedReason* reason) { -//} - -MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, MultiplayerSessionManager* self) { - - sessionManager = self; - SessionManagerStart(sessionManager); - packetManager = new PacketManager(sessionManager); - - - packetManager->RegisterCallback("MultiplayerExtensions.Beatmaps.PreviewBeatmapPacket", HandlePreviewBeatmapPacket); - packetManager->RegisterCallback("MultiplayerExtensions.Extensions.ExtendedPlayerPacket", HandleExtendedPlayerPacket); -} - -MAKE_HOOK_FIND_VERBOSE(SessionManager_StartSession, il2cpp_utils::FindMethodUnsafe("", "MultiplayerSessionManager", "StartSession", 1), void, MultiplayerSessionManager* self, ConnectedPlayerManager* connectedPlayerManager) { - SessionManager_StartSession(self, connectedPlayerManager); - getLogger().debug("MultiplayerSessionManager.StartSession, creating localExtendedPlayerPacket"); - //try { - localExtendedPlayer = Extensions::ExtendedPlayer::CS_ctor(self->get_localPlayer()); - //localExtendedPlayerSPTR = localExtendedPlayer; - - if (!UnityEngine::ColorUtility::TryParseHtmlString(il2cpp_utils::newcsstr(getConfig().config["color"].GetString()), localExtendedPlayer->playerColor)) - localExtendedPlayer->playerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f, 1.0f); - - static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll().get(0); - static auto UserInfoTask = localNetworkPlayerModel->dyn__platformUserModel()->GetUserInfo(); - static auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function*)>)[&](System::Threading::Tasks::Task_1* userInfoTask) { - auto userInfo = userInfoTask->get_Result(); - if (userInfo) { - localExtendedPlayer->platformID = userInfo->dyn_platformUserId(); - localExtendedPlayer->platform = (Extensions::Platform)userInfo->dyn_platform().value; - } - else getLogger().error("Failed to get local network player!"); - } - ); - reinterpret_cast(UserInfoTask)->ContinueWith(action); - - using namespace MultiQuestensions::Utils; - self->SetLocalPlayerState(getModdedStateStr(), true); - self->SetLocalPlayerState(getMEStateStr(), MatchesVersion("MappingExtensions", "*")); - self->SetLocalPlayerState(getNEStateStr(), MatchesVersion("NoodleExtensions", "*")); - self->SetLocalPlayerState(getChromaStateStr(), MatchesVersion(ChromaID, ChromaVersionRange)); - // TODO: Do this check correctly once Chroma got an Update for Multiplayer - - //} - //catch (const std::runtime_error& e) { - // getLogger().error("%s", e.what()); - //} - self->add_playerConnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerConnected)); - self->add_playerDisconnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerDisconnected)); - //self->add_disconnectedEvent(il2cpp_utils::MakeDelegate*>*>(classof(System::Action_1*>*), static_cast(nullptr), HandleDisconnect)); -} - - -void MultiQuestensions::Hooks::SessionManagerAndExtendedPlayerHooks() { - INSTALL_HOOK(getLogger(), SessionManagerStart); - INSTALL_HOOK(getLogger(), SessionManager_StartSession); -} \ No newline at end of file diff --git a/MultiQuestensions/src/Packets/PacketManager.cpp b/MultiQuestensions/src/Packets/PacketManager.cpp deleted file mode 100644 index a14aca8..0000000 --- a/MultiQuestensions/src/Packets/PacketManager.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "Packets/PacketManager.hpp" -#include "Packets/PacketSerializer.hpp" -#include "beatsaber-hook/shared/utils/il2cpp-utils.hpp" -#include "UnityEngine/GameObject.hpp" - -#include "GlobalNamespace/StandardScoreSyncStateNetSerializable.hpp" - -namespace MultiQuestensions { - PacketManager::PacketManager(GlobalNamespace::MultiplayerSessionManager* sessionManager) { - //if (packetSerializer == nullptr) { - getLogger().info("Creating Packet serializer."); - - _sessionManager = sessionManager; - packetSerializer = CRASH_UNLESS(il2cpp_utils::New()); - GlobalNamespace::MultiplayerSessionManager_MessageType messageType = (GlobalNamespace::MultiplayerSessionManager_MessageType)100; - - _sessionManager->RegisterSerializer(messageType, reinterpret_cast*>(packetSerializer)); - //} else { - // getLogger().info("Packet serializer already exists."); - //} - } - - void PacketManager::Send(LiteNetLib::Utils::INetSerializable* message) { - getLogger().debug("Running send"); - if (_sessionManager != nullptr && message != nullptr) { - _sessionManager->Send(message); - getLogger().debug("Sent message"); - } - else getLogger().error("Failed to Send message"); - } - - void PacketManager::SendUnreliable(LiteNetLib::Utils::INetSerializable* message) { - if (_sessionManager != nullptr && message != nullptr) { - _sessionManager->SendUnreliable(message); - getLogger().debug("Sent message"); - } - else getLogger().error("Failed to SendUnreliable message"); - } - - void PacketManager::UnregisterCallback(std::string identifier) { - packetSerializer->UnregisterCallback(identifier); - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/Packets/PacketSerializer.cpp b/MultiQuestensions/src/Packets/PacketSerializer.cpp deleted file mode 100644 index 53fe680..0000000 --- a/MultiQuestensions/src/Packets/PacketSerializer.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "Packets/PacketSerializer.hpp" -#include "GlobalNamespace/BeatmapIdentifierNetSerializable.hpp" - -DEFINE_TYPE(MultiQuestensions, PacketSerializer); - -namespace MultiQuestensions { - void PacketSerializer::Construct() { - registeredTypes = std::move(TypeDictionary()); - packetHandlers = std::move(CallbackDictionary()); - } - - void PacketSerializer::Deconstruct() { - getLogger().debug("PacketSerializer::Deconstruct"); - for (auto it = packetHandlers.begin(); it != packetHandlers.end(); it++) { - delete it->second; - } - packetHandlers.clear(); - } - - void PacketSerializer::Serialize(LiteNetLib::Utils::NetDataWriter* writer, LiteNetLib::Utils::INetSerializable* packet) { - Il2CppReflectionType* packetType = il2cpp_utils::GetSystemType(il2cpp_functions::object_get_class(reinterpret_cast(packet))); - getLogger().debug("Serialize packetType is: %s", to_utf8(csstrtostr(packetType->ToString())).c_str()); - getLogger().debug("Registered types check: %s", registeredTypes[packetType].c_str()); - writer->Put(StringW(registeredTypes[packetType])); - //writer->Put(packetType->ToString()); - getLogger().debug("Writer Put"); - getLogger().debug("Nullptr checking: packet: %p, writer: %p", packet, writer); - packet->Serialize(writer); - getLogger().debug("Serialize Finished"); - } - - void PacketSerializer::Deserialize(LiteNetLib::Utils::NetDataReader* reader, int length, GlobalNamespace::IConnectedPlayer* data) { - getLogger().debug("PacketSerializer::Deserialize"); - int prevPosition = reader->get_Position(); - std::string packetType = reader->GetString(); - getLogger().debug("packetType: %s", packetType.c_str()); - length -= reader->get_Position() - prevPosition; - getLogger().debug("length: %d", length); - prevPosition = reader->get_Position(); - if (packetHandlers.find(packetType) != packetHandlers.end()) { - getLogger().debug("packetHandlers found PacketType, try Invoke"); - try { - packetHandlers[packetType]->Invoke(reader, length, data); - } - catch (const std::exception& e) { - getLogger().warning("An C++ exception was thrown while processing custom packet"); - getLogger().error("REPORT TO ENDER: %s", e.what()); - } - catch (...) { - getLogger().warning("REPORT TO ENDER: An Unknown exception was thrown while processing custom packet"); - } - } - int processedBytes = reader->get_Position() - prevPosition; - reader->SkipBytes(length - processedBytes); - } - - bool PacketSerializer::HandlesType(Il2CppReflectionType* type) { - auto it = registeredTypes.find(type); - if (it != registeredTypes.end()) { - getLogger().debug("HandlesType: %s", it->second.c_str()); - return true; - } - return false; - } - - void PacketSerializer::UnregisterCallback(std::string identifier) { - getLogger().debug("UnregisterCallback called"); - - for (auto it = registeredTypes.begin(); it != registeredTypes.end(); it++) { - if (it->second == identifier) registeredTypes.erase(it); - } - - auto itr = packetHandlers.find(identifier); - if (itr != packetHandlers.end()) { - delete itr->second; - packetHandlers.erase(itr); - } - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/UI/CenterScreenLoading.cpp b/MultiQuestensions/src/UI/CenterScreenLoading.cpp deleted file mode 100644 index 8619a19..0000000 --- a/MultiQuestensions/src/UI/CenterScreenLoading.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "main.hpp" -#include "GlobalFields.hpp" -#include "UI/CenterScreenLoading.hpp" -#include "UnityEngine/GameObject.hpp" -#include "UnityEngine/Resources.hpp" -#include "UnityEngine/Transform.hpp" -#include "UnityEngine/RectOffset.hpp" -#include "UnityEngine/UI/LayoutElement.hpp" -using namespace GlobalNamespace; -using namespace UnityEngine; -using namespace UnityEngine::UI; - -#include "questui/shared/BeatSaberUI.hpp" - -DEFINE_TYPE(MultiQuestensions::UI, CenterScreenLoading); - -namespace MultiQuestensions::UI{ - - CenterScreenLoading* CenterScreenLoading::instance; - int CenterScreenLoading::playersReady; - - void CenterScreenLoading::Awake() { - getLogger().debug("CenterScreenLoading::Awake"); - instance = this; - screenController = get_gameObject()->GetComponentInParent(); - gameStateController = lobbyGameStateController; - - UnityEngine::UI::VerticalLayoutGroup* vertical = QuestUI::BeatSaberUI::CreateVerticalLayoutGroup(get_transform()); - vertical->get_rectTransform()->set_sizeDelta({ 60, 60 }); - vertical->get_rectTransform()->set_anchoredPosition({ 0.0f, -30.0f }); - auto layout = vertical->get_gameObject()->AddComponent(); - //layout->set_preferredHeight(GameListSizeDelta.y); - layout->set_minWidth(60); - //vertical->set_padding(UnityEngine::RectOffset::New_ctor(0, 0, 30, 10)); - - GameObject* existingLoadingControl = Resources::FindObjectsOfTypeAll()[0]->get_gameObject(); - GameObject* loadingControlGameObject = UnityEngine::GameObject::Instantiate(existingLoadingControl, vertical->get_transform()); - loadingControl = loadingControlGameObject->GetComponent(); - loadingControl->Hide(); - } - - void CenterScreenLoading::OnDisable() { - getLogger().debug("CenterScreenLoading::OnDisable"); - isDownloading = false; - if (loadingControl) { - loadingControl->Hide(); - } - playersReady = 0; - } - - void CenterScreenLoading::ShowLoading() { - int maxPlayers = sessionManager ? sessionManager->get_connectedPlayerCount() + 1 : 1; - int readyPlayers = std::min(playersReady + 1, maxPlayers); - getLogger().info("CenterScreenLoading::ShowLoading, players ready (%d of %d)", - readyPlayers, maxPlayers); - if (loadingControl) { - loadingControl->ShowLoading(string_format("%d of %d players ready...", - readyPlayers, maxPlayers).c_str()); - } - } - - void CenterScreenLoading::ShowDownloadingProgress(float downloadingProgress) { - //getLogger().debug("CenterScreenLoading::ShowDownloadingProgress: %f2", downloadingProgress); - isDownloading = (downloadingProgress < 100.0f); - if (loadingControl) { - //static Il2CppString* string = il2cpp_utils::newcsstr("Downloading..."); - loadingControl->ShowDownloadingProgress(il2cpp_utils::newcsstr(string_format("Downloading (%.2f%%)...", downloadingProgress)), downloadingProgress / 100); - } - } - - void CenterScreenLoading::HideLoading() { - getLogger().debug("CenterScreenLoading::HideLoading"); - if (get_Instance() && get_Instance()->loadingControl) { - get_Instance()->loadingControl->Hide(); - } - } - - - void CenterScreenLoading::FixedUpdate() { - if (isDownloading) - { - return; - } - else if (screenController->get_countdownShown() && gameStateController && sessionManager->get_syncTime() >= gameStateController->get_startTime() && gameStateController->get_levelStartInitiated()) - { - if (loadingControl) - loadingControl->ShowLoading(string_format("%d of %d players ready...", - playersReady + 1, sessionManager ? sessionManager->get_connectedPlayerCount() + 1 : 1).c_str()); - } - else - { - if (loadingControl) - loadingControl->Hide(); - playersReady = 0; - } - } - -} \ No newline at end of file diff --git a/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp b/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp deleted file mode 100644 index 226ef38..0000000 --- a/MultiQuestensions/src/UI/DownloadedSongsGSM.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* -* DownloadedSongsGameplaySetupMenu -* Copyright (c) EnderdracheLP -*/ - -#include "main.hpp" -#include "UI/DownloadedSongsGSM.hpp" - -#include "questui/shared/BeatSaberUI.hpp" -#include "songloader/shared/API.hpp" - -#include "HMUI/ModalView.hpp" -#include "System/Threading/Tasks/Task.hpp" -#include "System/Action_1.hpp" - -#include "GlobalFields.hpp" -using namespace GlobalNamespace; -using namespace QuestUI; -using namespace RuntimeSongLoader::API; -using namespace HMUI; -using namespace MultiQuestensions; - - -DEFINE_TYPE(MultiQuestensions::UI, DownloadedSongsGSM); - -namespace MultiQuestensions::UI { - bool cellIsSelected = false; - DownloadedSongsGSM* DownloadedSongsGSM::instance; - std::vector DownloadedSongsGSM::mapQueue; - - void DownloadedSongsGSM::CreateCell(System::Threading::Tasks::Task_1* coverTask, CustomPreviewBeatmapLevel* level) { - getLogger().debug("CreateCell"); - UnityEngine::Sprite* cover = coverTask->get_Result(); - if (cover && level) { - // "" + map.GetMetadata().GetSongAuthorName() + "" + " [" + map.GetMetadata().GetLevelAuthorName() + "]" - list->data.emplace_back(CustomListTableData::CustomCellInfo{ - level->get_songName() ? std::string(level->get_songName()) : "Error: songName null", - (level->get_songAuthorName() ? std::string(level->get_songAuthorName()) : std::string()) + " [" + (level->get_levelAuthorName() ? std::string(level->get_levelAuthorName()) : std::string()) + "]", - cover - }); - } - else if (level) { - list->data.emplace_back(CustomListTableData::CustomCellInfo{ - level->get_songName() ? std::string(level->get_songName()) : "Error: songName null", - (level->get_songAuthorName() ? std::string(level->get_songAuthorName()) : std::string()) + " [" + (level->get_levelAuthorName() ? std::string(level->get_levelAuthorName()) : std::string()) + "]", - level->get_defaultCoverImage() - }); - } else getLogger().error("Nullptr in UI: cover '%p', level '%p'", cover, level); - if (!mapQueue.empty()) { - InsertCell(mapQueue.back()); - mapQueue.pop_back(); - } - if (list && list->tableView) - list->tableView->RefreshCellsContent(); - else getLogger().error("Nullptr in UI: list '%p', list->tableView '%p'", list, list->tableView); - getLogger().debug("CreateCell Finished"); - } - - // TODO: Add index check, check if index is out of bounds - void DownloadedSongsGSM::Delete() { - try { - needSongRefresh = false; - auto level = GetLevelByHash(DownloadedSongIds.at(selectedIdx)); - if (level.has_value()) { - std::string songPath = to_utf8(csstrtostr(level.value()->get_customLevelPath())); - getLogger().info("Deleting Song: %s", songPath.c_str()); - DeleteSong(songPath, [&] { - if (needSongRefresh) { - RefreshSongs(false); - } - }); - if (lobbyGameStateController) lobbyGameStateController->dyn__menuRpcManager()->SetIsEntitledToLevel(level.value()->get_levelID(), EntitlementsStatus::NotOwned); - } - needSongRefresh = true; - DownloadedSongIds.erase(DownloadedSongIds.begin() + selectedIdx); - } - catch (const std::exception& e) { - getLogger().critical("REPORT TO ENDER: Exception encountered trying to delete song: %s", e.what()); - } - list->tableView->ClearSelection(); - list->data.erase(list->data.begin() + selectedIdx); - Refresh(); - modal->Hide(true, nullptr); - } - - // TODO: Add keep all and delete all option - void DownloadedSongsGSM::DidActivate(bool firstActivation) { - if (firstActivation) { - instance = this; - - modal = BeatSaberUI::CreateModal(get_transform(), { 55, 25 }, [this](HMUI::ModalView* self) { - list->tableView->ClearSelection(); - }); - auto wrapper = QuestUI::BeatSaberUI::CreateHorizontalLayoutGroup(modal->get_transform()); - auto container = QuestUI::BeatSaberUI::CreateVerticalLayoutGroup(wrapper->get_transform()); - container->set_childAlignment(UnityEngine::TextAnchor::MiddleCenter); - QuestUI::BeatSaberUI::CreateText(container->get_transform(), "Do you want to delete this song?")->set_alignment(TMPro::TextAlignmentOptions::Center); - - auto horizon = QuestUI::BeatSaberUI::CreateHorizontalLayoutGroup(container->get_transform()); - - QuestUI::BeatSaberUI::CreateUIButton(horizon->get_transform(), "Delete", [this]() -> void { - Delete(); - cellIsSelected = false; - }); - - QuestUI::BeatSaberUI::CreateUIButton(horizon->get_transform(), "Keep", [this]() -> void { - DownloadedSongIds.erase(DownloadedSongIds.begin() + selectedIdx); - list->tableView->ClearSelection(); - list->data.erase(list->data.begin() + selectedIdx); - Refresh(); - modal->Hide(true, nullptr); - cellIsSelected = false; - }); - - list = BeatSaberUI::CreateScrollableList(get_transform(), { 80, 60 }, [this](int idx) { - getLogger().debug("Cell with idx %d clicked", idx); - cellIsSelected = true; - selectedIdx = idx; - modal->Show(true, true, nullptr); - }); - } - getLogger().debug("DownloadedSongsGSM::DidActivate"); - Refresh(); - } - - void DownloadedSongsGSM::InsertCell(std::string hash) { - std::optional levelOpt = GetLevelByHash(hash); - if (levelOpt.has_value()) { - lastDownloaded = levelOpt.value(); - getLogger().info("Song with Hash '%s' added to list", hash.c_str()); - System::Threading::Tasks::Task_1* coverTask = lastDownloaded->GetCoverImageAsync(System::Threading::CancellationToken::get_None()); - auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function)[coverTask, this] { - CreateCell(coverTask, lastDownloaded/*, list->NumberOfCells() + 1*/); - } - ); - reinterpret_cast(coverTask)->ContinueWith(action); - } - else { - getLogger().error("Song with Hash '%s' not found, was it already deleted?", hash.c_str()); - } - } - - void DownloadedSongsGSM::Refresh() { - list->tableView->ReloadData(); - list->tableView->RefreshCellsContent(); - } - - void DownloadedSongsGSM::OnEnable() { - if (list && list->tableView) { - if (!mapQueue.empty()) { - InsertCell(mapQueue.back()); - mapQueue.pop_back(); - } - if (cellIsSelected) list->tableView->ClearSelection(); - list->tableView->ReloadData(); - list->tableView->RefreshCellsContent(); - } - } -} \ No newline at end of file diff --git a/MultiQuestensions/src/Utils/CustomData.cpp b/MultiQuestensions/src/Utils/CustomData.cpp deleted file mode 100644 index 86f0e62..0000000 --- a/MultiQuestensions/src/Utils/CustomData.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "main.hpp" -#include "Utils/CustomData.hpp" -#include "Utils/SemVerChecker.hpp" - -namespace MultiQuestensions::Utils { - bool HasRequirement(const std::optional& beatmapOpt) { - using namespace MultiQuestensions::Utils; - if (beatmapOpt) - { - std::string infodatPath = to_utf8(csstrtostr(beatmapOpt.value()->get_customLevelPath())); - if (fileexists(infodatPath + "/Info.dat")) { - infodatPath += "/Info.dat"; - } - else if (fileexists(infodatPath + "/info.dat")) { - infodatPath += "/info.dat"; - } - else { - getLogger().error("Could not find Info.dat or info.dat"); - return false; - } - rapidjson::Document document; - document.Parse(readfile(infodatPath)); - if (!document.HasParseError() && document.IsObject() && - document.HasMember("_difficultyBeatmapSets") && document["_difficultyBeatmapSets"].IsArray() && !document["_difficultyBeatmapSets"].Empty()) { - for (auto& dBS : document["_difficultyBeatmapSets"].GetArray()) - if (dBS.HasMember("_difficultyBeatmaps") && dBS["_difficultyBeatmaps"].IsArray() && !dBS["_difficultyBeatmaps"].Empty()) { - for (auto& dB : dBS["_difficultyBeatmaps"].GetArray()) { - if (dB.HasMember("_customData") && dB["_customData"].IsObject()) { - if (dB["_customData"].HasMember("_requirements") && dB["_customData"]["_requirements"].IsArray() && - !dB["_customData"]["_requirements"].Empty()) { - for (auto& req : dB["_customData"]["_requirements"].GetArray()) { - getLogger().debug("Found requirement: %s", req.GetString()); - if (strcmp(req.GetString(), "Chroma") == 0 && (!AllPlayersHaveChroma() || !MatchesVersion(ChromaID, ChromaVersionRange))) { - getLogger().warning("Requires Chroma"); - missingLevelText = "Chroma suggestion block, please install or update Chroma"; - return false; - } - else if (strcmp(req.GetString(), "Noodle Extensions") == 0 && (!AllPlayersHaveNE() || !MatchesVersion("NoodleExtensions", "*"))) { - getLogger().warning("Requires Noodle Extensions but it was not installed"); - missingLevelText = "You or another Player are Missing the following Requirement: Noodle Extensions"; - return false; - } - else if (strcmp(req.GetString(), "Mapping Extensions") == 0 && (!AllPlayersHaveME() || !MatchesVersion("MappingExtensions", "*"))) { - getLogger().warning("Requires Mapping Extensions but it was not installed"); - missingLevelText = "You or another Player are Missing the following Requirement: Mapping Extensions"; - return false; - } - } - } - /*if (dB["_customData"].HasMember("_suggestions") && dB["_customData"]["_suggestions"].IsArray() && - !dB["_customData"]["_suggestions"].Empty()) { - for (auto& sug : dB["_customData"]["_suggestions"].GetArray()) { - getLogger().debug("Found suggestion: %s", sug.GetString()); - if (strcmp(sug.GetString(), "Chroma") == 0 && (!AllPlayersHaveChroma() || !MatchesVersion(ChromaID, ChromaVersionRange))) { - getLogger().warning("Suggestion Chroma and Chroma outdated or missing"); - missingLevelText = "Chroma suggestion block, please install or update Chroma"; - return false; - } - getLogger().debug("Checking bools 'All players have chroma': %s, 'MatchesVersion': %s 'Combined check': %s", AllPlayersHaveChroma() ? "true" : "false", MatchesVersion(ChromaID, ChromaVersionRange) ? "true" : "false", (!AllPlayersHaveChroma() || !MatchesVersion(ChromaID, ChromaVersionRange)) ? "true" : "false"); - } - }*/ - } - else getLogger().warning("No _customData or _requirements/_suggestions empty/not an array"); - } - } - else getLogger().error("_difficultyBeatmaps not found, empty or not an array"); - } - else getLogger().error("Failed to parse beatmap or _difficultyBeatmapSets empty/not an array"); - } - missingLevelText.clear(); - return true; - } -} From ad6cc8415e9dbeaae28e3228d76e3557f7cbb5e5 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:39:40 +0200 Subject: [PATCH 10/56] Remove unused string getter in GlobalFields --- MultiQuestensions/include/GlobalFields.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MultiQuestensions/include/GlobalFields.hpp b/MultiQuestensions/include/GlobalFields.hpp index 94389b6..b5ed5c9 100644 --- a/MultiQuestensions/include/GlobalFields.hpp +++ b/MultiQuestensions/include/GlobalFields.hpp @@ -5,7 +5,7 @@ #include "GlobalNamespace/LobbyGameStateController.hpp" // MQE Includes -#include "Packets/PacketManager.hpp" +// #include "Packets/PacketManager.hpp" //#include "System/Collections/Generic/Dictionary_2.hpp" namespace MultiQuestensions { @@ -13,8 +13,6 @@ namespace MultiQuestensions { extern GlobalNamespace::MultiplayerSessionManager* sessionManager; extern GlobalNamespace::LobbyPlayersDataModel* lobbyPlayersDataModel; extern GlobalNamespace::LobbyGameStateController* lobbyGameStateController; - - extern StringW getCustomLevelSongPackMaskStr(); } //extern System::Collections::Generic::Dictionary_2 extendedPlayers; \ No newline at end of file From 9b26e26e1f159c75d6907b57e36b6862d11b2524 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:40:44 +0200 Subject: [PATCH 11/56] Add Meta sprite --- MultiQuestensions/include/Assets/Sprites.hpp | 2 ++ MultiQuestensions/src/Assets/Sprites.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/MultiQuestensions/include/Assets/Sprites.hpp b/MultiQuestensions/include/Assets/Sprites.hpp index 23337aa..8a2f60b 100644 --- a/MultiQuestensions/include/Assets/Sprites.hpp +++ b/MultiQuestensions/include/Assets/Sprites.hpp @@ -5,9 +5,11 @@ namespace MultiQuestensions { class Sprites { static std::string Oculus64; static std::string Steam64; + static std::string Meta64; public: static UnityEngine::Sprite* IconOculus64(); static UnityEngine::Sprite* IconSteam64(); + static UnityEngine::Sprite* IconMeta64(); }; } \ No newline at end of file diff --git a/MultiQuestensions/src/Assets/Sprites.cpp b/MultiQuestensions/src/Assets/Sprites.cpp index 0f6d65c..205f604 100644 --- a/MultiQuestensions/src/Assets/Sprites.cpp +++ b/MultiQuestensions/src/Assets/Sprites.cpp @@ -13,6 +13,7 @@ namespace MultiQuestensions { std::string Sprites::Oculus64 = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAAHdbkFIAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAN1sAADdbAZmDAsYAAATaSURBVGhD7ZrNq1ZFHMefey21yDSxNyIKKtEyfIEgWgkhIaUFERFKK1GQJHvHZatCFymE/0ALk9zUImpViwiM3l8X1yRSVCKvZaWm5u3znfnd6zNz3u9zjtxb84EvvzNn3ufMnDMvpzcwQ2Z7Y2NjMzHb0AU0PDQ09LLuO/B8E+UxYzyA+M45DLun1JxjkXeHOM8pQH87PIm5xbt6H9AOH+nCBSgqMYF8AnkBxu/VS+G/BHU9rwrX4GmLchHzcNitDHjN8iEcR3Vv2PlE4LkKLYyF1x4fwuESCCDQalSJBU9MGTLDiae0CPMoivvIn2gPI/CYd3omEiDi1Zjfvauc/nHcn0CjDhK8DIi7VgkYG+12BvyO+iBRZrh3+9vlpcD7Jh/qYjhXDNzXY8Yb5zy6y18GXIYmPgBBFQSJXHBJ1+NrixaCx1/ev5RPLHgikaiCATOMXkHnNHoG4DN0pyVbDYFnokOK2QGaxgUELyQCOOMcWc6hA/6yFMWfg252riyv8x7cYtchFGC7K2fIIfNuDHHv90kEnDVvR/zdy853er1riTTXrpuy1mw/Z8w6wm8CkNlpzGzv6oRlPIKv7Do7O8TzCszz3tUqo2hef+aV0Bqz0TNoBDXlLNqHVlhyiUQikUjkkvkcx/AxuQFzO7oHaRns9/Py0ddVy8PDaD86yNcvmIDUhowXI00oB0HbT6+i3E2hQoiwRbFbRAVR61VDwPUuSvscRtrkDYhnxdrQ1TPsin30icfs2hEXYCcmux3oUcc6iao6rqbld6DLnSsLZShIggIcQTHHUONJKnE2uNhZHrEgWfDUPC5mlXk3hrg/+yQCdpi3Ix4e2sqJ+cHsZPjDbD9XmXXEBdCGXMxLZhtBTTXsbvOugBGzjrgTfo5Z7l0B7yCdkdQdIVoXvofyWvRGOuHEjmNcgLsx+Ztg7fA3mQcdOngEeH6D6aoAGp55rRtCK8xFx1HbNFvuEWG/jzcw2r5cbck2g4gr0Fso7/1QxQH0LOpypZ1IJBKJRCKRSCSmMVXbLIWw0NCpmn4TWYnuQ8uQVsN5K+E20cpch6g6dfsYfYi+ZT2rY8buoeIPoU/RKTRVUFlUpjVWzHYhYS3UX0BdLNbbZhS9iOZZ8UupHAIktBizFy1Bkx4ylxhtwehvrccZGt+7OwWUVojKL8Vor3+WuzH90PnEvTTCF96ZpbABqLwOR95F1ZtZHr2c3ka7kbb+9JtJm+jlqjJtRg+jov3vmC/RgzTCEe+sCQ2gXxVOoirOoF2o3hlIC5DXHLQTnUZVqA7PWdQMZadHOmUItrIL+BHtoIV1enFJIC9tu2uf/6C7UY7qoGO+XMoaQJnU2Q3Xk6//b1h7KM86vU51yDt2KIduswblHRnloWOkTajzXVjlgTZannVQHfJ+4HKUvQRlXkNbddEAtfgvSK1edqrcBPVUdeXrUNOZ5i60lWHjXRFVn0Edm76BnnA3ph+av6yj8v945ySgEfQ75zqUd+A4VdHvpzpwzxyMTxoS06dnMxr0h9ouUdmeQvp9tRalQyAPEtd41CdyPXoAaaLU9QqwCL1vNNF5H2mojtDdG713GjdADA2iGdl8pMXHNehWtABdidQwg+aht7Eqegr9in5CJ9BvaJQKtz3jTCQSiUQi8b+g1/sXRmYDomhz93gAAAAASUVORK5CYII="; std::string Sprites::Steam64 = "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"; + std::string Sprites::Meta64 = "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"; Sprite* CreateSpriteFromBase64(std::string& base64) { ArrayW bytes = System::Convert::FromBase64String(base64.c_str()); @@ -30,4 +31,8 @@ namespace MultiQuestensions { Sprite* Sprites::IconSteam64() { return CreateSpriteFromBase64(Steam64); } + + Sprite* Sprites::IconMeta64() { + return CreateSpriteFromBase64(Meta64); + } } \ No newline at end of file From 4e5e04b0800be4de71f319a1e8cda808ccec3c8c Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:41:12 +0200 Subject: [PATCH 12/56] Rename and refactor Components --- .../include/Environments/MQEAvatarNameTag.hpp | 46 ++++ .../Environments/MQEAvatarPlaceLighting.hpp | 31 +++ .../Environments/MQEAvatarPlaceLighting.cpp | 100 +++++++ .../src/Environments/MQEAvaterNameTag.cpp | 252 ++++++++++++++++++ 4 files changed, 429 insertions(+) create mode 100644 MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp create mode 100644 MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp create mode 100644 MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp create mode 100644 MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp diff --git a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp new file mode 100644 index 0000000..b01281e --- /dev/null +++ b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp @@ -0,0 +1,46 @@ +#pragma once +#include "custom-types/shared/macros.hpp" +// #include "Extensions/ExtendedPlayer.hpp" +#include "Players/MpexPlayerData.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" +#include "UnityEngine/MonoBehaviour.hpp" +#include "HMUI/ImageView.hpp" +#include "HMUI/CurvedTextMeshPro.hpp" +#include "GlobalNamespace/IConnectedPlayer.hpp" +#include "UnityEngine/Sprite.hpp" +#include + +DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarNameTag, UnityEngine::MonoBehaviour, + DECLARE_INSTANCE_FIELD(GlobalNamespace::IConnectedPlayer*, _playerInfo); + + DECLARE_INSTANCE_FIELD(HMUI::ImageView*, _bg); + DECLARE_INSTANCE_FIELD(HMUI::CurvedTextMeshPro*, _nameText); + + DECLARE_CTOR(New); + + DECLARE_INSTANCE_METHOD(void, Awake); + DECLARE_INSTANCE_METHOD(void, OnEnable); + DECLARE_INSTANCE_METHOD(void, OnDisable); + + DECLARE_INSTANCE_METHOD(void, SetPlayerInfo, GlobalNamespace::IConnectedPlayer* player); + // DECLARE_INSTANCE_METHOD(void, SetExtendedPlayerInfo, MultiQuestensions::Extensions::ExtendedPlayer* extendedPlayer); + DECLARE_INSTANCE_METHOD(void, SetPlatformData, MultiplayerCore::Players::MpPlayerData* data); + DECLARE_INSTANCE_METHOD(void, SetSimplePlayerInfo, GlobalNamespace::IConnectedPlayer* simplePlayer); + DECLARE_INSTANCE_METHOD(void, HandlePlatformData, GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data); + DECLARE_INSTANCE_METHOD(void, HandleMpexData, GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpexPlayerData* data); + + enum PlayerIconSlot { + Platform = 0 + }; + + bool _enabled; + + MultiplayerCore::event_handler _platformDataEventHandler; + MultiplayerCore::event_handler _mpexPlayerDataEventHandler; + + std::map _playerIcons; + + void SetIcon(PlayerIconSlot slot, UnityEngine::Sprite* sprite); + void RemoveIcon(PlayerIconSlot slot); +) \ No newline at end of file diff --git a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp new file mode 100644 index 0000000..244c900 --- /dev/null +++ b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "custom-types/shared/macros.hpp" +#include "UnityEngine/MonoBehaviour.hpp" +#include "GlobalNamespace/TubeBloomPrePassLight.hpp" +#include "UnityEngine/Color.hpp" + +#include "Players/MpexPlayerManager.hpp" + +#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" +#include "MultiplayerCore/shared/Utils/event.hpp" + +DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarPlaceLighting, UnityEngine::MonoBehaviour, + std::vector lights; + DECLARE_INSTANCE_FIELD(float, smoothTime); + DECLARE_INSTANCE_FIELD_DEFAULT(UnityEngine::Color, targetColor, UnityEngine::Color::get_black()); + DECLARE_INSTANCE_FIELD_DEFAULT(UnityEngine::Color, TargetColor, targetColor); + + DECLARE_CTOR(New); + + // DECLARE_INSTANCE_METHOD(void, Awake); + DECLARE_INSTANCE_METHOD(void, OnEnable); + DECLARE_INSTANCE_METHOD(void, OnDisable); + DECLARE_INSTANCE_METHOD(void, Update); + DECLARE_INSTANCE_METHOD(UnityEngine::Color, GetColor); + DECLARE_INSTANCE_METHOD(bool, IsColorVeryCloseToColor, UnityEngine::Color color0, UnityEngine::Color color1); + +public: + void SetColor(const UnityEngine::Color& color, bool immediate); +private: + void SetColor(const UnityEngine::Color& color); +) \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp new file mode 100644 index 0000000..5510e8f --- /dev/null +++ b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp @@ -0,0 +1,100 @@ +#include "main.hpp" +#include "Environments/MQEAvatarPlaceLighting.hpp" +#include "UnityEngine/Time.hpp" +#include "Config.hpp" +using namespace GlobalNamespace; +using namespace UnityEngine; + +DEFINE_TYPE(MultiQuestensions::Environments, MQEAvatarPlaceLighting); + +namespace MultiQuestensions::Environments { + + void MQEAvatarPlaceLighting::New() { + smoothTime = 2.0f; + // if (targetColor != UnityEngine::Color::get_black()) + targetColor = UnityEngine::Color::get_black(); + } + + // void MQEAvatarPlaceLighting::Awake() { + // // auto lightsArr = this->GetComponentsInChildren(); + // // for (int i = 0; i < lightsArr.Length(); i++) { + // // this->lights.emplace_back(lightsArr.get(i)); + // // } + + // // if (_sessionManager == nullptr || _sessionManager->get_localPlayer() == nullptr) + // // return; + + // // if (_sessionManager->get_localPlayer()->get_sortIndex() == SortIndex) { + // // this->SetColor(config.PlayerColor, true); + // // return; + // // } + + // // for (int i = 0; i < _sessionManager->dyn__connectedPlayers()->get_Count(); i++) { + // // if (_sessionManager->dyn__connectedPlayers()->get_Item(i)->get_sortIndex() == SortIndex) { + // // auto player = _sessionManager->dyn__connectedPlayers()->get_Item(i); + // // auto mpexPlayerData = MpexPlayerManager::GetPlayer(player->get_playerId()); + // // this->SetColor(mpexPlayerData ? mpexPlayerData->get_color() : Config::DefaultPlayerColor, true); + // // return; + // // } + // // } + // } + + void MQEAvatarPlaceLighting::OnEnable() { + auto lightsArr = this->GetComponentsInChildren(); + for (int i = 0; i < lightsArr.Length(); i++) { + this->lights.emplace_back(lightsArr.get(i)); + } + } + + void MQEAvatarPlaceLighting::OnDisable() { + lights.clear(); + } + + inline static Color Lerp(Color const& a, Color const& b, float const& t) + { + float t_clamp = std::clamp(t, 0.0f, 1.0f); + return Color(a.r + (b.r - a.r) * t_clamp, a.g + (b.g - a.g) * t_clamp, a.b + (b.b - a.b) * t_clamp, a.a + (b.a - a.a) * t_clamp); + } + + void MQEAvatarPlaceLighting::Update() { + Color current = GetColor(); + + if (current == targetColor) + return; + + // SetColor(targetColor); + + if (IsColorVeryCloseToColor(current, targetColor)) + SetColor(targetColor); + else + //SetColor(Color::Lerp(current, targetColor, Time::get_deltaTime() * smoothTime)); + SetColor(Lerp(current, targetColor, Time::get_deltaTime() * smoothTime)); + } + + void MQEAvatarPlaceLighting::SetColor(const Color& color, bool immediate) { + targetColor = color; + + if (immediate) + { + SetColor(color); + } + } + + Color MQEAvatarPlaceLighting::GetColor() { + if (lights.size() > 0) + return lights[0]->get_color(); + return Color::get_black(); + } + + bool MQEAvatarPlaceLighting::IsColorVeryCloseToColor(Color color0, Color color1) + { + return (fabs(color0.r - color1.r) < 0.002f && fabs(color0.g - color1.g) < 0.002f && fabs(color0.b - color1.b) < 0.002f && fabs(color0.a - color1.a) < 0.002f); + } + + void MQEAvatarPlaceLighting::SetColor(const Color& color) { + for (TubeBloomPrePassLight* light : lights) { + light->set_color(color); + light->Refresh(); + } + } +} \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp new file mode 100644 index 0000000..30ba356 --- /dev/null +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -0,0 +1,252 @@ +#include "main.hpp" +#include "Environments/MQEAvatarNameTag.hpp" +#include "Assets/Sprites.hpp" +#include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" +#include "UnityEngine/CanvasRenderer.hpp" +#include "UnityEngine/RectTransform.hpp" +#include "UnityEngine/UI/HorizontalLayoutGroup.hpp" +#include "GlobalNamespace/ConnectedPlayerName.hpp" +#include "UnityEngine/Object.hpp" +#include "Players/MpexPlayerManager.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" +using namespace GlobalNamespace; +using namespace UnityEngine::UI; +using namespace UnityEngine; +using namespace HMUI; + +DEFINE_TYPE(MultiQuestensions::Environments, MQEAvatarNameTag); + +namespace MultiQuestensions::Environments { + static StringW BG() { + static ConstString bg("BG"); + return bg; + } + + static StringW Name() { + static ConstString name("Name"); + return name; + } + + static StringW Player() { + static ConstString player("Player"); + return player; + } + + + void MQEAvatarNameTag::New() { + _enabled = false; + _playerInfo = nullptr; + _playerIcons.clear(); + } + + void MQEAvatarNameTag::Awake() { + // Get references + _bg = get_transform()->Find(BG())->GetComponent(); + _nameText = get_transform()->Find(Name())->GetComponent(); + + // Add horizontal layout to bg + HorizontalLayoutGroup* _; + if (!_bg->TryGetComponent(ByRef(_))) + { + auto hLayout = _bg->get_gameObject()->AddComponent(); + hLayout->set_childAlignment(TextAnchor::MiddleCenter); + hLayout->set_childForceExpandWidth(false); + hLayout->set_childForceExpandHeight(false); + hLayout->set_childScaleWidth(false); + hLayout->set_childScaleHeight(false); + hLayout->set_spacing(4); + } + + // Re-nest name onto bg + _nameText->get_transform()->SetParent(_bg->get_transform(), false); + + // Take control of name tag + ConnectedPlayerName* nativeNameScript; + if (_nameText->TryGetComponent(ByRef(nativeNameScript))) + Object::Destroy(nativeNameScript); + _nameText->set_text(Player()); + + // Create Event handlers + _platformDataEventHandler = MultiplayerCore::event_handler( + [this](GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data) { + if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) + SetPlatformData(data); + }); + _mpexPlayerDataEventHandler = MultiplayerCore::event_handler( + [this](GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpexPlayerData* data) { + if (_nameText && data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) + _nameText->set_color(data->Color); + }); + } + + void MQEAvatarNameTag::OnEnable() + { + _enabled = true; + + // Subscribe to events + MultiplayerCore::Players::MpPlayerManager::PlayerConnected += _platformDataEventHandler; + MultiQuestensions::Players::MpexPlayerManager::PlayerConnected += _mpexPlayerDataEventHandler; + + // Set player info + if (_playerInfo != nullptr) + SetPlayerInfo(_playerInfo); + } + + void MQEAvatarNameTag::OnDisable() + { + _enabled = false; + + // Unsubscribe from events + MultiplayerCore::Players::MpPlayerManager::PlayerConnected -= _platformDataEventHandler; + MultiQuestensions::Players::MpexPlayerManager::PlayerConnected -= _mpexPlayerDataEventHandler; + } + + #pragma region Set Player Info + void MQEAvatarNameTag::SetPlayerInfo(IConnectedPlayer* player) + { + _playerInfo = player; + + if (!_enabled) + return; + + _nameText->set_text(player->get_userName()); + std::string userName = static_cast(player->get_userName()); + if (_mpexPlayerData.contains(userName)) + _nameText->set_color(_mpexPlayerData.at(userName)->Color); + + RemoveIcon(PlayerIconSlot::Platform); + + MultiplayerCore::Players::MpPlayerData* data; + std::string userId = static_cast(player->get_userId()); + if (MultiplayerCore::Players::MpPlayerManager::TryGetPlayer(userId, data)) + SetPlatformData(data); + // if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) + // SetExtendedPlayerInfo(reinterpret_cast(player)); + // else + // SetSimplePlayerInfo(player); + } + + void MQEAvatarNameTag::SetPlatformData(MultiplayerCore::Players::MpPlayerData* data) { + using MultiplayerCore::Players::Platform; + switch (data->platform) + { + case Platform::Steam: + SetIcon(PlayerIconSlot::Platform, Sprites::IconSteam64()); + break; + case Platform::OculusQuest: + SetIcon(PlayerIconSlot::Platform, Sprites::IconMeta64()); + break; + case Platform::OculusPC: + SetIcon(PlayerIconSlot::Platform, Sprites::IconOculus64()); + break; + case Platform::Unknown: + case Platform::PS4: + default: + break; + } + } + + // void LobbyAvatarNameTag::SetExtendedPlayerInfo(ExtendedPlayer* extendedPlayer) + // { + // _playerInfo = reinterpret_cast(extendedPlayer); + + // if (!_enabled) + // return; + + // _nameText->set_text(extendedPlayer->get_userName()); + // _nameText->set_color(extendedPlayer->get_playerColor()); + + // //getLogger().debug("SetExtendedPlayerInfo platform: %d", (int)extendedPlayer->get_platform()); + + // switch (extendedPlayer->get_platform()) + // { + // case Extensions::Platform::Steam: + // SetIcon(PlayerIconSlot::Platform, Sprites::IconSteam64()); + // break; + // case Extensions::Platform::OculusQuest: + // case Extensions::Platform::OculusPC: + // SetIcon(PlayerIconSlot::Platform, Sprites::IconOculus64()); + // break; + // default: + // RemoveIcon(PlayerIconSlot::Platform); + // break; + // } + // } + + void MQEAvatarNameTag::SetSimplePlayerInfo(IConnectedPlayer* simplePlayer) + { + _playerInfo = simplePlayer; + + if (!_enabled) + return; + + _nameText->set_text(simplePlayer->get_userName()); + _nameText->set_color(Color::get_white()); + + RemoveIcon(PlayerIconSlot::Platform); + } + + using MultiplayerCore::Players::MpPlayerData; + void MQEAvatarNameTag::HandlePlatformData(IConnectedPlayer* player, MpPlayerData* data) { + if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) + SetPlatformData(data); + } + + using MultiQuestensions::Players::MpexPlayerData; + void MQEAvatarNameTag::HandleMpexData(IConnectedPlayer* player, MpexPlayerData* data) { + if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) + _nameText->set_color(data->Color); + } + #pragma endregion + + #pragma region Set Icons + void MQEAvatarNameTag::SetIcon(PlayerIconSlot slot, Sprite* sprite) + { + getLogger().debug("SetIcon Sprite %p", sprite); + + if (!_enabled) + return; + + HMUI::ImageView* imageView; + if (!_playerIcons.contains(slot)) + { + //getLogger().debug("SetIcon, create new Icon"); + auto iconObj = GameObject::New_ctor(string_format("MQEPlayerIcon(%d)", (int)slot).c_str()); + iconObj->get_transform()->SetParent(_bg->get_transform(), false); + iconObj->get_transform()->SetSiblingIndex((int)slot); + iconObj->set_layer(5); + + iconObj->AddComponent(); + + imageView = iconObj->AddComponent(); + imageView->set_maskable(true); + imageView->set_fillCenter(true); + imageView->set_preserveAspect(true); + imageView->set_material(_bg->get_material()); // No Glow Billboard material + _playerIcons.insert_or_assign(slot, imageView); + + auto rectTransform = iconObj->GetComponent(); + rectTransform->set_localScale({ 3.2f, 3.2f, 0.0f }); + } + else imageView = _playerIcons.at(slot); + + imageView->set_sprite(sprite); + + _nameText->get_transform()->SetSiblingIndex(999); + } + + void MQEAvatarNameTag::RemoveIcon(PlayerIconSlot slot) + { + //getLogger().debug("RemoveIcon"); + + if (!_enabled) + return; + if (_playerIcons.contains(slot)) + { + HMUI::ImageView* imageView = _playerIcons[slot]; + GameObject::Destroy(imageView->get_gameObject()); + _playerIcons.erase(slot); + } + } + #pragma endregion +} \ No newline at end of file From 541c9710a92395ae313ad40727d79b0557bbcf40 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:41:32 +0200 Subject: [PATCH 13/56] Add MpexPlayerData and MpexPlayerManager --- .../shared/Players/MpexPlayerData.hpp | 22 ++++++++++++++++++ .../shared/Players/MpexPlayerManager.hpp | 12 ++++++++++ .../src/Players/MpexPlayerData.cpp | 23 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 MultiQuestensions/shared/Players/MpexPlayerData.hpp create mode 100644 MultiQuestensions/shared/Players/MpexPlayerManager.hpp create mode 100644 MultiQuestensions/src/Players/MpexPlayerData.cpp diff --git a/MultiQuestensions/shared/Players/MpexPlayerData.hpp b/MultiQuestensions/shared/Players/MpexPlayerData.hpp new file mode 100644 index 0000000..fa0afad --- /dev/null +++ b/MultiQuestensions/shared/Players/MpexPlayerData.hpp @@ -0,0 +1,22 @@ +#pragma once +#include "custom-types/shared/macros.hpp" +#include "GlobalNamespace/IConnectedPlayer.hpp" +#include "MultiplayerCore/shared/Networking/Abstractions/MpPacket.hpp" +#include "UnityEngine/Color.hpp" + +DECLARE_CLASS_CUSTOM_DLL(MultiQuestensions::Players, MpexPlayerData, MultiplayerCore::Networking::Abstractions::MpPacket, "MultiplayerExtensions.Players", + + DECLARE_DEFAULT_CTOR(); + + /// + /// Player's color set in the mod config. + /// + DECLARE_INSTANCE_FIELD(UnityEngine::Color, Color); + + DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); + DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Deserialize", 1), LiteNetLib::Utils::NetDataReader* reader); + + public: + operator LiteNetLib::Utils::INetSerializable*() { return reinterpret_cast(this); } + LiteNetLib::Utils::INetSerializable* ToSerializable() { return reinterpret_cast(this); } +) \ No newline at end of file diff --git a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp new file mode 100644 index 0000000..b94a592 --- /dev/null +++ b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "MpexPlayerData.hpp" +#include "MultiplayerCore/shared/Utils/event.hpp" + +namespace MultiQuestensions::Players { + class MpexPlayerManager { + public: + static MultiplayerCore::event PlayerConnected; + static bool TryGetPlayer(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player); + static MpexPlayerData* GetPlayer(std::string playerId); + }; +} \ No newline at end of file diff --git a/MultiQuestensions/src/Players/MpexPlayerData.cpp b/MultiQuestensions/src/Players/MpexPlayerData.cpp new file mode 100644 index 0000000..a60762a --- /dev/null +++ b/MultiQuestensions/src/Players/MpexPlayerData.cpp @@ -0,0 +1,23 @@ +#include "CodegenExtensions/ColorUtility.hpp" +#include "Players/MpexPlayerData.hpp" +#include "Config.hpp" +using namespace UnityEngine; +using namespace LiteNetLib::Utils; + +DEFINE_TYPE(MultiQuestensions::Players, MpexPlayerData) + +namespace MultiQuestensions::Players +{ + void MpexPlayerData::Serialize(NetDataWriter* writer) + { + writer->Put(ColorUtility::ToHtmlStringRGB(Color)); + } + + void MpexPlayerData::Deserialize(NetDataReader* reader) + { + UnityEngine::Color color; + if (!ColorUtility::TryParseHtmlString(reader->GetString(), color)) + color = Config::DefaultPlayerColor; + Color = color; + } +} From 43e4e830104d0acbd550d2898b0de48074d3a079 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:42:32 +0200 Subject: [PATCH 14/56] Refactor Hooks --- .../Hooks/EnvironmentAndAvatarHooks.hpp | 3 +- MultiQuestensions/include/Hooks/Hooks.hpp | 29 --- .../SessionManagerAndExtendedPlayerHooks.hpp | 8 +- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 215 +++++++++--------- .../src/Hooks/InstallerHooks.cpp | 13 +- .../SessionManagerAndMpexPlayerHooks.cpp | 206 +++++++++++++++++ 6 files changed, 328 insertions(+), 146 deletions(-) create mode 100644 MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp diff --git a/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp b/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp index bedd418..ac3bcf7 100644 --- a/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp +++ b/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp @@ -4,5 +4,6 @@ namespace MultiQuestensions { extern void SetPlayerPlaceColor(GlobalNamespace::IConnectedPlayer* player, const UnityEngine::Color& color, bool priority); - extern void CreateOrUpdateNameTag(GlobalNamespace::IConnectedPlayer* player); + // extern void CreateOrUpdateNameTag(GlobalNamespace::IConnectedPlayer* player); + // extern void SetPlatformData(MultiplayerCore::Players::MpPlayerData* data); } \ No newline at end of file diff --git a/MultiQuestensions/include/Hooks/Hooks.hpp b/MultiQuestensions/include/Hooks/Hooks.hpp index 7f2dda2..c975ecf 100644 --- a/MultiQuestensions/include/Hooks/Hooks.hpp +++ b/MultiQuestensions/include/Hooks/Hooks.hpp @@ -47,47 +47,18 @@ #include "questui/shared/CustomTypes/Components/MainThreadScheduler.hpp" -#include "songdownloader/shared/BeatSaverAPI.hpp" - -#include "songloader/shared/API.hpp" - namespace MultiQuestensions { - constexpr bool IsCustomLevel(const std::string& levelId) { - return levelId.starts_with(RuntimeSongLoader::API::GetCustomLevelsPrefix()); - } - - extern bool HasSong(const std::string& levelId); - - extern StringW getModdedStateStr(); - extern StringW getMEStateStr(); - extern StringW getNEStateStr(); - extern StringW getChromaStateStr(); - extern GlobalNamespace::LobbyGameStateController* lobbyGameStateController; - extern std::map> entitlementDictionary; - - extern GlobalNamespace::IPreviewBeatmapLevel* loadingPreviewBeatmapLevel; - extern GlobalNamespace::BeatmapDifficulty loadingBeatmapDifficulty; - extern GlobalNamespace::BeatmapCharacteristicSO* loadingBeatmapCharacteristic; - extern GlobalNamespace::IDifficultyBeatmap* loadingDifficultyBeatmap; - extern GlobalNamespace::GameplayModifiers* loadingGameplayModifiers; - class Hooks { - static void NetworkplayerEntitlementChecker(); - static void MaxPlayerHooks(); static void EnvironmentHooks(); - static void QuickplayHooks(); static void SessionManagerAndExtendedPlayerHooks(); static void InstallerHooks(); public: static const void Install_Hooks() { - NetworkplayerEntitlementChecker(); - MaxPlayerHooks(); EnvironmentHooks(); - QuickplayHooks(); SessionManagerAndExtendedPlayerHooks(); InstallerHooks(); } diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index f9f3de0..9cc593e 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -1,7 +1,5 @@ #pragma once -#include "Extensions/ExtendedPlayer.hpp" +#include "Players/MpexPlayerData.hpp" -extern SafePtr localExtendedPlayer; -extern std::map> _extendedPlayers; - -static void HandlePreviewBeatmapPacket(MultiQuestensions::Beatmaps::PreviewBeatmapPacket* packet, GlobalNamespace::IConnectedPlayer* player); \ No newline at end of file +extern SafePtr localMpexPlayerData; +extern std::map> _mpexPlayerData; \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index c411a08..deaccce 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -3,8 +3,9 @@ #include "GlobalFields.hpp" #include "Hooks/EnvironmentAndAvatarHooks.hpp" #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" -#include "Environments/LobbyAvatarPlaceLighting.hpp" -#include "Environments/LobbyAvatarNameTag.hpp" +#include "Environments/MQEAvatarPlaceLighting.hpp" +#include "Environments/MQEAvatarNameTag.hpp" +#include "Config.hpp" #include "GlobalNamespace/MultiplayerLobbyController.hpp" #include "GlobalNamespace/LightWithIdMonoBehaviour.hpp" @@ -19,17 +20,19 @@ #include "GlobalNamespace/MultiplayerLobbyAvatarManager.hpp" #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/ConnectedPlayerManager_ConnectedPlayer.hpp" -#include "GlobalNamespace/AvatarPoseRestrictions.hpp" +// #include "GlobalNamespace/AvatarPoseRestrictions.hpp" +#include "GlobalNamespace/GameplayServerConfiguration.hpp" #include "System/Collections/Generic/List_1.hpp" #include "UnityEngine/Resources.hpp" #include "UnityEngine/Transform.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" + using namespace GlobalNamespace; using namespace UnityEngine; using namespace MultiQuestensions::Environments; -using namespace MultiQuestensions::Extensions; using namespace System::Collections::Generic; namespace MultiQuestensions { @@ -40,7 +43,7 @@ namespace MultiQuestensions { MultiplayerLobbyAvatarPlaceManager* _placeManager; MultiplayerLobbyCenterStageManager* _stageManager; - std::vector avatarPlaces; + std::vector avatarPlaces; float innerCircleRadius; float minOuterCircleRadius; @@ -55,7 +58,7 @@ namespace MultiQuestensions { #pragma endregion #pragma region LobbyAvatarPlaceLigting - LobbyAvatarPlaceLighting* GetConnectedPlayerPlace(IConnectedPlayer* player) + MQEAvatarPlaceLighting* GetConnectedPlayerPlace(IConnectedPlayer* player) { //getLogger().debug("GetConnectedPlayerPlace"); int sortIndex = _lobbyStateDataModel->get_localPlayer()->get_sortIndex(); @@ -76,38 +79,38 @@ namespace MultiQuestensions { { if (!initialized) return; - //if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) - // getLogger().debug("SetPlayerPlaceColor ExtendedPlayer"); - - //else if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) getLogger().debug("CreateOrUpdateNameTag SimplePlayer"); - //else { - // getLogger().debug("SetPlayerPlaceColor unknown type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - // return; - //} - if (!(il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass) || il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass))) { - getLogger().error("SetPlayerPlaceColor unknown type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - return; - } - - //getLogger().debug("SetPlayerPlaceColor player type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - //getLogger().debug("SetPlayerPlaceColor"); - LobbyAvatarPlaceLighting* place = GetConnectedPlayerPlace(player); + MQEAvatarPlaceLighting* place = GetConnectedPlayerPlace(player); if (place == nullptr) return; - if (!priority && place->TargetColor != Color::get_black() && place->TargetColor != ExtendedPlayer::DefaultColor) + getLogger().debug("SetPlayerPlaceColor player %s userId %s", static_cast(player->get_userName()).c_str(), static_cast(player->get_userId()).c_str()); + + getLogger().debug("SetPlayerPlaceColor new TargetColor %f, %f, %f, %f", color.r, color.g, color.b, color.a); + + getLogger().debug("SetPlayerPlaceColor current TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); + + if (!priority && place->targetColor != Color::get_black() && place->targetColor != Config::DefaultPlayerColor) { + getLogger().debug("SetPlayerPlaceColor not priority and TargetColor check is priority '%s' check is black '%s', check is DefaultPlayerColor '%s' check full eval '%s'", !priority ? "true" : "false", place->targetColor != Color::get_black() ? "true" : "false", place->targetColor != Config::DefaultPlayerColor ? "true" : "false", (!priority && place->targetColor != Color::get_black() && place->targetColor != Config::DefaultPlayerColor) ? "true" : "false"); + + getLogger().debug("SetPlayerPlaceColor TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); + + getLogger().debug("SetPlayerPlaceColor black %f, %f, %f, %f", Color::get_black().r, Color::get_black().g, Color::get_black().b, Color::get_black().a); + + getLogger().debug("SetPlayerPlaceColor DefaultPlayerColor %f, %f, %f, %f", Config::DefaultPlayerColor.r, Config::DefaultPlayerColor.g, Config::DefaultPlayerColor.b, Config::DefaultPlayerColor.a); // Priority colors are always set; non-priority colors can only override default black/blue return; + } + getLogger().debug("SetPlayerPlaceColor setting color"); place->SetColor(color, false); } void SetAllPlayerPlaceColors(Color color, bool immediate = false) { - for (LobbyAvatarPlaceLighting* place : avatarPlaces) + for (MQEAvatarPlaceLighting* place : avatarPlaces) { place->SetColor(color, immediate); } @@ -116,16 +119,26 @@ namespace MultiQuestensions { static void SetDefaultPlayerPlaceColors() { SetAllPlayerPlaceColors(Color::get_black(), true); - SetPlayerPlaceColor(sessionManager->get_localPlayer(), localExtendedPlayer->get_playerColor(), true); + getLogger().debug("SetDefaultPlayerPlaceColors set local player color"); + SetPlayerPlaceColor(sessionManager->get_localPlayer(), config.PlayerColor, true); using System::Collections::Generic::List_1; for (int i = 0; i < reinterpret_cast*>(sessionManager->get_connectedPlayers())->get_Count(); i++) { auto player = sessionManager->get_connectedPlayers()->get_Item(i); - SetPlayerPlaceColor(player, ExtendedPlayer::DefaultColor, false); + std::string userId = player->get_userId(); + if (userId == static_cast(sessionManager->get_localPlayer()->get_userId())) continue; + getLogger().debug("SetDefaultPlayerPlaceColors set player color for userId %s", userId.c_str()); + if (_mpexPlayerData.contains(userId)) { + getLogger().debug("SetDefaultPlayerPlaceColors found MpexPlayerData setting color for player %s", userId.c_str()); + SetPlayerPlaceColor(player, _mpexPlayerData.at(userId)->Color, true); + } else { + getLogger().debug("SetDefaultPlayerPlaceColors did not find MpexPlayerData setting default color for player %s", userId.c_str()); + SetPlayerPlaceColor(player, Config::DefaultPlayerColor, true); + } } - for (auto& [key, extendedPlayer] : _extendedPlayers) { - SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); - } + // for (auto& [key, extendedPlayer] : _mpexPlayerData) { + // SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); + // } } void HandleLobbyEnvironmentLoaded() { @@ -136,33 +149,18 @@ namespace MultiQuestensions { { auto nativeAvatarPlace = nativeAvatarPlaces[i]; - auto avatarPlace = nativeAvatarPlace->GetComponent(); + auto avatarPlace = nativeAvatarPlace->GetComponent(); if (avatarPlace == nullptr) - avatarPlace = nativeAvatarPlace->get_gameObject()->AddComponent(); + avatarPlace = nativeAvatarPlace->get_gameObject()->AddComponent(); avatarPlaces.push_back(avatarPlace); } innerCircleRadius = _placeManager->dyn__innerCircleRadius(); minOuterCircleRadius = _placeManager->dyn__minOuterCircleRadius(); - //getLogger().debug("innerCircleRadius %f, minOuterCircleRadius %f", innerCircleRadius, minOuterCircleRadius); - angleBetweenPlayersWithEvenAdjustment = MultiplayerPlayerPlacement::GetAngleBetweenPlayersWithEvenAdjustment(_lobbyStateDataModel->get_maxPartySize(), MultiplayerPlayerLayout::Circle); - outerCircleRadius = fmax(MultiplayerPlayerPlacement::GetOuterCircleRadius(angleBetweenPlayersWithEvenAdjustment, innerCircleRadius), minOuterCircleRadius); - //getLogger().debug("angleBetweenPlayersWithEvenAdjustment %f, outerCircleRadius %f", angleBetweenPlayersWithEvenAdjustment, outerCircleRadius); - - bool buildingsEnabled = (sessionManager->dyn__maxPlayerCount() <= 18); - auto* Construction_tr = _menuEnvironmentManager->get_transform()->Find(il2cpp_utils::newcsstr("Construction")); - if (Construction_tr && Construction_tr->get_gameObject()) { - Construction_tr->get_gameObject()->SetActive(buildingsEnabled); - } - auto* Construction_1_tr = _menuEnvironmentManager->get_transform()->Find(il2cpp_utils::newcsstr("Construction (1)")); - if (Construction_1_tr && Construction_1_tr->get_gameObject()) { - Construction_1_tr->get_gameObject()->SetActive(buildingsEnabled); - } - - float centerScreenScale = outerCircleRadius / minOuterCircleRadius; - _stageManager->get_transform()->set_localScale({ centerScreenScale, centerScreenScale, centerScreenScale }); + angleBetweenPlayersWithEvenAdjustment = MultiplayerPlayerPlacement::GetAngleBetweenPlayersWithEvenAdjustment(_lobbyStateDataModel->get_configuration().maxPlayerCount, MultiplayerPlayerLayout::Circle); + outerCircleRadius = fmax(MultiplayerPlayerPlacement::GetOuterCircleRadius(angleBetweenPlayersWithEvenAdjustment, innerCircleRadius), minOuterCircleRadius); initialized = true; SetDefaultPlayerPlaceColors(); @@ -170,23 +168,20 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(MultiplayerLobbyController_ActivateMultiplayerLobby, &MultiplayerLobbyController::ActivateMultiplayerLobby, void, MultiplayerLobbyController* self) { - if (!_placeManager) _placeManager = Resources::FindObjectsOfTypeAll()[0]; - if (!_menuEnvironmentManager) _menuEnvironmentManager = Resources::FindObjectsOfTypeAll()[0]; - if (!_stageManager) _stageManager = Resources::FindObjectsOfTypeAll()[0]; - if (!_lobbyStateDataModel) _lobbyStateDataModel = _placeManager->dyn__lobbyStateDataModel(); + _placeManager = Resources::FindObjectsOfTypeAll()[0]; + _menuEnvironmentManager = Resources::FindObjectsOfTypeAll()[0]; + _stageManager = Resources::FindObjectsOfTypeAll()[0]; + _lobbyStateDataModel = _placeManager->dyn__lobbyStateDataModel(); - self->dyn__innerCircleRadius() = 1; - self->dyn__minOuterCircleRadius() = 4.4f; MultiplayerLobbyController_ActivateMultiplayerLobby(self); HandleLobbyEnvironmentLoaded(); } MAKE_HOOK_MATCH(LightWithIdMonoBehaviour_RegisterLight, &LightWithIdMonoBehaviour::RegisterLight, void, LightWithIdMonoBehaviour* self) { - if (!(self->get_transform()->get_parent() != nullptr && self->get_transform()->get_parent()->get_name()->Contains(il2cpp_utils::newcsstr("LobbyAvatarPlace")))) + if (!(self && self->get_transform() && self->get_transform()->get_parent() && self->get_transform()->get_parent()->get_name()->Contains("LobbyAvatarPlace"))) LightWithIdMonoBehaviour_RegisterLight(self); } - #pragma endregion #pragma region LobbyAvatarNameTag @@ -201,7 +196,7 @@ namespace MultiQuestensions { if (_refPlayerIdToAvatarMap != nullptr) { MultiplayerLobbyAvatarController* value; //getLogger().debug("Start GetAvatarController return MultiplayerLobbyAvatarController"); - return _refPlayerIdToAvatarMap->TryGetValue(userId, ByRef(value)) ? value : nullptr; + return _refPlayerIdToAvatarMap->TryGetValue(userId, byref(value)) ? value : nullptr; } //getLogger().debug("GetAvatarController return nullptr, this part should never be triggered"); @@ -216,64 +211,76 @@ namespace MultiQuestensions { else return nullptr; } - void CreateOrUpdateNameTag(IConnectedPlayer* player) - { - try { - //getLogger().debug("Start CreateOrUpdateNameTag: GetAvatarCaptionObject"); - //Il2CppString* userId; - //if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) - // getLogger().debug("CreateOrUpdateNameTag ExtendedPlayer"); - - //else if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) getLogger().debug("CreateOrUpdateNameTag SimplePlayer"); - //else { - // getLogger().debug("CreateOrUpdateNameTag unknown type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - // return; - //} - //getLogger().debug("CreateOrUpdateNameTag player type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - - if (!(il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass) || il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass))) { - getLogger().error("REPORT TO ENDER: CreateOrUpdateNameTag unknown type: %s, this shouldn't happen!!!", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - return; - } - - auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()/*userId*/); - if (objAvatarCaption == nullptr) - return; + // void CreateOrUpdateNameTag(IConnectedPlayer* player) + // { + // try { + // //getLogger().debug("Start CreateOrUpdateNameTag: GetAvatarCaptionObject"); + // //Il2CppString* userId; + // //if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) + // // getLogger().debug("CreateOrUpdateNameTag ExtendedPlayer"); + + // //else if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) getLogger().debug("CreateOrUpdateNameTag SimplePlayer"); + // //else { + // // getLogger().debug("CreateOrUpdateNameTag unknown type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); + // // return; + // //} + // //getLogger().debug("CreateOrUpdateNameTag player type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); + + // // if (!(il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass) || il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass))) { + // // getLogger().error("REPORT TO ENDER: CreateOrUpdateNameTag unknown type: %s, this shouldn't happen!!!", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); + // // return; + // // } + + // auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()/*userId*/); + // if (objAvatarCaption == nullptr) + // return; + + // //getLogger().debug("Found GetAvatarCaptionObject"); + // LobbyAvatarNameTag* nameTag; + // if (!objAvatarCaption->TryGetComponent(byref(nameTag))) { + // //getLogger().debug("Adding new LobbyAvatarNameTag Component"); + // nameTag = objAvatarCaption->AddComponent(); + // } + + // //getLogger().debug("SetPlayerInfo"); + // nameTag->SetPlayerInfo(player); + // } + // catch (const std::runtime_error& e) { + // getLogger().error("REPORT TO ENDER: CreateOrUpdateNameTag Failed: %s", e.what()); + // } + // } - //getLogger().debug("Found GetAvatarCaptionObject"); - LobbyAvatarNameTag* nameTag; - if (!objAvatarCaption->TryGetComponent(ByRef(nameTag))) { - //getLogger().debug("Adding new LobbyAvatarNameTag Component"); - nameTag = objAvatarCaption->AddComponent(); - } + void HandleLobbyAvatarCreated(IConnectedPlayer* player) { + auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()); + if (objAvatarCaption == nullptr) + return; - //getLogger().debug("SetPlayerInfo"); - nameTag->SetPlayerInfo(player); - } - catch (const std::runtime_error& e) { - getLogger().error("REPORT TO ENDER: CreateOrUpdateNameTag Failed: %s", e.what()); + //getLogger().debug("Found GetAvatarCaptionObject"); + MQEAvatarNameTag* nameTag; + if (!objAvatarCaption->TryGetComponent(byref(nameTag))) { + //getLogger().debug("Adding new LobbyAvatarNameTag Component"); + nameTag = objAvatarCaption->AddComponent(); } - } + nameTag->_playerInfo = player; - void HandleLobbyAvatarCreated(IConnectedPlayer* player) { //const std::string userId = player->get_userId(); - if (_extendedPlayers.contains(player->get_userId())) - player = reinterpret_cast(_extendedPlayers.at(player->get_userId())->get_self()); - CreateOrUpdateNameTag(player); + // if (_extendedPlayers.contains(player->get_userId())) + // player = reinterpret_cast(_extendedPlayers.at(player->get_userId())->get_self()); + // CreateOrUpdateNameTag(player); } MAKE_HOOK_MATCH(MultiplayerLobbyAvatarManager_AddPlayer, &MultiplayerLobbyAvatarManager::AddPlayer, void, MultiplayerLobbyAvatarManager* self, IConnectedPlayer* connectedPlayer) { MultiplayerLobbyAvatarManager_AddPlayer(self, connectedPlayer); - if (!_avatarManager) _avatarManager = self; + _avatarManager = self; HandleLobbyAvatarCreated(connectedPlayer); } - MAKE_HOOK_MATCH(AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet, &AvatarPoseRestrictions::HandleAvatarPoseControllerPositionsWillBeSet, void, AvatarPoseRestrictions* self, Quaternion headRotation, Vector3 headPosition, Vector3 leftHandPosition, Vector3 rightHandPosition, ByRef newHeadPosition, ByRef newLeftHandPosition, ByRef newRightHandPosition) { - newHeadPosition.heldRef = headPosition; - newLeftHandPosition.heldRef = self->LimitHandPositionRelativeToHead(leftHandPosition, headPosition); - newRightHandPosition.heldRef = self->LimitHandPositionRelativeToHead(rightHandPosition, headPosition); - //AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet(self, headRotation, headPosition, leftHandPosition, rightHandPosition, newHeadPosition, newLeftHandPosition, newRightHandPosition); - } + // MAKE_HOOK_MATCH(AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet, &AvatarPoseRestrictions::HandleAvatarPoseControllerPositionsWillBeSet, void, AvatarPoseRestrictions* self, Quaternion headRotation, Vector3 headPosition, Vector3 leftHandPosition, Vector3 rightHandPosition, ByRef newHeadPosition, ByRef newLeftHandPosition, ByRef newRightHandPosition) { + // newHeadPosition.heldRef = headPosition; + // newLeftHandPosition.heldRef = self->LimitHandPositionRelativeToHead(leftHandPosition, headPosition); + // newRightHandPosition.heldRef = self->LimitHandPositionRelativeToHead(rightHandPosition, headPosition); + // //AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet(self, headRotation, headPosition, leftHandPosition, rightHandPosition, newHeadPosition, newLeftHandPosition, newRightHandPosition); + // } #pragma endregion @@ -281,6 +288,6 @@ namespace MultiQuestensions { INSTALL_HOOK(getLogger(), MultiplayerLobbyController_ActivateMultiplayerLobby); INSTALL_HOOK(getLogger(), LightWithIdMonoBehaviour_RegisterLight); INSTALL_HOOK(getLogger(), MultiplayerLobbyAvatarManager_AddPlayer); - INSTALL_HOOK_ORIG(getLogger(), AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet); + // INSTALL_HOOK_ORIG(getLogger(), AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet); } } \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/InstallerHooks.cpp b/MultiQuestensions/src/Hooks/InstallerHooks.cpp index fd3fcb6..35abc44 100644 --- a/MultiQuestensions/src/Hooks/InstallerHooks.cpp +++ b/MultiQuestensions/src/Hooks/InstallerHooks.cpp @@ -8,19 +8,16 @@ #include "GlobalNamespace/PracticeSettings.hpp" #include "GlobalNamespace/EnvironmentInfoSO.hpp" #include "GlobalNamespace/ColorScheme.hpp" +#include "GlobalNamespace/MainSettingsModelSO.hpp" +#include "Config.hpp" using namespace GlobalNamespace; namespace MultiQuestensions { MAKE_HOOK_MATCH(MultiplayerConnectedPlayerInstaller_InstallBindings, &MultiplayerConnectedPlayerInstaller::InstallBindings, void, MultiplayerConnectedPlayerInstaller* self) { - //getLogger().debug("LagReducer set to '%s'", getConfig().config["LagReducer"].GetBool() ? "true" : "false"); - //self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() |= getConfig().config["LagReducer"].GetBool(); - self->dyn__sceneSetupData() = GameplayCoreSceneSetupData::New_ctor( self->dyn__sceneSetupData()->dyn_difficultyBeatmap(), self->dyn__sceneSetupData()->dyn_previewBeatmapLevel(), self->dyn__sceneSetupData()->dyn_gameplayModifiers()->CopyWith( - System::Nullable_1(), - System::Nullable_1(), System::Nullable_1(), System::Nullable_1(), System::Nullable_1(), @@ -34,7 +31,7 @@ namespace MultiQuestensions { System::Nullable_1(), System::Nullable_1(), System::Nullable_1(), - System::Nullable_1(self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() || getConfig().config["LagReducer"].GetBool(), true), + System::Nullable_1(self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() || config.LagReducer, true), System::Nullable_1() //zenMode: Plugin.Config.LagReducer ), @@ -42,12 +39,14 @@ namespace MultiQuestensions { self->dyn__sceneSetupData()->dyn_practiceSettings(), self->dyn__sceneSetupData()->dyn_useTestNoteCutSoundEffects(), self->dyn__sceneSetupData()->dyn_environmentInfo(), - self->dyn__sceneSetupData()->dyn_colorScheme() + self->dyn__sceneSetupData()->dyn_colorScheme(), + self->dyn__sceneSetupData()->dyn_mainSettingsModel() ); MultiplayerConnectedPlayerInstaller_InstallBindings(self); } + void Hooks::InstallerHooks() { INSTALL_HOOK(getLogger(), MultiplayerConnectedPlayerInstaller_InstallBindings); } diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp new file mode 100644 index 0000000..f8dfe8d --- /dev/null +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -0,0 +1,206 @@ +#include "main.hpp" +#include "Hooks/Hooks.hpp" +#include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" +#include "GlobalFields.hpp" +#include "Hooks/EnvironmentAndAvatarHooks.hpp" +#include "Players/MpexPlayerManager.hpp" +#include "Config.hpp" + +#include "GlobalNamespace/IPlatformUserModel.hpp" +#include "GlobalNamespace/LocalNetworkPlayerModel.hpp" +#include "UnityEngine/Resources.hpp" +#include "GlobalNamespace/UserInfo.hpp" +#include "GlobalNamespace/MultiplayerSessionManager_SessionType.hpp" + +#include "CodegenExtensions/ColorUtility.hpp" + +#include "questui/shared/BeatSaberUI.hpp" +#include "questui/shared/CustomTypes/Components/MainThreadScheduler.hpp" + +#include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" +using namespace MultiQuestensions; +using namespace MultiplayerCore::Networking; +using namespace GlobalNamespace; + +// std::map> _extendedPlayers; +std::map> _mpexPlayerData; +//System::Collections::Generic::Dictionary_2* extendedPlayers; +//SafePtr*> extendedPlayersSPTR; +//SafePtr localExtendedPlayerSPTR; +// SafePtr localExtendedPlayer; +SafePtr localMpexPlayerData; +IPlatformUserModel* platformUserModel; + +MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::PlayerConnected; + +bool MultiQuestensions::Players::MpexPlayerManager::TryGetPlayer(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { + if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { + player = static_cast(_mpexPlayerData.at(playerId)); + return true; + } + return false; + } + +MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetPlayer(std::string playerId) { + if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { + return static_cast(_mpexPlayerData.at(playerId)); + } + return nullptr; + } + +static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* player) { + const std::string userId = to_utf8(csstrtostr(player->get_userId())); + + if (_mpexPlayerData.contains(userId)) { + _mpexPlayerData[userId] = packet; + } + else { + getLogger().info("Received 'MpexPlayerData' from '%s' with color: '%f, %f, %f, %f'", + userId.c_str(), + packet->Color.r, packet->Color.g, packet->Color.b, packet->Color.a + ); + _mpexPlayerData.emplace(userId, packet); + } + + SetPlayerPlaceColor(player, packet->Color, true); + MultiQuestensions::Players::MpexPlayerManager::PlayerConnected(player, packet); + // CreateOrUpdateNameTag(player); + + //if (extendedPlayers->ContainsKey(player->get_userId())) { + // if (_mpexPlayerData.contains(userId)) { + // SafePtr extendedPlayer = _mpexPlayerData.at(userId); + // //Extensions::ExtendedPlayer* extendedPlayer = extendedPlayers->get_Item(player->get_userId()); + // // extendedPlayer->_connectedPlayer = player; + // // extendedPlayer->platformID = packet->platformID; + // // extendedPlayer->platform = packet->platform; + // // extendedPlayer->playerColor = packet->playerColor; + // // extendedPlayer->mpexVersion = packet->mpexVersion; + + // // Updates Color and NameTag + // SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); + // CreateOrUpdateNameTag(reinterpret_cast(extendedPlayer->get_self())); + // } + // else { + // getLogger().info("Received 'ExtendedPlayerPacket' from '%s' with platformID: '%s' mpexVersion: '%s'", + // std::string(player->get_userId()).c_str(), + // std::string(packet->platformID).c_str(), + // std::string(packet->mpexVersion).c_str() + // ); + // Extensions::ExtendedPlayer* extendedPlayer; + // try { + // extendedPlayer = Extensions::ExtendedPlayer::CS_ctor(player, packet->platformID, packet->platform, packet->mpexVersion, packet->playerColor); + // if (std::string(extendedPlayer->mpexVersion) != MPEX_PROTOCOL) + // { + // getLogger().warning( + // "###################################################################\r\n" + // "Different MultiplayerExtensions protocol detected!\r\n" + // "The player '%s' is using MpEx protocol version %s while you are using MpEx protocol " MPEX_PROTOCOL "\r\n" + // "For best compatibility all players should use a compatible version of MultiplayerExtensions/MultiQuestensions.\r\n" + // "###################################################################", + // std::string(player->get_userName()).c_str(), + // std::string(extendedPlayer->mpexVersion).c_str() + // ); + // } + // } + // catch (const std::runtime_error& e) { + // getLogger().error("REPORT TO ENDER: Exception while trying to create ExtendedPlayer: %s", e.what()); + // } + // if (extendedPlayer) { + // _extendedPlayers.emplace(userId, extendedPlayer); + // //extendedPlayers->Add(player->get_userId(), extendedPlayer); + // //if (!extendedPlayersSPTR) extendedPlayersSPTR = extendedPlayers; + + // //getLogger().debug("SetPlayerPlaceColor"); + // SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); + // //getLogger().debug("CreateOrUpdateNameTag"); + // // This packet is usually received before the avatar is actually created + // CreateOrUpdateNameTag(reinterpret_cast(extendedPlayer->get_self())); + // getLogger().debug("ExtendedPlayerPacket done"); + + // //extendedPlayerConnectedEvent::Invoke(extendedPlayer); + // } + // } +} + +void HandlePlayerConnected(IConnectedPlayer* player) { + try { + getLogger().debug("HandlePlayerConnected"); + if (player) { + const std::string userId = player->get_userId(); + getLogger().info("Player '%s' joined", userId.c_str()); + getLogger().debug("Sending MpexPlayerData"); + if (localMpexPlayerData) + { + MultiplayerCore::mpPacketSerializer->Send(localMpexPlayerData->ToSerializable()); + } + getLogger().debug("MpexPlayerData sent"); + + SetPlayerPlaceColor(player, Config::DefaultPlayerColor, false); + } + } + catch (const std::runtime_error& e) { + getLogger().error("REPORT TO ENDER: %s", e.what()); + } +} + +void HandlePlayerDisconnected(IConnectedPlayer* player) { + getLogger().info("Reseting platform lights for Player '%s'", std::string(player->get_userId()).c_str()); + SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); + _mpexPlayerData.erase(std::string(player->get_userId()).c_str()); +} + +// void HandleDisconnect(DisconnectedReason* reason) { + +// } + +MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, MultiplayerSessionManager* self) { + + sessionManager = self; + SessionManagerStart(sessionManager); +} + +MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSession, void, MultiplayerSessionManager* self, MultiplayerSessionManager_SessionType sessionType, ConnectedPlayerManager* connectedPlayerManager) { + SessionManager_StartSession(self, sessionType, connectedPlayerManager); + getLogger().debug("MultiplayerSessionManager.StartSession, creating localMpexPlayerData"); + //try { + localMpexPlayerData = Players::MpexPlayerData::New_ctor(); + // localExtendedPlayer = Extensions::ExtendedPlayer::CS_ctor(self->get_localPlayer()); + //localExtendedPlayerSPTR = localExtendedPlayer; + + localMpexPlayerData->Color = config.PlayerColor; + // if (!UnityEngine::ColorUtility::TryParseHtmlString(il2cpp_utils::newcsstr(getConfig().config["color"].GetString()), localExtendedPlayer->playerColor)) + // localExtendedPlayer->playerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f, 1.0f); + + // static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll().get(0); + // static auto UserInfoTask = localNetworkPlayerModel->dyn__platformUserModel()->GetUserInfo(); + // static auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function*)>)[&](System::Threading::Tasks::Task_1* userInfoTask) { + // auto userInfo = userInfoTask->get_Result(); + // if (userInfo) { + // localExtendedPlayer->platformID = userInfo->dyn_platformUserId(); + // localExtendedPlayer->platform = (Extensions::Platform)userInfo->dyn_platform().value; + // } + // else getLogger().error("Failed to get local network player!"); + // } + // ); + // reinterpret_cast(UserInfoTask)->ContinueWith(action); + + self->SetLocalPlayerState("modded", true); + + //} + //catch (const std::runtime_error& e) { + // getLogger().error("%s", e.what()); + //} + + MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); + + self->add_playerConnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerConnected)); + self->add_playerDisconnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerDisconnected)); + // self->add_disconnectedEvent(il2cpp_utils::MakeDelegate*>*>(classof(System::Action_1*>*), static_cast(nullptr), HandleDisconnect)); +} + + +void MultiQuestensions::Hooks::SessionManagerAndExtendedPlayerHooks() { + INSTALL_HOOK(getLogger(), SessionManagerStart); + INSTALL_HOOK(getLogger(), SessionManager_StartSession); +} \ No newline at end of file From b1a3f0c9dced87337b2173ac3eae2a6aed703cbd Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:42:51 +0200 Subject: [PATCH 15/56] Remove useless comment --- .../shared/CodegenExtensions/ColorUtility.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp b/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp index db437db..d81d9ae 100644 --- a/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp +++ b/MultiQuestensions/shared/CodegenExtensions/ColorUtility.hpp @@ -1,16 +1,12 @@ #pragma once #include "main.hpp" #include "beatsaber-hook/shared/utils/byref.hpp" -#include "UnityEngine/UnityString.hpp" #include "UnityEngine/Color32.hpp" +#include "UnityEngine/Color.hpp" namespace UnityEngine { // Forward declaration of UnityEngine.Color - class Color; - //// Forward declaration of UnityEngine.Color32 - //class Color32; - //// Forward declaration of UnityEngine.UnityString - //class UnityString; + // class Color; class ColorUtility { ColorUtility() = delete; From 840efd16e103b590a1959e52bd8438f2211540bd Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:43:57 +0200 Subject: [PATCH 16/56] Refactor LobbySetupPanel --- MultiQuestensions/src/UI/LobbySetupPanel.cpp | 69 +++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/MultiQuestensions/src/UI/LobbySetupPanel.cpp b/MultiQuestensions/src/UI/LobbySetupPanel.cpp index 4d7505a..c9defbc 100644 --- a/MultiQuestensions/src/UI/LobbySetupPanel.cpp +++ b/MultiQuestensions/src/UI/LobbySetupPanel.cpp @@ -1,5 +1,6 @@ #include "main.hpp" #include "UI/LobbySetupPanel.hpp" +#include "Config.hpp" #include "questui/shared/BeatSaberUI.hpp" #include "UnityEngine/UI/ContentSizeFitter.hpp" #include "UnityEngine/UI/LayoutElement.hpp" @@ -9,10 +10,10 @@ #include "GlobalFields.hpp" #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" #include "Hooks/EnvironmentAndAvatarHooks.hpp" -#include "songloader/shared/API.hpp" -#include "UI/DownloadedSongsGSM.hpp" -#include "Utils/SemVerChecker.hpp" + +#include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" using namespace UnityEngine::UI; +using namespace MultiQuestensions; namespace MultiQuestensions::UI { @@ -20,6 +21,7 @@ namespace MultiQuestensions::UI { bool LobbySetupPanel::needRefresh; void SetLagReducer(bool value) { + getConfig().config["LagReducer"].SetBool(value); getConfig().Write(); } @@ -47,20 +49,20 @@ namespace MultiQuestensions::UI { vertical4->get_gameObject()->AddComponent() ->set_minWidth(45); - using namespace MultiQuestensions::Utils; - if (IsInstalled(ChromaID) && !MatchesVersion(ChromaID, ChromaVersionRange)) { - //HMUI::ModalView* modal = QuestUI::BeatSaberUI::CreateModal(parent, { 55, 25 }, std::nullptr_t()); - //auto wrapper = QuestUI::BeatSaberUI::CreateHorizontalLayoutGroup(modal->get_transform()); - //auto container = QuestUI::BeatSaberUI::CreateVerticalLayoutGroup(wrapper->get_transform()); - //container->set_childAlignment(UnityEngine::TextAnchor::MiddleCenter); - //QuestUI::BeatSaberUI::CreateText(modal->get_transform(), "Chroma detected!\r\nChroma may cause issues such as crashes,\r\nif you're experiencing issues like these,\r\nthen it may be best to try disabling Chroma")->set_alignment(TMPro::TextAlignmentOptions::Center); - //modal->Show(true, true, nullptr); - QuestUI::BeatSaberUI::CreateText(vertical2->get_transform(), - "Chroma outdated!\r\nPlease update to the latest version of Chroma.", - { -40, 0 })->set_alignment(TMPro::TextAlignmentOptions::Left); - getLogger().warning("Chroma outdated"); - } - else getLogger().debug("Chroma not installed or version incompatible"); + // using namespace MultiQuestensions::Utils; + // if (IsInstalled(ChromaID) && !MatchesVersion(ChromaID, ChromaVersionRange)) { + // //HMUI::ModalView* modal = QuestUI::BeatSaberUI::CreateModal(parent, { 55, 25 }, std::nullptr_t()); + // //auto wrapper = QuestUI::BeatSaberUI::CreateHorizontalLayoutGroup(modal->get_transform()); + // //auto container = QuestUI::BeatSaberUI::CreateVerticalLayoutGroup(wrapper->get_transform()); + // //container->set_childAlignment(UnityEngine::TextAnchor::MiddleCenter); + // //QuestUI::BeatSaberUI::CreateText(modal->get_transform(), "Chroma detected!\r\nChroma may cause issues such as crashes,\r\nif you're experiencing issues like these,\r\nthen it may be best to try disabling Chroma")->set_alignment(TMPro::TextAlignmentOptions::Center); + // //modal->Show(true, true, nullptr); + // QuestUI::BeatSaberUI::CreateText(vertical2->get_transform(), + // "Chroma outdated!\r\nPlease update to the latest version of Chroma.", + // { -40, 0 })->set_alignment(TMPro::TextAlignmentOptions::Left); + // getLogger().warning("Chroma outdated"); + // } + // else getLogger().debug("Chroma not installed or version incompatible"); // @@ -68,26 +70,29 @@ namespace MultiQuestensions::UI { //QuestUI::BeatSaberUI::CreateText(vertical4->get_transform(), "THESE TOGGLES ARE JUST\r\nPLACEHOLDERS!"); lagReducerToggle = QuestUI::BeatSaberUI::CreateToggle(vertical4->get_transform(), "Lag Reducer", getConfig().config["LagReducer"].GetBool(), SetLagReducer); - QuestUI::BeatSaberUI::AddHoverHint(lagReducerToggle->get_gameObject(), "Makes multiplayer easier for the quest to handle."); + QuestUI::BeatSaberUI::AddHoverHint(lagReducerToggle->get_gameObject(), "Makes Multiplayer easier for the Quest to handle."); - UnityEngine::Color playerColor; - UnityEngine::ColorUtility::TryParseHtmlString(getConfig().config["color"].GetString(), playerColor); + UnityEngine::Color playerColor = config.PlayerColor; + // UnityEngine::ColorUtility::TryParseHtmlString(getConfig().config["color"].GetString(), playerColor); //QuestUI::BeatSaberUI::CreateColorPickerModal(parent->get_transform(), "Player Color Selection", playerColor); auto colorPicker = QuestUI::BeatSaberUI::CreateColorPickerModal(parent, "Player Color Selection", playerColor, [&playerColor, sessionManager](UnityEngine::Color value) { playerColor = value; - getConfig().config["color"].SetString(UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(value), getConfig().config.GetAllocator()); - getConfig().Write(); - localExtendedPlayer->playerColor = value; + config.PlayerColor = value; + // getConfig().config["color"].SetString(UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(value), getConfig().config.GetAllocator()); + // getConfig().Write(); + // localExtendedPlayer->playerColor = value; + localMpexPlayerData->Color = value; SetPlayerPlaceColor(sessionManager->get_localPlayer(), value, true); - Extensions::ExtendedPlayerPacket* localPlayerPacket = Extensions::ExtendedPlayerPacket::Init(localExtendedPlayer->get_platformID(), localExtendedPlayer->get_platform(), localExtendedPlayer->get_playerColor()); - getLogger().debug("LocalPlayer Color is, R: %f G: %f B: %f", localPlayerPacket->playerColor.r, localPlayerPacket->playerColor.g, localPlayerPacket->playerColor.b); - packetManager->Send(reinterpret_cast(localPlayerPacket)); + // Extensions::ExtendedPlayerPacket* localPlayerPacket = Extensions::ExtendedPlayerPacket::Init(localExtendedPlayer->get_platformID(), localExtendedPlayer->get_platform(), localExtendedPlayer->get_playerColor()); + getLogger().debug("LocalPlayer Color is, R: %f G: %f B: %f", localMpexPlayerData->Color.r, localMpexPlayerData->Color.g, localMpexPlayerData->Color.b); + // packetManager->Send(reinterpret_cast(localPlayerPacket)); + MultiplayerCore::mpPacketSerializer->Send(localMpexPlayerData); }, [sessionManager] { - SetPlayerPlaceColor(sessionManager->get_localPlayer(), localExtendedPlayer->get_playerColor(), true); + SetPlayerPlaceColor(sessionManager->get_localPlayer(), localMpexPlayerData->Color, true); //Extensions::ExtendedPlayerPacket* localPlayerPacket = Extensions::ExtendedPlayerPacket::Init(localExtendedPlayer->get_platformID(), localExtendedPlayer->get_platform(), localExtendedPlayer->get_playerColor()); //getLogger().debug("LocalPlayer Color is, R: %f G: %f B: %f", localPlayerPacket->playerColor.r, localPlayerPacket->playerColor.g, localPlayerPacket->playerColor.b); //packetManager->Send(reinterpret_cast(localPlayerPacket)); @@ -107,11 +112,11 @@ namespace MultiQuestensions::UI { } ); - auto autoDelete = QuestUI::BeatSaberUI::CreateToggle(vertical4->get_transform(), "Auto-Delete Songs", getConfig().config["autoDelete"].GetBool(), [](bool value) { - getConfig().config["autoDelete"].SetBool(value); - getConfig().Write(); - }); - QuestUI::BeatSaberUI::AddHoverHint(autoDelete->get_gameObject(), "Automatically deletes downloaded songs after playing them."); + // auto autoDelete = QuestUI::BeatSaberUI::CreateToggle(vertical4->get_transform(), "Auto-Delete Songs", getConfig().config["autoDelete"].GetBool(), [](bool value) { + // getConfig().config["autoDelete"].SetBool(value); + // getConfig().Write(); + // }); + // QuestUI::BeatSaberUI::AddHoverHint(autoDelete->get_gameObject(), "Automatically deletes downloaded songs after playing them."); //auto deleteDownloadedSongs = QuestUI::BeatSaberUI::CreateUIButton(vertical2->get_transform(), "Delete Downloaded", [] { // using namespace RuntimeSongLoader::API; From c789d55ae6c259081a17fa8d56e1cf56c3b2edd8 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 15:44:19 +0200 Subject: [PATCH 17/56] Refactor config reading, remove unused includes --- MultiQuestensions/src/main.cpp | 602 ++++----------------------------- 1 file changed, 71 insertions(+), 531 deletions(-) diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 98421bd..7a2a1c6 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -1,21 +1,14 @@ #include "main.hpp" #include "Hooks/Hooks.hpp" #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" -#include "Beatmaps/PreviewBeatmapPacket.hpp" -#include "Beatmaps/PreviewBeatmapStub.hpp" #include "UI/LobbySetupPanel.hpp" -#include "UI/DownloadedSongsGSM.hpp" -#include "UI/CenterScreenLoading.hpp" -#include "CS_DataStore.hpp" +#include "Config.hpp" + +#include "CodegenExtensions/ColorUtility.hpp" #include "GlobalNamespace/ConnectedPlayerManager.hpp" -#include "CodegenExtensions/TempBloomFilterUtil.hpp" #include "GlobalNamespace/MultiplayerLevelSelectionFlowCoordinator.hpp" -#include "GlobalNamespace/CenterStageScreenController.hpp" - -// For Hooking Debug Loggers -#include "GlobalNamespace/BGNetDebug.hpp" #include "beatsaber-hook/shared/utils/il2cpp-utils.hpp" #include "custom-types/shared/register.hpp" @@ -28,6 +21,7 @@ using namespace GlobalNamespace; using namespace System::Threading::Tasks; using namespace MultiQuestensions; +using UnityEngine::ColorUtility; #ifndef VERSION #warning No Version set @@ -47,120 +41,36 @@ Configuration& getConfig() { return config; } +// Loads the old config from disk using our modInfo, then returns it for use +Configuration& getLegacyConfig() { + static Configuration config({"multiquestensions", modInfo.version}); + config.Load(); + return config; +} + // Returns a logger, useful for printing debug messages Logger& getLogger() { static Logger* myLogger = new Logger(modInfo, LoggerOptions(false, true)); return *myLogger; } - -// Converts a levelId to a levelHash -StringW LevelIdToHash(StringW levelId) { - if (Il2CppString::IsNullOrWhiteSpace(levelId)) { - return nullptr; - } - ArrayW ary = levelId->Split(std::initializer_list{ '_' }, ' '); - StringW hash = nullptr; - if (ary.Length() > 2) { - hash = ary[2]; - } - return (hash != nullptr && hash->get_Length() == 40) ? hash : StringW(); -} - - +Config MultiQuestensions::config; namespace MultiQuestensions { // Plugin setup stuff GlobalNamespace::MultiplayerSessionManager* sessionManager; GlobalNamespace::LobbyPlayersDataModel* lobbyPlayersDataModel; - MultiQuestensions::PacketManager* packetManager; + // MultiQuestensions::PacketManager* packetManager; GlobalNamespace::LobbyGameStateController* lobbyGameStateController; LobbySetupViewController* lobbySetupView; - std::string moddedState = "modded"; - - StringW getCustomLevelSongPackMaskStr() { - static StringW songPackMaskStr("custom_levelpack_CustomLevels"); - return songPackMaskStr; - } - - StringW getModdedStateStr() { - static StringW moddedStateStr("modded"); - return moddedStateStr; - } - - StringW getMEStateStr() { - static StringW moddedStateStr("ME_Installed"); - return moddedStateStr; - } - - StringW getNEStateStr() { - static StringW moddedStateStr("ME_Installed"); - return moddedStateStr; - } - - StringW getChromaStateStr() { - static StringW moddedStateStr("Chroma_Installed"); - return moddedStateStr; - } - bool AllPlayersModded() { for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getModdedStateStr())) return false; - } - return true; - } - - bool AllPlayersHaveNE() { - for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getNEStateStr())) return false; - } - return true; - } - - bool AllPlayersHaveME() { - for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getMEStateStr())) return false; - } - return true; - } - - bool AllPlayersHaveChroma() { - for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState(getChromaStateStr())) return false; + if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState("modded")) return false; } return true; } - - -} - -//using PD_ValueCollection = System::Collections::Generic::Dictionary_2::ValueCollection; - -MultiQuestensions::Beatmaps::PreviewBeatmapStub* GetExistingPreview(Il2CppString* levelId) { - getLogger().debug("GetExistingPreview PlayerCount: %d", sessionManager->dyn__connectedPlayers()->get_Count()); - for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - ILevelGameplaySetupData* playerData = reinterpret_cast(lobbyPlayersDataModel->dyn__playersData()-> - get_Item(sessionManager->dyn__connectedPlayers()->get_Item(i)->get_userId())); - if (playerData->get_beatmapLevel() != nullptr && csstrtostr(playerData->get_beatmapLevel()->get_levelID()) == csstrtostr(levelId)) { - getLogger().debug("GetExistingPreview type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(playerData->get_beatmapLevel())->klass).c_str()); - if (il2cpp_utils::AssignableFrom(reinterpret_cast(playerData->get_beatmapLevel())->klass)) { - getLogger().debug(__FILE__ " Line: %d", __LINE__); - return reinterpret_cast(playerData->get_beatmapLevel()); - } - } - else { - if (playerData->get_beatmapLevel() != nullptr) - getLogger().debug("Check expected levelId: %s, \r\nactual levelId: %s, \r\nlevelIDs match? %s", - to_utf8(csstrtostr(levelId)).c_str(), - to_utf8(csstrtostr(playerData->get_beatmapLevel()->get_levelID())).c_str(), - csstrtostr(playerData->get_beatmapLevel()->get_levelID()) == csstrtostr(levelId) ? "true" : "false"); - else getLogger().debug("beatmapLevel is null"); - } - } - getLogger().debug("GetExistingPreview return nullptr"); - return nullptr; } // LobbyPlayersDataModel Activate @@ -169,403 +79,81 @@ MAKE_HOOK_MATCH(LobbyPlayersActivate, &LobbyPlayersDataModel::Activate, void, Lo LobbyPlayersActivate(lobbyPlayersDataModel); } -// LobbyPlayersDataModel SetLocalPlayerBeatmapLevel -MAKE_HOOK_MATCH(LobbyPlayersSetLocalBeatmap, &LobbyPlayersDataModel::SetLocalPlayerBeatmapLevel, void, LobbyPlayersDataModel* self, StringW levelId, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO* characteristic) { - - StringW hash = LevelIdToHash(levelId); - if (hash.convert() != nullptr) { - getLogger().info("Local user selected song '%s'.", std::string(hash).c_str()); - MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview = GetExistingPreview(levelId); - if (preview != nullptr) { - self->SetPlayerBeatmapLevel(self->get_localUserId(), reinterpret_cast(preview), beatmapDifficulty, characteristic); - self->dyn__menuRpcManager()->RecommendBeatmap(BeatmapIdentifierNetSerializable::New_ctor(levelId, characteristic->get_serializedName(), beatmapDifficulty)); - return; - } - else { - IPreviewBeatmapLevel* localIPreview = self->dyn__beatmapLevelsModel()->GetLevelPreviewForLevelId(levelId); - if (localIPreview != nullptr) { - try { - using namespace MultiQuestensions::Beatmaps; - PreviewBeatmapStub* previewStub = THROW_UNLESS(il2cpp_utils::New(hash, localIPreview, static_cast(nullptr))); - //MultiQuestensions::Beatmaps::PreviewBeatmapStub* previewStub = MultiQuestensions::Beatmaps::PreviewBeatmapStub::New_ctor(hash, localIPreview); - getLogger().debug("Check 'LobbyPlayersSetLocalBeatmap' levelID: %s", std::string(reinterpret_cast(previewStub)->get_levelID()).c_str()); - self->SetPlayerBeatmapLevel(self->get_localUserId(), reinterpret_cast(previewStub), beatmapDifficulty, characteristic); - PreviewBeatmapPacket* packet = previewStub->GetPacket(characteristic->get_serializedName(), beatmapDifficulty); - self->dyn__menuRpcManager()->RecommendBeatmap(BeatmapIdentifierNetSerializable::New_ctor(levelId, characteristic->get_serializedName(), beatmapDifficulty)); - packetManager->Send(packet->ToINetSerializable()); - return; - } - catch (const std::runtime_error& e) { - getLogger().critical("REPORT TO ENDER: An Exception occured during class creation: %s", e.what()); - } - } - } - } - LobbyPlayersSetLocalBeatmap(self, levelId, beatmapDifficulty, characteristic); -} - -std::string GetHash(const std::string& levelId) { - return levelId.substr(RuntimeSongLoader::API::GetCustomLevelsPrefix().length(), levelId.length() - RuntimeSongLoader::API::GetCustomLevelsPrefix().length()); -} - -// LobbyPlayersDataModel HandleMenuRpcManagerSelectedBeatmap (DONT REMOVE THIS, without it a player's selected map will be cleared) -MAKE_HOOK_MATCH(LobbyPlayersSelectedBeatmap, &LobbyPlayersDataModel::HandleMenuRpcManagerRecommendBeatmap, void, LobbyPlayersDataModel* self, StringW userId, BeatmapIdentifierNetSerializable* beatmapId) { - getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: LevelID: %s", std::string(beatmapId->get_levelID()).c_str()); - MultiQuestensions::Beatmaps::PreviewBeatmapStub* preview = GetExistingPreview(beatmapId->get_levelID()); - if (preview != nullptr) { - getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: Preview exists, SetPlayerBeatmapLevel"); - BeatmapCharacteristicSO* characteristic = self->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(beatmapId->get_beatmapCharacteristicSerializedName()); - self->SetPlayerBeatmapLevel(userId, reinterpret_cast(preview), beatmapId->get_difficulty(), characteristic); - return; - } - else { - getLogger().debug("HandleMenuRpcManagerRecommendBeatmap: Preview doesn't exist use localPreview, SetPlayerBeatmapLevel"); - IPreviewBeatmapLevel* localPreview = self->dyn__beatmapLevelsModel()->GetLevelPreviewForLevelId(beatmapId->get_levelID()); - if (localPreview != nullptr) { - BeatmapCharacteristicSO* characteristic = self->dyn__beatmapCharacteristicCollection()->GetBeatmapCharacteristicBySerializedName(beatmapId->get_beatmapCharacteristicSerializedName()); - //self->SetPlayerBeatmapLevel(userId, localPreview, beatmapId->get_difficulty(), characteristic); - LobbyPlayersSelectedBeatmap(self, userId, beatmapId); - } - else { - // TODO: fetch beatmap data from beatsaver - getLogger().debug("No Info found, need to fetch from BeatSaver"); - //BeatSaver::API::GetBeatmapByHashAsync(GetHash((beatmapId->levelID), - // [](std::optional beatmap) { - // QuestUI::MainThreadScheduler::Schedule( - // [beatmap] { - // if (beatmap.has_value()) { - // self->SetPlayerBeatmapLevel(userId, bmPreview, beatmapId); - // // Create our own Preview or something? - // } - // else { - // // Well doesn't exist on BeatSaver then - // } - // } - // ); - // } - //); - } - } -} - MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController::DidActivate, void, LobbySetupViewController* self, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) { lobbySetupView = self; LobbySetupViewController_DidActivate(self, firstActivation, addedToHierarchy, screenSystemEnabling); - if (getConfig().config["autoDelete"].GetBool() && !DownloadedSongIds.empty()) { - using namespace RuntimeSongLoader::API; - std::string hash = DownloadedSongIds.back(); - getLogger().debug("AutoDelete Song with Hash '%s'", hash.c_str()); - std::optional levelOpt = GetLevelByHash(hash); - if (levelOpt.has_value()) { - std::string songPath = to_utf8(csstrtostr(levelOpt.value()->dyn__customLevelPath())); - getLogger().info("Deleting Song: %s", songPath.c_str()); - DeleteSong(songPath, [&] { - RefreshSongs(false); - DownloadedSongIds.pop_back(); - }); - if (lobbyGameStateController) lobbyGameStateController->dyn__menuRpcManager()->SetIsEntitledToLevel(levelOpt.value()->get_levelID(), EntitlementsStatus::NotOwned); - } - } if (firstActivation) { MultiQuestensions::UI::LobbySetupPanel::AddSetupPanel(self->get_rectTransform(), sessionManager); } } -MAKE_HOOK_MATCH(MultiplayerLobbyConnectionController_CreateParty, &MultiplayerLobbyConnectionController::CreateParty, void, MultiplayerLobbyConnectionController* self, CreateServerFormData data) { - data.songPacks = SongPackMask::get_all() | SongPackMask(BloomFilterUtil::ToBloomFilter(getCustomLevelSongPackMaskStr(), 2, 13)); // TODO: Figure out why the Il2CppString constructor crashes - MultiplayerLobbyConnectionController_CreateParty(self, data); -} - -//MAKE_HOOK_MATCH(MultiplayerLobbyConnectionController_ConnectToMatchmaking, &MultiplayerLobbyConnectionController::ConnectToMatchmaking, void, MultiplayerLobbyConnectionController* self, BeatmapDifficultyMask beatmapDifficultyMask, SongPackMask songPackMask, bool allowSongSelection) { -// if (!gotSongPackOverrides) { -// songPackMask = songPackMask | SongPackMask(getCustomLevelSongPackMaskStr()); -// } -// MultiplayerLobbyConnectionController_ConnectToMatchmaking(self, beatmapDifficultyMask, songPackMask, allowSongSelection); -//} - -// Show the custom levels tab in multiplayer -MAKE_HOOK_MATCH(LevelSelectionNavigationController_Setup, &LevelSelectionNavigationController::Setup, void, LevelSelectionNavigationController* self, - SongPackMask songPackMask, BeatmapDifficultyMask allowedBeatmapDifficultyMask, ::ArrayW notAllowedCharacteristics, - bool hidePacksIfOneOrNone, bool hidePracticeButton, ::StringW actionButtonText, IBeatmapLevelPack* levelPackToBeSelectedAfterPresent, - SelectLevelCategoryViewController::LevelCategory startLevelCategory, IPreviewBeatmapLevel* beatmapLevelToBeSelectedAfterPresent, bool enableCustomLevels) { - getLogger().info("LevelSelectionNavigationController_Setup setting custom songs . . ."); - LevelSelectionNavigationController_Setup(self, songPackMask, allowedBeatmapDifficultyMask, notAllowedCharacteristics, hidePacksIfOneOrNone, hidePracticeButton, - actionButtonText, levelPackToBeSelectedAfterPresent, startLevelCategory, beatmapLevelToBeSelectedAfterPresent, songPackMask.Contains(BloomFilterUtil::ToBloomFilter(getCustomLevelSongPackMaskStr(), 2, 13))); +MAKE_HOOK_MATCH(LobbyGameStateController_Activate, &LobbyGameStateController::Activate, void, LobbyGameStateController* self) { + lobbyGameStateController = self; + LobbyGameStateController_Activate(self); } -static bool isMissingLevel = false; - -// This hook makes sure to grey-out the play button so that players can't start a level that someone doesn't have. -// This prevents crashes. -MAKE_HOOK_MATCH(LobbySetupViewController_SetPlayersMissingLevelText , &LobbySetupViewController::SetPlayersMissingLevelText, void, LobbySetupViewController* self, StringW playersMissingLevelText) { - getLogger().info("LobbySetupViewController_SetPlayersMissingLevelText"); - if (!missingLevelText.empty()) { - getLogger().info("Disabling start game as entitlements missing level text exists . . ."); - isMissingLevel = true; - playersMissingLevelText = il2cpp_utils::newcsstr(missingLevelText); - self->SetStartGameEnabled(CannotStartGameReason::DoNotOwnSong); - LobbySetupViewController_SetPlayersMissingLevelText(self, playersMissingLevelText); - return; - } - else if (playersMissingLevelText) { - getLogger().info("Disabling start game as missing level text exists . . ."); - isMissingLevel = true; - self->SetStartGameEnabled(CannotStartGameReason::DoNotOwnSong); - } - else { - getLogger().info("Enabling start game as missing level text does not exist . . ."); - isMissingLevel = false; - self->SetStartGameEnabled(CannotStartGameReason::None); - } +void saveDefaultConfig() { + getLogger().info("Creating config file..."); + ConfigDocument& configDoc = getConfig().config; + configDoc.RemoveAllMembers(); + if (!configDoc.IsObject()) + configDoc.SetObject(); + auto& allocator = configDoc.GetAllocator(); - LobbySetupViewController_SetPlayersMissingLevelText(self, playersMissingLevelText); -} + configDoc.AddMember("Hologram", config.Hologram, allocator); + configDoc.AddMember("LagReducer", config.LagReducer, allocator); + configDoc.AddMember("MissLighting", config.MissLighting, allocator); + configDoc.AddMember("PlayerColor", ColorUtility::ToHtmlStringRGB_CPP(config.PlayerColor), allocator); + configDoc.AddMember("MissColor", ColorUtility::ToHtmlStringRGB_CPP(config.MissColor), allocator); -// Prevent the button becoming shown when we're force disabling it, as pressing it would crash -MAKE_HOOK_MATCH(LobbySetupViewController_SetStartGameEnabled, &LobbySetupViewController::SetStartGameEnabled, void, LobbySetupViewController* self, CannotStartGameReason cannotStartGameReason) { - getLogger().info("LobbySetupViewController_SetStartGameEnabled. Reason: %d", (int)cannotStartGameReason); - if (isMissingLevel && cannotStartGameReason == CannotStartGameReason::None) { - getLogger().info("Game attempted to enable the play button when the level was missing, stopping it!"); - cannotStartGameReason = CannotStartGameReason::DoNotOwnSong; - } - LobbySetupViewController_SetStartGameEnabled(self, cannotStartGameReason); -} - -namespace MultiQuestensions { - bool HasSong(const std::string& levelId) { - return static_cast(RuntimeSongLoader::API::GetLevelById(levelId)); - } + getConfig().Write(); + getLogger().info("Config file created."); } -std::vector DownloadedSongIds; - -MAKE_HOOK_MATCH(MultiplayerLevelLoader_LoadLevel, &MultiplayerLevelLoader::LoadLevel, void, MultiplayerLevelLoader* self, BeatmapIdentifierNetSerializable* beatmapId, GameplayModifiers* gameplayModifiers, float initialStartTime) { - std::string levelId = to_utf8(csstrtostr(beatmapId->get_levelID())); - getLogger().info("MultiplayerLevelLoader_LoadLevel: %s", levelId.c_str()); - MultiQuestensions::UI::CenterScreenLoading* cslInstance = MultiQuestensions::UI::CenterScreenLoading::get_Instance(); - if (IsCustomLevel(levelId)) { - if (HasSong(levelId)) { - getLogger().debug("MultiplayerLevelLoader_LoadLevel, HasSong, calling original"); - MultiplayerLevelLoader_LoadLevel(self, beatmapId, gameplayModifiers, initialStartTime); - return; +bool readConfig() { + getLogger().info("Checking for legacy config file..."); + // Checking legacy config file + ConfigDocument& legacyConfig = getLegacyConfig().config; + if (legacyConfig.IsObject() && !legacyConfig.HasMember("Converted")) { + // Legacy Conversion + getLogger().info("Legacy config file found. Converting..."); + if (legacyConfig.HasMember("LagReducer") && legacyConfig["LagReducer"].IsBool()) { + config.LagReducer = legacyConfig["LagReducer"].GetBool(); } - else { - std::string hash = GetHash(levelId); - BeatSaver::API::GetBeatmapByHashAsync(hash, - [self, beatmapId, gameplayModifiers, initialStartTime, hash, cslInstance](std::optional beatmapOpt) { - if (beatmapOpt.has_value()) { - auto beatmap = beatmapOpt.value(); - auto beatmapName = beatmap.GetName(); - getLogger().info("Downloading map: %s", beatmap.GetName().c_str()); - BeatSaver::API::DownloadBeatmapAsync(beatmap, - [self, beatmapId, gameplayModifiers, initialStartTime, beatmapName, hash, beatmap, cslInstance](bool error) { - if (error) { - getLogger().info("Failed downloading map retrying: %s", beatmapName.c_str()); - BeatSaver::API::DownloadBeatmapAsync(beatmap, - [self, beatmapId, gameplayModifiers, initialStartTime, beatmapName, hash](bool error) { - if (error) { - getLogger().info("Failed downloading map: %s", beatmapName.c_str()); - } - else { - getLogger().info("Downloaded map: %s", beatmapName.c_str()); - DownloadedSongIds.emplace_back(hash); - QuestUI::MainThreadScheduler::Schedule( - [self, beatmapId, gameplayModifiers, initialStartTime, hash] { - RuntimeSongLoader::API::RefreshSongs(false, - [self, beatmapId, gameplayModifiers, initialStartTime, hash](const std::vector& songs) { - auto* downloadedSongsGSM = UI::DownloadedSongsGSM::get_Instance(); - if (!getConfig().config["autoDelete"].GetBool() && downloadedSongsGSM) downloadedSongsGSM->InsertCell(hash); - else { - getLogger().warning("DownloadedSongsGSM was null, adding to queue"); - UI::DownloadedSongsGSM::mapQueue.push_back(hash); - } - getLogger().debug("Pointer Check before loading level: self='%p', beatmapId='%p', gameplayModifiers='%p'", self, beatmapId, gameplayModifiers); - self->dyn__loaderState() = MultiplayerLevelLoader::MultiplayerBeatmapLoaderState::NotLoading; - //getLogger().debug("MultiplayerLevelLoader_LoadLevel, Downloaded, calling original"); - MultiplayerLevelLoader_LoadLevel(self, beatmapId, gameplayModifiers, initialStartTime); - return; - } - ); - } - ); - } - }, [cslInstance](float downloadProgress) { - if (cslInstance) { - QuestUI::MainThreadScheduler::Schedule( - [cslInstance, downloadProgress] { - cslInstance->ShowDownloadingProgress(downloadProgress); - }); - } - } - ); - } - else { - getLogger().info("Downloaded map: %s", beatmapName.c_str()); - DownloadedSongIds.emplace_back(hash); - QuestUI::MainThreadScheduler::Schedule( - [self, beatmapId, gameplayModifiers, initialStartTime, hash] { - RuntimeSongLoader::API::RefreshSongs(false, - [self, beatmapId, gameplayModifiers, initialStartTime, hash](const std::vector& songs) { - auto* downloadedSongsGSM = UI::DownloadedSongsGSM::get_Instance(); - if (!getConfig().config["autoDelete"].GetBool() && downloadedSongsGSM) downloadedSongsGSM->InsertCell(hash); - else { - getLogger().warning("DownloadedSongsGSM was null, adding to queue"); - UI::DownloadedSongsGSM::mapQueue.push_back(hash); - } - getLogger().debug("Pointer Check before loading level: self='%p', beatmapId='%p', gameplayModifiers='%p'", self, beatmapId, gameplayModifiers); - self->dyn__loaderState() = MultiplayerLevelLoader::MultiplayerBeatmapLoaderState::NotLoading; - //getLogger().debug("MultiplayerLevelLoader_LoadLevel, Downloaded, calling original"); - MultiplayerLevelLoader_LoadLevel(self, beatmapId, gameplayModifiers, initialStartTime); - return; - } - ); - } - ); - } - }, [cslInstance](float downloadProgress) { - if (cslInstance) { - QuestUI::MainThreadScheduler::Schedule( - [cslInstance, downloadProgress] { - cslInstance->ShowDownloadingProgress(downloadProgress); - }); - } - } - ); - } - } - ); + if (legacyConfig.HasMember("color") && legacyConfig["color"].IsString()) { + ColorUtility::TryParseHtmlString(legacyConfig["color"].GetString(), config.PlayerColor); } + legacyConfig.AddMember("Converted", true, legacyConfig.GetAllocator()); + } + // TODO: Delete config on a later version + /* + else if (legacyConfig.IsObject() && legacyConfig.HasMember("Converted")) { + remove(Configuration::getConfigFilePath({"multiquestensions", modInfo.version}).c_str()); } - else { - getLogger().debug("MultiplayerLevelLoader_LoadLevel, calling original"); - MultiplayerLevelLoader_LoadLevel(self, beatmapId, gameplayModifiers, initialStartTime); - } -} + */ -// Checks entitlement and stalls lobby until fullfilled, unless a game is already in progress. -MAKE_HOOK_MATCH(LobbyGameStateController_HandleMultiplayerLevelLoaderCountdownFinished, &LobbyGameStateController::HandleMultiplayerLevelLoaderCountdownFinished, void, LobbyGameStateController* self, GlobalNamespace::IPreviewBeatmapLevel* previewBeatmapLevel, GlobalNamespace::BeatmapDifficulty beatmapDifficulty, GlobalNamespace::BeatmapCharacteristicSO* beatmapCharacteristic, GlobalNamespace::IDifficultyBeatmap* difficultyBeatmap, GlobalNamespace::GameplayModifiers* gameplayModifiers) { - getLogger().debug("LobbyGameStateController_HandleMultiplayerLevelLoaderCountdownFinished"); - lobbyGameStateController = self; + getLogger().info("Reading config file..."); + ConfigDocument& configDoc = getConfig().config; + bool parseError = false; + if (configDoc.IsObject()) { - DataStore* instance = DataStore::get_Instance(); - if (!instance) instance = DataStore::CS_Ctor(previewBeatmapLevel, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers, beatmapDifficulty); - - instance->loadingPreviewBeatmapLevel = previewBeatmapLevel; - instance->loadingBeatmapDifficulty = beatmapDifficulty; - instance->loadingBeatmapCharacteristic = beatmapCharacteristic; - instance->loadingDifficultyBeatmap = difficultyBeatmap; - instance->loadingGameplayModifiers = gameplayModifiers; - - //self->dyn__multiplayerLevelLoader()->dyn__loaderState() = MultiplayerLevelLoader::MultiplayerBeatmapLoaderState::NotLoading; - bool entitlementStatusOK = true; - std::string LevelID = to_utf8(csstrtostr(self->get_startedBeatmapId()->get_levelID())); - // Checks each player, to see if they're in the lobby, and if they are, checks their entitlement status. - MultiQuestensions::UI::CenterScreenLoading::playersReady = 0; - for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - StringW csUserID = sessionManager->dyn__connectedPlayers()->get_Item(i)->get_userId(); - std::string UserID = to_utf8(csstrtostr(csUserID)); - if (self->dyn__lobbyPlayersDataModel()->GetPlayerIsInLobby(csUserID)) { - if (entitlementDictionary[UserID][LevelID] != EntitlementsStatus::Ok) entitlementStatusOK = false; - else MultiQuestensions::UI::CenterScreenLoading::playersReady++; - } - } - getLogger().debug("[HandleMultiplayerLevelLoaderCountdownFinished] Players ready: '%d'", MultiQuestensions::UI::CenterScreenLoading::playersReady + 1); - self->dyn__menuRpcManager()->SetIsEntitledToLevel(previewBeatmapLevel->get_levelID(), EntitlementsStatus::Ok); - if (entitlementStatusOK) { - //if (cslInstance) cslInstance->HideLoading(); - //loadingPreviewBeatmapLevel = nullptr; - ////loadingBeatmapDifficulty.dyn_value__() = 1000; - //loadingBeatmapCharacteristic = nullptr; - //loadingDifficultyBeatmap = nullptr; - //loadingGameplayModifiers = nullptr; - DataStore::Clear(); - - // call original method - LobbyGameStateController_HandleMultiplayerLevelLoaderCountdownFinished(self, previewBeatmapLevel, beatmapDifficulty, beatmapCharacteristic, difficultyBeatmap, gameplayModifiers); - //entitlementDictionary.clear(); - } -} -MAKE_HOOK_MATCH(LobbyGameStateController_Activate, &LobbyGameStateController::Activate, void, LobbyGameStateController* self) { - lobbyGameStateController = self; - LobbyGameStateController_Activate(self); -} -//MAKE_HOOK_MATCH(MenuRpcManager_InvokeSetCountdownEndTime, &MenuRpcManager::InvokeSetCountdownEndTime, void, MenuRpcManager* self, ::Il2CppString* userId, float newTime) { -// getLogger().debug("InvokeSetCountdownEndTime: newTime: %f", newTime); -// MenuRpcManager_InvokeSetCountdownEndTime(self, userId, newTime); -//} - -//MAKE_HOOK_MATCH(MenuRpcManager_InvokeStartLevel, &MenuRpcManager::InvokeStartLevel, void, MenuRpcManager* self, ::Il2CppString* userId, GlobalNamespace::BeatmapIdentifierNetSerializable* beatmapId, GlobalNamespace::GameplayModifiers* gameplayModifiers, float startTime) { -// getLogger().debug("StartLevel: startTime: %f", startTime); -// MenuRpcManager_InvokeStartLevel(self, userId, beatmapId, gameplayModifiers, startTime); -//} -// -//MAKE_HOOK_MATCH(LobbyGameStateController_HandleMenuRpcManagerSetCountdownEndTime, &LobbyGameStateController::HandleMenuRpcManagerSetCountdownEndTime, void, LobbyGameStateController* self, ::Il2CppString* userId, float countdownTime) { -// getLogger().debug("SetCountdownEndTime: raw=%f, synctime=%f, r-s=%f", countdownTime, self->multiplayerSessionManager->get_syncTime(), countdownTime - self->multiplayerSessionManager->get_syncTime()); -// LobbyGameStateController_HandleMenuRpcManagerSetCountdownEndTime(self, userId, countdownTime); -//} - -//MAKE_HOOK_MATCH(ConnectedPlayerManager_HandleSyncTimePacket, &ConnectedPlayerManager::HandleSyncTimePacket, void, ConnectedPlayerManager* self, GlobalNamespace::ConnectedPlayerManager::SyncTimePacket* packet, GlobalNamespace::IConnectedPlayer* player) { -// //getLogger().debug("SetCountdownEndTime: raw=%f, synctime=%f, r-s=%f", countdownTime, self->multiplayerSessionManager->get_syncTime(), countdownTime - self->multiplayerSessionManager->get_syncTime()); -// getLogger().debug("HandleSyncTimePacket: syncTime=%f", packet->syncTime); -// -// ConnectedPlayerManager_HandleSyncTimePacket(self, packet, player); -//} - -// TODO: This allows for overwriting entitlement as it doesn't check entitlement for other players selection -MAKE_HOOK_MATCH(GameServerPlayerTableCell_SetData, &GameServerPlayerTableCell::SetData, void, GameServerPlayerTableCell* self, IConnectedPlayer* connectedPlayer, ILobbyPlayerData* playerData, bool hasKickPermissions, bool allowSelection, System::Threading::Tasks::Task_1* getLevelEntitlementTask) { - getLogger().debug("GameServerPlayerTableCell_SetData Set Entitlement Owned"); - getLevelEntitlementTask = Task_1::New_ctor(AdditionalContentModel::EntitlementStatus::Owned); - //if (playerData && reinterpret_cast(playerData)->get_beatmapLevel()) { - // std::string UserID = to_utf8(csstrtostr(connectedPlayer->get_userId())); - // std::string LevelID = to_utf8(csstrtostr(reinterpret_cast(playerData)->get_beatmapLevel()->get_levelID())); - // if (!playerData->get_isInLobby() && entitlementDictionary[UserID][LevelID] != EntitlementsStatus::Ok) getLevelEntitlementTask->TrySetResult(AdditionalContentModel::EntitlementStatus::NotOwned); - //} - GameServerPlayerTableCell_SetData(self, connectedPlayer, playerData, hasKickPermissions, allowSelection, getLevelEntitlementTask); -} + (configDoc.HasMember("Hologram") && configDoc["Hologram"].IsBool()) ? (config.Hologram = configDoc["Hologram"].GetBool()) : parseError = true; + (configDoc.HasMember("LagReducer") && configDoc["LagReducer"].IsBool()) ? (config.LagReducer = configDoc["LagReducer"].GetBool()) : parseError = true; + (configDoc.HasMember("MissLighting") && configDoc["MissLighting"].IsBool()) ? (config.LagReducer = configDoc["MissLighting"].GetBool()) : parseError = true; + if (!(configDoc.HasMember("PlayerColor") && configDoc["PlayerColor"].IsString() && + ColorUtility::TryParseHtmlString(configDoc["PlayerColor"].GetString(), config.PlayerColor))) { + parseError = true; + } + if (!(configDoc.HasMember("MissColor") && configDoc["MissColor"].IsString() && + ColorUtility::TryParseHtmlString(configDoc["MissColor"].GetString(), config.MissColor))) { + parseError = true; + } + } else parseError = true; -MAKE_HOOK_MATCH(CenterStageScreenController_Setup, &CenterStageScreenController::Setup, void, CenterStageScreenController* self, bool showModifiers) { - CenterStageScreenController_Setup(self, showModifiers); - if (!self->get_gameObject()->GetComponent()) - self->get_gameObject()->AddComponent(); -} - - -void saveDefaultConfig() { - getLogger().info("Creating config file..."); - ConfigDocument& config = getConfig().config; - - if (config.HasMember("color") && config["color"].IsString() && - config.HasMember("autoDelete") && config["autoDelete"].IsBool() && - config.HasMember("LagReducer") && config["LagReducer"].IsBool() && - config.HasMember("MaxPlayers") && config["MaxPlayers"].IsInt()) { - getLogger().info("Config file already exists."); - return; - } - - //config.RemoveAllMembers(); - if (!config.IsObject()) - config.SetObject(); - auto& allocator = config.GetAllocator(); - - if (!(config.HasMember("MaxPlayers") && config["MaxPlayers"].IsInt())) - config.AddMember("MaxPlayers", 10, allocator); - if (!(config.HasMember("LagReducer") && config["LagReducer"].IsBool())) - config.AddMember("LagReducer", false, allocator); - if (!(config.HasMember("autoDelete") && config["autoDelete"].IsBool())) - config.AddMember("autoDelete", false, allocator); - if (!(config.HasMember("color") && config["color"].IsString())) - config.AddMember("color", "#08C0FF", allocator); - - //config.AddMember("freemod", false, allocator); - //config.AddMember("hostpick", true, allocator); - //config["customsongs"].SetBool(true); - //config["enforcemods"].SetBool(true); - - getConfig().Write(); - getLogger().info("Config file created."); + return parseError; } // Called at the early stages of game loading @@ -574,73 +162,25 @@ extern "C" void setup(ModInfo& info) { info.version = VERSION; modInfo = info; - //getConfig().Load(); - saveDefaultConfig(); - getLogger().info("Completed setup!"); } -MAKE_HOOK_MATCH(BGNetDebug_Log, &GlobalNamespace::BGNetDebug::Log, void, StringW message) { - getLogger().WithContext("BGNetDebug::Log").debug("%s", std::string(message).c_str()); - BGNetDebug_Log(message); -} - -MAKE_HOOK_MATCH(BGNetDebug_LogError, &GlobalNamespace::BGNetDebug::LogError, void, StringW message) { - getLogger().WithContext("BGNetDebug::LogError").error("%s", std::string(message).c_str()); - BGNetDebug_LogError(message); -} - -MAKE_HOOK_MATCH(BGNetDebug_LogWarning, &GlobalNamespace::BGNetDebug::LogWarning, void, StringW message) { - getLogger().WithContext("BGNetDebug::LogWarning").warning("%s", std::string(message).c_str()); - BGNetDebug_LogWarning(message); -} - // Called later on in the game loading - a good time to install function hooks extern "C" void load() { il2cpp_functions::Init(); - custom_types::Register::AutoRegister(); + if (readConfig()) { + getLogger().error("Config file is invalid."); + saveDefaultConfig(); + } - QuestUI::Register::RegisterGameplaySetupMenu(modInfo, "MP Downloaded", QuestUI::Register::Online); + custom_types::Register::AutoRegister(); getLogger().info("Installing hooks..."); Hooks::Install_Hooks(); INSTALL_HOOK(getLogger(), LobbyPlayersActivate); - INSTALL_HOOK(getLogger(), LobbyPlayersSetLocalBeatmap); - INSTALL_HOOK(getLogger(), LobbyPlayersSelectedBeatmap); - - INSTALL_HOOK_ORIG(getLogger(), MultiplayerLevelLoader_LoadLevel); - //INSTALL_HOOK(getLogger(), NetworkPlayerEntitlementChecker_GetPlayerLevelEntitlementsAsync); - if (Modloader::getMods().find("BeatTogether") != Modloader::getMods().end()) { - getLogger().info("Hello BeatTogether!"); - } - else getLogger().warning("BeatTogether was not found! Is Multiplayer modded?"); - INSTALL_HOOK_ORIG(getLogger(), LobbyGameStateController_HandleMultiplayerLevelLoaderCountdownFinished); INSTALL_HOOK(getLogger(), LobbyGameStateController_Activate); - INSTALL_HOOK(getLogger(), LobbySetupViewController_SetPlayersMissingLevelText); - INSTALL_HOOK(getLogger(), LobbySetupViewController_SetStartGameEnabled); INSTALL_HOOK(getLogger(), LobbySetupViewController_DidActivate); - - INSTALL_HOOK(getLogger(), MultiplayerLobbyConnectionController_CreateParty); - //INSTALL_HOOK(getLogger(), MultiplayerLobbyConnectionController_ConnectToMatchmaking); - - INSTALL_HOOK(getLogger(), LevelSelectionNavigationController_Setup); - INSTALL_HOOK(getLogger(), CenterStageScreenController_Setup); - -#pragma region Debug Hooks - //INSTALL_HOOK(getLogger(), MenuRpcManager_InvokeSetCountdownEndTime); - //INSTALL_HOOK(getLogger(), MenuRpcManager_InvokeStartLevel); - //INSTALL_HOOK(getLogger(), LobbyGameStateController_HandleMenuRpcManagerSetCountdownEndTime); - //INSTALL_HOOK(getLogger(), ConnectedPlayerManager_HandleSyncTimePacket); - - INSTALL_HOOK(getLogger(), BGNetDebug_Log); - INSTALL_HOOK(getLogger(), BGNetDebug_LogError); - INSTALL_HOOK(getLogger(), BGNetDebug_LogWarning); -#pragma endregion - - - INSTALL_HOOK(getLogger(), GameServerPlayerTableCell_SetData); - getLogger().info("Installed all hooks!"); } \ No newline at end of file From 69a9c96e1080955ac8404fdc3a23d5a214cd8fd1 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 16:55:42 +0200 Subject: [PATCH 18/56] Update build files --- MultiQuestensions/build.ps1 | 2 +- MultiQuestensions/buildQMOD.ps1 | 153 ++++++++++++++++++++------------ MultiQuestensions/mod.json | 26 +++--- MultiQuestensions/qpm.json | 2 +- 4 files changed, 111 insertions(+), 72 deletions(-) diff --git a/MultiQuestensions/build.ps1 b/MultiQuestensions/build.ps1 index 3025e13..31ba03b 100644 --- a/MultiQuestensions/build.ps1 +++ b/MultiQuestensions/build.ps1 @@ -8,7 +8,7 @@ if ($env:VERSION) { $Version = $env:VERSION } if (!($Version)) { -$Version = "0.2.0" +$Version = "1.0.0" } if ($env:MPEX_PROTOCOL) { $MpEx_Protocol = $env:MPEX_PROTOCOL diff --git a/MultiQuestensions/buildQMOD.ps1 b/MultiQuestensions/buildQMOD.ps1 index a037a67..8c22e7a 100644 --- a/MultiQuestensions/buildQMOD.ps1 +++ b/MultiQuestensions/buildQMOD.ps1 @@ -1,65 +1,104 @@ -# Builds a .qmod file for loading with QP -if ($args.Count -eq 0) { -$ModID = "MultiQuestensions" -$VERSION = "0.2.0" -$BS_Version = "1.21.0" -$new_VERSION = Read-Host -Prompt "Input desired mod version (leave empty for default: '$VERSION')" -$bs_hook_version = $BSHook.Replace("_", ".") -$new_BSHook = Read-Host -Prompt "Input current bs-hook version (leave empty for default: '$bs_hook_version')" -if ($new_VERSION -ne "") { - $VERSION = $new_VERSION +Param( + [Parameter(Mandatory=$false, HelpMessage="The name the output qmod file should have")][String] $qmodname="MultiQuestensions", + + [Parameter(Mandatory=$false, HelpMessage="The version of the mod")][String] $version, + + [Parameter(Mandatory=$false, HelpMessage="Switch to create a clean compilation")] + [Alias("rebuild")] + [Switch] $clean, + + [Parameter(Mandatory=$false, HelpMessage="Prints the help instructions")] + [Switch] $help, + + [Parameter(Mandatory=$false, HelpMessage="Tells the script to not compile and only package the existing files")] + [Alias("actions", "pack")] + [Switch] $package +) + +# Builds a .qmod file for loading with QP or BMBF + + +if ($help -eq $true) { + Write-Output "`"BuildQmod `" - Copiles your mod into a `".so`" or a `".a`" library" + Write-Output "`n-- Parameters --`n" + Write-Output "qmodName `t The file name of your qmod" + + Write-Output "`n-- Arguments --`n" + + Write-Output "-clean `t`t Performs a clean build on both your library and the qmod" + Write-Output "-help `t`t Prints this" + Write-Output "-package `t Only packages existing files, without recompiling`n" + + exit } -if ($new_BSHook -ne "") { - $BSHook = $new_BSHook.Replace(".", "_") + +if ($qmodName -eq "") +{ + Write-Output "Give a proper qmod name and try again" + exit } -Write-Host "Compiling Mod" -& $PSScriptRoot/build.ps1 -Version $VERSION -& Copy-Item "./build/debug/lib$ModID.so" -Destination "./debug-builds/lib""$ModID""_$VERSION.so" + +if ($package -eq $true) { + $qmodName = "$($env:module_id)_$($env:version)" + Write-Output "Actions: Packaging QMod $qmodName" } +if (($args.Count -eq 0) -And $package -eq $false) { + Write-Output "Creating QMod $qmodName" + & $PSScriptRoot/build.ps1 -clean:$clean -version:$version + + if ($LASTEXITCODE -ne 0) { + Write-Output "Failed to build, exiting..." + exit $LASTEXITCODE + } -# TODO: Get the below working with Github Actions variables. -if ($args[0] -eq "--package") { - $ModID = $env:module_id - $BSHook = $env:bs_hook - $VERSION = $env:version - $BS_Version = $env:BSVersion - Write-Host "Github Actions Package started" + qpm-rust qmod build } -# Checks if the build was successful -if ($?) { - # Checks if any needed files are missing - if ((Test-Path "./build/libbeatsaber-hook_$BSHook.so", "./build/lib$ModID.so", "./mod.json") -contains $false) { - Write-Host "The following files are missing" - if (!(Test-Path "./build/libbeatsaber-hook_$BSHook.so")) { - Write-Host "./build/libbeatsaber-hook_$BSHook.so" - } - if (!(Test-Path "./build/lib$ModID.so")) { - Write-Host "./build/lib$ModID.so" - } - if (!(Test-Path ".\mod.json")) { - Write-Host ".\mod.json" - } - Write-Host "Task Failed" - exit 1; + +Write-Output "Creating qmod from mod.json" + +$mod = "./mod.json" +$modJson = Get-Content $mod -Raw | ConvertFrom-Json + +$filelist = @($mod) + +$cover = "./" + $modJson.coverImage +if ((-not ($cover -eq "./")) -and (Test-Path $cover)) +{ + $filelist += ,$cover +} else { + Write-Output "No cover Image found" +} + +foreach ($mod in $modJson.modFiles) +{ + $path = "./build/" + $mod + if (-not (Test-Path $path)) + { + $path = "./extern/libs/" + $mod } - else { - # If we have all files needed, go ahead and package into qmod - if ($args.Count -eq 0 -or $args[0] -eq "--package") { - Write-Host "Upating mod.json" - $json = Get-Content $PSScriptRoot/mod.json -raw | ConvertFrom-Json - $json.packageVersion = "$BS_Version" - $json.version="$VERSION" - $json.libraryFiles=@("libbeatsaber-hook_$BSHook.so") - $json | ConvertTo-Json -depth 32| Set-Content $PSScriptRoot/mod.json - - Write-Host "Packaging QMod with ModID: $ModID Version: $VERSION and BS-Hook version: $BSHook" - $packagename = $ModID + "_v" + $VERSION - Compress-Archive -Path "./libs/arm64-v8a/lib$ModID.so", "./libs/arm64-v8a/libbeatsaber-hook_$BSHook.so", ".\mod.json" -DestinationPath "./Temp$packagename.zip" -Update - Move-Item "./Temp$packagename.zip" "./$packagename.qmod" -Force - } - Write-Host "Task Completed" + $filelist += $path +} + +foreach ($lib in $modJson.libraryFiles) +{ + $path = "./extern/libs/" + $lib + if (-not (Test-Path $path)) + { + $path = "./build/" + $lib } + $filelist += $path +} + +$zip = $qmodName + ".zip" +$qmod = $qmodName + ".qmod" + +if ((-not ($clean.IsPresent)) -and (Test-Path $qmod)) +{ + Write-Output "Making Clean Qmod" + Move-Item $qmod $zip -Force } -else { - Write-Host "Build failed, see output" -} \ No newline at end of file + +Compress-Archive -Path $filelist -DestinationPath $zip -Update +Move-Item $zip $qmod -Force + +Write-Output "Task Completed" \ No newline at end of file diff --git a/MultiQuestensions/mod.json b/MultiQuestensions/mod.json index 3fd299f..ad23443 100644 --- a/MultiQuestensions/mod.json +++ b/MultiQuestensions/mod.json @@ -1,11 +1,11 @@ { "_QPVersion": "0.1.2", "name": "MultiQuestensions", - "id": "multiquestensions", + "id": "MultiQuestensions", "author": "EnderdracheLP and Goobie", - "version": "0.2.0", + "version": "1.0.0-Dev", "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.19.0", + "packageVersion": "1.21.0", "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", "dependencies": [ { @@ -14,31 +14,31 @@ "downloadIfMissing": "https://github.com/pythonology/BeatTogether.Quest/releases/download/v1.4.0/BeatTogether_v1.4.0.qmod" }, { - "version": "^0.15.6", - "id": "custom-types", - "downloadIfMissing": "https://github.com/sc2ad/Il2CppQuestTypePatching/releases/download/v0.15.6/CustomTypes.qmod" + "version": "^1.0.0", + "id": "MultiplayerCore.Quest", + "downloadIfMissing": "https://github.com/EnderdracheLP/MultiplayerCore.Quest/releases/download/v1.0.0/MultiplayerCore.qmod" }, { - "version": "^0.8.3", - "id": "songloader", - "downloadIfMissing": "https://github.com/darknight1050/SongLoader/releases/download/v0.8.3/SongLoader.qmod" + "version": "^0.15.9", + "id": "custom-types", + "downloadIfMissing": "https://github.com/sc2ad/Il2CppQuestTypePatching/releases/download/v0.15.9/CustomTypes.qmod" }, { - "version": "^0.19.3", + "version": "^0.22.0", "id": "codegen", - "downloadIfMissing": "https://github.com/sc2ad/BeatSaber-Quest-Codegen/releases/download/v0.19.3/Codegen.qmod" + "downloadIfMissing": "https://github.com/sc2ad/BeatSaber-Quest-Codegen/releases/download/v0.22.0/Codegen.qmod" }, { "version": "^0.13.1", "id": "questui", - "downloadIfMissing": "https://github.com/darknight1050/questui/releases/download/v0.13.1/QuestUI.qmod" + "downloadIfMissing": "https://github.com/darknight1050/questui/releases/download/v0.13.5/QuestUI.qmod" } ], "modFiles": [ "libMultiQuestensions.so" ], "libraryFiles": [ - "libbeatsaber-hook_3_6_7.so" + "libbeatsaber-hook_3_7_4.so" ], "fileCopies": [], "copyExtensions": [] diff --git a/MultiQuestensions/qpm.json b/MultiQuestensions/qpm.json index d229882..163b50c 100644 --- a/MultiQuestensions/qpm.json +++ b/MultiQuestensions/qpm.json @@ -4,7 +4,7 @@ "info": { "name": "MultiQuestensions", "id": "MultiQuestensions", - "version": "0.2.0", + "version": "1.0.0", "url": "", "additionalData": { "overrideSoName": "libMultiQuestensions.so" From 2aedac4bf31d43faf2b0f8f6e03001539a2e6f1f Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 16:57:04 +0200 Subject: [PATCH 19/56] Fix stupid mistake + event use handle functions --- .../src/Environments/MQEAvaterNameTag.cpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 30ba356..96af2d2 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -69,13 +69,11 @@ namespace MultiQuestensions::Environments { // Create Event handlers _platformDataEventHandler = MultiplayerCore::event_handler( [this](GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data) { - if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) - SetPlatformData(data); + HandlePlatformData(player, data); }); _mpexPlayerDataEventHandler = MultiplayerCore::event_handler( [this](GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpexPlayerData* data) { - if (_nameText && data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) - _nameText->set_color(data->Color); + HandleMpexData(player, data); }); } @@ -110,9 +108,9 @@ namespace MultiQuestensions::Environments { return; _nameText->set_text(player->get_userName()); - std::string userName = static_cast(player->get_userName()); - if (_mpexPlayerData.contains(userName)) - _nameText->set_color(_mpexPlayerData.at(userName)->Color); + std::string userId = static_cast(player->get_userId()); + if (_mpexPlayerData.contains(userId)) + _nameText->set_color(_mpexPlayerData.at(userId)->Color); RemoveIcon(PlayerIconSlot::Platform); @@ -179,21 +177,24 @@ namespace MultiQuestensions::Environments { if (!_enabled) return; + + SetPlayerInfo(simplePlayer); + // _nameText->set_text(simplePlayer->get_userName()); + // _nameText->set_color(Color::get_white()); - _nameText->set_text(simplePlayer->get_userName()); - _nameText->set_color(Color::get_white()); - - RemoveIcon(PlayerIconSlot::Platform); + // RemoveIcon(PlayerIconSlot::Platform); } using MultiplayerCore::Players::MpPlayerData; void MQEAvatarNameTag::HandlePlatformData(IConnectedPlayer* player, MpPlayerData* data) { + getLogger().debug("HandlePlatformData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) SetPlatformData(data); } using MultiQuestensions::Players::MpexPlayerData; void MQEAvatarNameTag::HandleMpexData(IConnectedPlayer* player, MpexPlayerData* data) { + getLogger().debug("HandleMpexData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) _nameText->set_color(data->Color); } From 4fe1ca39e529bfca5d6652a56fb388130aef6650 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 16:57:21 +0200 Subject: [PATCH 20/56] Disable some loggers --- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index deaccce..909961b 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -86,20 +86,20 @@ namespace MultiQuestensions { if (place == nullptr) return; - getLogger().debug("SetPlayerPlaceColor player %s userId %s", static_cast(player->get_userName()).c_str(), static_cast(player->get_userId()).c_str()); + // getLogger().debug("SetPlayerPlaceColor player %s userId %s", static_cast(player->get_userName()).c_str(), static_cast(player->get_userId()).c_str()); - getLogger().debug("SetPlayerPlaceColor new TargetColor %f, %f, %f, %f", color.r, color.g, color.b, color.a); + // getLogger().debug("SetPlayerPlaceColor new TargetColor %f, %f, %f, %f", color.r, color.g, color.b, color.a); - getLogger().debug("SetPlayerPlaceColor current TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); + // getLogger().debug("SetPlayerPlaceColor current TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); if (!priority && place->targetColor != Color::get_black() && place->targetColor != Config::DefaultPlayerColor) { - getLogger().debug("SetPlayerPlaceColor not priority and TargetColor check is priority '%s' check is black '%s', check is DefaultPlayerColor '%s' check full eval '%s'", !priority ? "true" : "false", place->targetColor != Color::get_black() ? "true" : "false", place->targetColor != Config::DefaultPlayerColor ? "true" : "false", (!priority && place->targetColor != Color::get_black() && place->targetColor != Config::DefaultPlayerColor) ? "true" : "false"); + // getLogger().debug("SetPlayerPlaceColor not priority and TargetColor check is priority '%s' check is black '%s', check is DefaultPlayerColor '%s' check full eval '%s'", !priority ? "true" : "false", place->targetColor != Color::get_black() ? "true" : "false", place->targetColor != Config::DefaultPlayerColor ? "true" : "false", (!priority && place->targetColor != Color::get_black() && place->targetColor != Config::DefaultPlayerColor) ? "true" : "false"); - getLogger().debug("SetPlayerPlaceColor TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); + // getLogger().debug("SetPlayerPlaceColor TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); - getLogger().debug("SetPlayerPlaceColor black %f, %f, %f, %f", Color::get_black().r, Color::get_black().g, Color::get_black().b, Color::get_black().a); + // getLogger().debug("SetPlayerPlaceColor black %f, %f, %f, %f", Color::get_black().r, Color::get_black().g, Color::get_black().b, Color::get_black().a); - getLogger().debug("SetPlayerPlaceColor DefaultPlayerColor %f, %f, %f, %f", Config::DefaultPlayerColor.r, Config::DefaultPlayerColor.g, Config::DefaultPlayerColor.b, Config::DefaultPlayerColor.a); + // getLogger().debug("SetPlayerPlaceColor DefaultPlayerColor %f, %f, %f, %f", Config::DefaultPlayerColor.r, Config::DefaultPlayerColor.g, Config::DefaultPlayerColor.b, Config::DefaultPlayerColor.a); // Priority colors are always set; non-priority colors can only override default black/blue return; } @@ -261,7 +261,7 @@ namespace MultiQuestensions { //getLogger().debug("Adding new LobbyAvatarNameTag Component"); nameTag = objAvatarCaption->AddComponent(); } - nameTag->_playerInfo = player; + nameTag->SetPlayerInfo(player); //const std::string userId = player->get_userId(); // if (_extendedPlayers.contains(player->get_userId())) From 2cc79284cf2cdc76b4100e7a7f8d17a0625f89ee Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 16:57:34 +0200 Subject: [PATCH 21/56] Add logger for event calling --- MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index f8dfe8d..f3b153c 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -64,6 +64,7 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl } SetPlayerPlaceColor(player, packet->Color, true); + getLogger().info("Calling event 'PlayerConnected'"); MultiQuestensions::Players::MpexPlayerManager::PlayerConnected(player, packet); // CreateOrUpdateNameTag(player); From c3f8cdd4922304fb4ff7ed1643de5585f4d07325 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 17 Apr 2022 16:58:45 +0200 Subject: [PATCH 22/56] Fix redefinition by accident --- MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 96af2d2..04c937c 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -115,7 +115,6 @@ namespace MultiQuestensions::Environments { RemoveIcon(PlayerIconSlot::Platform); MultiplayerCore::Players::MpPlayerData* data; - std::string userId = static_cast(player->get_userId()); if (MultiplayerCore::Players::MpPlayerManager::TryGetPlayer(userId, data)) SetPlatformData(data); // if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) From de01ab0237138cfb7f1f7aea46f695862bd65d79 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 22 Apr 2022 00:21:32 +0200 Subject: [PATCH 23/56] Move some config stuff into MQE namespace --- MultiQuestensions/src/main.cpp | 99 +++++++--------------------------- 1 file changed, 20 insertions(+), 79 deletions(-) diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 7a2a1c6..1e53b22 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -34,18 +34,20 @@ using UnityEngine::ColorUtility; ModInfo modInfo; // Stores the ID and version of our mod, and is sent to the modloader upon startup -// Loads the config from disk using our modInfo, then returns it for use -Configuration& getConfig() { - static Configuration config(modInfo); - config.Load(); - return config; -} +namespace MultiQuestensions { + // Loads the config from disk using our modInfo, then returns it for use + Configuration& getConfig() { + static Configuration config(modInfo); + config.Load(); + return config; + } -// Loads the old config from disk using our modInfo, then returns it for use -Configuration& getLegacyConfig() { - static Configuration config({"multiquestensions", modInfo.version}); - config.Load(); - return config; + // Loads the old config from disk using our modInfo, then returns it for use + Configuration& getLegacyConfig() { + static Configuration config({"multiquestensions", modInfo.version}); + config.Load(); + return config; + } } // Returns a logger, useful for printing debug messages @@ -92,70 +94,6 @@ MAKE_HOOK_MATCH(LobbyGameStateController_Activate, &LobbyGameStateController::Ac LobbyGameStateController_Activate(self); } -void saveDefaultConfig() { - getLogger().info("Creating config file..."); - ConfigDocument& configDoc = getConfig().config; - - configDoc.RemoveAllMembers(); - if (!configDoc.IsObject()) - configDoc.SetObject(); - auto& allocator = configDoc.GetAllocator(); - - configDoc.AddMember("Hologram", config.Hologram, allocator); - configDoc.AddMember("LagReducer", config.LagReducer, allocator); - configDoc.AddMember("MissLighting", config.MissLighting, allocator); - configDoc.AddMember("PlayerColor", ColorUtility::ToHtmlStringRGB_CPP(config.PlayerColor), allocator); - configDoc.AddMember("MissColor", ColorUtility::ToHtmlStringRGB_CPP(config.MissColor), allocator); - - getConfig().Write(); - getLogger().info("Config file created."); -} - -bool readConfig() { - getLogger().info("Checking for legacy config file..."); - // Checking legacy config file - ConfigDocument& legacyConfig = getLegacyConfig().config; - if (legacyConfig.IsObject() && !legacyConfig.HasMember("Converted")) { - // Legacy Conversion - getLogger().info("Legacy config file found. Converting..."); - if (legacyConfig.HasMember("LagReducer") && legacyConfig["LagReducer"].IsBool()) { - config.LagReducer = legacyConfig["LagReducer"].GetBool(); - } - if (legacyConfig.HasMember("color") && legacyConfig["color"].IsString()) { - ColorUtility::TryParseHtmlString(legacyConfig["color"].GetString(), config.PlayerColor); - } - legacyConfig.AddMember("Converted", true, legacyConfig.GetAllocator()); - } - // TODO: Delete config on a later version - /* - else if (legacyConfig.IsObject() && legacyConfig.HasMember("Converted")) { - remove(Configuration::getConfigFilePath({"multiquestensions", modInfo.version}).c_str()); - } - */ - - getLogger().info("Reading config file..."); - ConfigDocument& configDoc = getConfig().config; - bool parseError = false; - if (configDoc.IsObject()) { - - - - (configDoc.HasMember("Hologram") && configDoc["Hologram"].IsBool()) ? (config.Hologram = configDoc["Hologram"].GetBool()) : parseError = true; - (configDoc.HasMember("LagReducer") && configDoc["LagReducer"].IsBool()) ? (config.LagReducer = configDoc["LagReducer"].GetBool()) : parseError = true; - (configDoc.HasMember("MissLighting") && configDoc["MissLighting"].IsBool()) ? (config.LagReducer = configDoc["MissLighting"].GetBool()) : parseError = true; - if (!(configDoc.HasMember("PlayerColor") && configDoc["PlayerColor"].IsString() && - ColorUtility::TryParseHtmlString(configDoc["PlayerColor"].GetString(), config.PlayerColor))) { - parseError = true; - } - if (!(configDoc.HasMember("MissColor") && configDoc["MissColor"].IsString() && - ColorUtility::TryParseHtmlString(configDoc["MissColor"].GetString(), config.MissColor))) { - parseError = true; - } - } else parseError = true; - - return parseError; -} - // Called at the early stages of game loading extern "C" void setup(ModInfo& info) { info.id = ID; @@ -169,10 +107,13 @@ extern "C" void setup(ModInfo& info) { extern "C" void load() { il2cpp_functions::Init(); - if (readConfig()) { - getLogger().error("Config file is invalid."); - saveDefaultConfig(); - } + // Initialize Config + config.Initialize(); + + // if (readConfig()) { + // getLogger().error("Config file is invalid."); + // saveDefaultConfig(); + // } custom_types::Register::AutoRegister(); From a29aed4cf1021cd1ae1930d9e31f03bdf0d5ef74 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 22 Apr 2022 00:21:52 +0200 Subject: [PATCH 24/56] Meta Sprite --- MultiQuestensions/src/Assets/Sprites.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MultiQuestensions/src/Assets/Sprites.cpp b/MultiQuestensions/src/Assets/Sprites.cpp index 205f604..4213743 100644 --- a/MultiQuestensions/src/Assets/Sprites.cpp +++ b/MultiQuestensions/src/Assets/Sprites.cpp @@ -12,8 +12,9 @@ using namespace QuestUI::BeatSaberUI; namespace MultiQuestensions { std::string Sprites::Oculus64 = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAAHdbkFIAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAN1sAADdbAZmDAsYAAATaSURBVGhD7ZrNq1ZFHMefey21yDSxNyIKKtEyfIEgWgkhIaUFERFKK1GQJHvHZatCFymE/0ALk9zUImpViwiM3l8X1yRSVCKvZaWm5u3znfnd6zNz3u9zjtxb84EvvzNn3ufMnDMvpzcwQ2Z7Y2NjMzHb0AU0PDQ09LLuO/B8E+UxYzyA+M45DLun1JxjkXeHOM8pQH87PIm5xbt6H9AOH+nCBSgqMYF8AnkBxu/VS+G/BHU9rwrX4GmLchHzcNitDHjN8iEcR3Vv2PlE4LkKLYyF1x4fwuESCCDQalSJBU9MGTLDiae0CPMoivvIn2gPI/CYd3omEiDi1Zjfvauc/nHcn0CjDhK8DIi7VgkYG+12BvyO+iBRZrh3+9vlpcD7Jh/qYjhXDNzXY8Yb5zy6y18GXIYmPgBBFQSJXHBJ1+NrixaCx1/ev5RPLHgikaiCATOMXkHnNHoG4DN0pyVbDYFnokOK2QGaxgUELyQCOOMcWc6hA/6yFMWfg252riyv8x7cYtchFGC7K2fIIfNuDHHv90kEnDVvR/zdy853er1riTTXrpuy1mw/Z8w6wm8CkNlpzGzv6oRlPIKv7Do7O8TzCszz3tUqo2hef+aV0Bqz0TNoBDXlLNqHVlhyiUQikUjkkvkcx/AxuQFzO7oHaRns9/Py0ddVy8PDaD86yNcvmIDUhowXI00oB0HbT6+i3E2hQoiwRbFbRAVR61VDwPUuSvscRtrkDYhnxdrQ1TPsin30icfs2hEXYCcmux3oUcc6iao6rqbld6DLnSsLZShIggIcQTHHUONJKnE2uNhZHrEgWfDUPC5mlXk3hrg/+yQCdpi3Ix4e2sqJ+cHsZPjDbD9XmXXEBdCGXMxLZhtBTTXsbvOugBGzjrgTfo5Z7l0B7yCdkdQdIVoXvofyWvRGOuHEjmNcgLsx+Ztg7fA3mQcdOngEeH6D6aoAGp55rRtCK8xFx1HbNFvuEWG/jzcw2r5cbck2g4gr0Fso7/1QxQH0LOpypZ1IJBKJRCKRSCSmMVXbLIWw0NCpmn4TWYnuQ8uQVsN5K+E20cpch6g6dfsYfYi+ZT2rY8buoeIPoU/RKTRVUFlUpjVWzHYhYS3UX0BdLNbbZhS9iOZZ8UupHAIktBizFy1Bkx4ylxhtwehvrccZGt+7OwWUVojKL8Vor3+WuzH90PnEvTTCF96ZpbABqLwOR95F1ZtZHr2c3ka7kbb+9JtJm+jlqjJtRg+jov3vmC/RgzTCEe+sCQ2gXxVOoirOoF2o3hlIC5DXHLQTnUZVqA7PWdQMZadHOmUItrIL+BHtoIV1enFJIC9tu2uf/6C7UY7qoGO+XMoaQJnU2Q3Xk6//b1h7KM86vU51yDt2KIduswblHRnloWOkTajzXVjlgTZannVQHfJ+4HKUvQRlXkNbddEAtfgvSK1edqrcBPVUdeXrUNOZ5i60lWHjXRFVn0Edm76BnnA3ph+av6yj8v945ySgEfQ75zqUd+A4VdHvpzpwzxyMTxoS06dnMxr0h9ouUdmeQvp9tRalQyAPEtd41CdyPXoAaaLU9QqwCL1vNNF5H2mojtDdG713GjdADA2iGdl8pMXHNehWtABdidQwg+aht7Eqegr9in5CJ9BvaJQKtz3jTCQSiUQi8b+g1/sXRmYDomhz93gAAAAASUVORK5CYII="; + std::string Sprites::Steam64 = "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"; - std::string Sprites::Meta64 = "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"; + std::string Sprites::Meta64 = "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"; Sprite* CreateSpriteFromBase64(std::string& base64) { ArrayW bytes = System::Convert::FromBase64String(base64.c_str()); From 268b448ecefc7fb323b06f9969b5a574a74c39fe Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 22 Apr 2022 00:23:14 +0200 Subject: [PATCH 25/56] Add extern _multiplayerSessionManager --- .../include/Hooks/EnvironmentAndAvatarHooks.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp b/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp index ac3bcf7..a8f7478 100644 --- a/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp +++ b/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp @@ -4,6 +4,12 @@ namespace MultiQuestensions { extern void SetPlayerPlaceColor(GlobalNamespace::IConnectedPlayer* player, const UnityEngine::Color& color, bool priority); + extern void UpdateNameTagIcons(); // extern void CreateOrUpdateNameTag(GlobalNamespace::IConnectedPlayer* player); // extern void SetPlatformData(MultiplayerCore::Players::MpPlayerData* data); +} + +#include "GlobalNamespace/MultiplayerSessionManager.hpp" +namespace MultiplayerCore { + extern GlobalNamespace::MultiplayerSessionManager* _multiplayerSessionManager; } \ No newline at end of file From 2d216352ef06fe0cefc6db26c8d2c3943c53f688 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 22 Apr 2022 00:23:37 +0200 Subject: [PATCH 26/56] Add new config --- MultiQuestensions/include/Config.hpp | 128 ++++++++++++++++++++++++++- MultiQuestensions/include/main.hpp | 20 +---- 2 files changed, 128 insertions(+), 20 deletions(-) diff --git a/MultiQuestensions/include/Config.hpp b/MultiQuestensions/include/Config.hpp index 0421148..34c027e 100644 --- a/MultiQuestensions/include/Config.hpp +++ b/MultiQuestensions/include/Config.hpp @@ -1,16 +1,142 @@ #pragma once +#include "main.hpp" #include "UnityEngine/Color.hpp" +#include "CodegenExtensions/ColorUtility.hpp" namespace MultiQuestensions { + Configuration& getConfig(); + Configuration& getLegacyConfig(); + struct Config { static constexpr UnityEngine::Color DefaultPlayerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f, 1.0f); + protected: bool Hologram = true; bool LagReducer = false; bool MissLighting = true; + bool NoMetaZone = false; UnityEngine::Color PlayerColor = DefaultPlayerColor; UnityEngine::Color MissColor = UnityEngine::Color(1, 0, 0, 1); + + public: + bool getHologram() const { return Hologram; } + + void setHologram(bool value) { + Hologram = value; + getConfig().config["Hologram"].SetBool(Hologram); + getConfig().Write(); + } + + bool getLagReducer() const { return LagReducer; } + + void setLagReducer(bool value) { + LagReducer = value; + getConfig().config["LagReducer"].SetBool(LagReducer); + getConfig().Write(); + } + + bool getMissLighting() const { return MissLighting; } + + void setMissLighting(bool value) { + MissLighting = value; + getConfig().config["MissLighting"].SetBool(MissLighting); + getConfig().Write(); + } + + bool getNoMetaZone() const { return NoMetaZone; } + + void setNoMetaZone(bool value) { + NoMetaZone = value; + getConfig().config["NoMetaZone"].SetBool(NoMetaZone); + getConfig().Write(); + } + + UnityEngine::Color getPlayerColor() const { + return PlayerColor; + } + + void setPlayerColor(const UnityEngine::Color& value) { + PlayerColor = value; + ConfigDocument& configDoc = getConfig().config; + auto& allocator = configDoc.GetAllocator(); + configDoc["PlayerColor"].SetString(UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(PlayerColor), allocator); + getConfig().Write(); + } + + UnityEngine::Color getMissColor() const { + return MissColor; + } + + void setMissColor(const UnityEngine::Color& value) { + MissColor = value; + ConfigDocument& configDoc = getConfig().config; + auto& allocator = configDoc.GetAllocator(); + configDoc["MissColor"].SetString(UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(MissColor), allocator); + getConfig().Write(); + } + + void Initialize() { + getLogger().info("Checking for legacy config file..."); + // Checking legacy config file + ConfigDocument& legacyConfig = getLegacyConfig().config; + if (legacyConfig.IsObject() && !legacyConfig.HasMember("Converted")) { + // Legacy Conversion + getLogger().info("Legacy config file found. Converting..."); + if (legacyConfig.HasMember("LagReducer") && legacyConfig["LagReducer"].IsBool()) { + LagReducer = legacyConfig["LagReducer"].GetBool(); + } + if (legacyConfig.HasMember("color") && legacyConfig["color"].IsString()) { + UnityEngine::ColorUtility::TryParseHtmlString(legacyConfig["color"].GetString(), PlayerColor); + } + legacyConfig.AddMember("Converted", true, legacyConfig.GetAllocator()); + } + // TODO: Delete config on a later version + /* + else if (legacyConfig.IsObject() && legacyConfig.HasMember("Converted")) { + remove(Configuration::getConfigFilePath({"multiquestensions", modInfo.version}).c_str()); + } + */ + + getLogger().info("Reading config file..."); + ConfigDocument& configDoc = getConfig().config; + bool parseError = false; + if (configDoc.IsObject()) { + (configDoc.HasMember("Hologram") && configDoc["Hologram"].IsBool()) ? (Hologram = configDoc["Hologram"].GetBool()) : parseError = true; + (configDoc.HasMember("LagReducer") && configDoc["LagReducer"].IsBool()) ? (LagReducer = configDoc["LagReducer"].GetBool()) : parseError = true; + (configDoc.HasMember("MissLighting") && configDoc["MissLighting"].IsBool()) ? (MissLighting = configDoc["MissLighting"].GetBool()) : parseError = true; + (configDoc.HasMember("NoMetaZone") && configDoc["NoMetaZone"].IsBool()) ? (NoMetaZone = configDoc["NoMetaZone"].GetBool()) : parseError = true; + if (!(configDoc.HasMember("PlayerColor") && configDoc["PlayerColor"].IsString() && + UnityEngine::ColorUtility::TryParseHtmlString(configDoc["PlayerColor"].GetString(), PlayerColor))) { + parseError = true; + } + if (!(configDoc.HasMember("MissColor") && configDoc["MissColor"].IsString() && + UnityEngine::ColorUtility::TryParseHtmlString(configDoc["MissColor"].GetString(), MissColor))) { + parseError = true; + } + } else parseError = true; + + if (parseError) SaveDefaultConfig(); + } + + void SaveDefaultConfig() { + getLogger().info("Creating config file..."); + ConfigDocument& configDoc = getConfig().config; + configDoc.RemoveAllMembers(); + if (!configDoc.IsObject()) + configDoc.SetObject(); + auto& allocator = configDoc.GetAllocator(); + + configDoc.AddMember("Hologram", Hologram, allocator); + configDoc.AddMember("LagReducer", LagReducer, allocator); + configDoc.AddMember("MissLighting", MissLighting, allocator); + configDoc.AddMember("NoMetaZone", NoMetaZone, allocator); + configDoc.AddMember("PlayerColor", UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(PlayerColor), allocator); + configDoc.AddMember("MissColor", UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(MissColor), allocator); + + getConfig().Write(); + getLogger().info("Config file created."); + } }; - extern Config config; + extern MultiQuestensions::Config config; } \ No newline at end of file diff --git a/MultiQuestensions/include/main.hpp b/MultiQuestensions/include/main.hpp index 9deb3a8..2cc41ae 100644 --- a/MultiQuestensions/include/main.hpp +++ b/MultiQuestensions/include/main.hpp @@ -36,24 +36,6 @@ #include // Define these functions here so that we can easily read configuration and log information from other files -Configuration& getConfig(); Logger& getLogger(); -// Utilities -StringW LevelIdToHash(StringW); - -extern std::string GetHash(const std::string& levelId); - -extern ModInfo modInfo; - -extern std::vector DownloadedSongIds; - -extern bool gotSongPackOverrides; - -extern std::string missingLevelText; - -namespace MultiQuestensions { - extern bool AllPlayersHaveNE(); - extern bool AllPlayersHaveME(); - extern bool AllPlayersHaveChroma(); -} \ No newline at end of file +extern ModInfo modInfo; \ No newline at end of file From 420e0abb5479af0dff923111137f6c733910c736 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 22 Apr 2022 00:24:17 +0200 Subject: [PATCH 27/56] Meta Icon optional --- .../src/Environments/MQEAvaterNameTag.cpp | 7 ++++-- MultiQuestensions/src/UI/LobbySetupPanel.cpp | 22 ++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 04c937c..a5a9946 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -1,4 +1,5 @@ #include "main.hpp" +#include "Config.hpp" #include "Environments/MQEAvatarNameTag.hpp" #include "Assets/Sprites.hpp" #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" @@ -131,8 +132,10 @@ namespace MultiQuestensions::Environments { SetIcon(PlayerIconSlot::Platform, Sprites::IconSteam64()); break; case Platform::OculusQuest: - SetIcon(PlayerIconSlot::Platform, Sprites::IconMeta64()); - break; + if (!config.getNoMetaZone()) { + SetIcon(PlayerIconSlot::Platform, Sprites::IconMeta64()); + break; + } case Platform::OculusPC: SetIcon(PlayerIconSlot::Platform, Sprites::IconOculus64()); break; diff --git a/MultiQuestensions/src/UI/LobbySetupPanel.cpp b/MultiQuestensions/src/UI/LobbySetupPanel.cpp index c9defbc..a45c396 100644 --- a/MultiQuestensions/src/UI/LobbySetupPanel.cpp +++ b/MultiQuestensions/src/UI/LobbySetupPanel.cpp @@ -20,10 +20,9 @@ namespace MultiQuestensions::UI { UnityEngine::UI::Toggle* LobbySetupPanel::lagReducerToggle; bool LobbySetupPanel::needRefresh; - void SetLagReducer(bool value) { - - getConfig().config["LagReducer"].SetBool(value); - getConfig().Write(); + void SetNoMetaZone(bool value) { + config.setNoMetaZone(value); + UpdateNameTagIcons(); } void LobbySetupPanel::AddSetupPanel(UnityEngine::RectTransform* parent, GlobalNamespace::MultiplayerSessionManager* sessionManager) { @@ -69,10 +68,16 @@ namespace MultiQuestensions::UI { //QuestUI::BeatSaberUI::CreateText(vertical4->get_transform(), "THESE TOGGLES ARE JUST\r\nPLACEHOLDERS!"); - lagReducerToggle = QuestUI::BeatSaberUI::CreateToggle(vertical4->get_transform(), "Lag Reducer", getConfig().config["LagReducer"].GetBool(), SetLagReducer); + lagReducerToggle = QuestUI::BeatSaberUI::CreateToggle(vertical4->get_transform(), "Lag Reducer", config.getLagReducer(), [](bool value) { config.setLagReducer(value); }); QuestUI::BeatSaberUI::AddHoverHint(lagReducerToggle->get_gameObject(), "Makes Multiplayer easier for the Quest to handle."); + // lagReducerToggle->set_interactable(false); + // QuestUI::BeatSaberUI::AddHoverHint(lagReducerToggle->get_gameObject(), "Currently Broken."); + + auto noMetaToggle = QuestUI::BeatSaberUI::CreateToggle(vertical4->get_transform(), "No Meta Icons", config.getNoMetaZone(), SetNoMetaZone); + QuestUI::BeatSaberUI::AddHoverHint(noMetaToggle->get_gameObject(), "Shows the Oculus Icon for Quest Players instead."); + - UnityEngine::Color playerColor = config.PlayerColor; + UnityEngine::Color playerColor = config.getPlayerColor(); // UnityEngine::ColorUtility::TryParseHtmlString(getConfig().config["color"].GetString(), playerColor); //QuestUI::BeatSaberUI::CreateColorPickerModal(parent->get_transform(), "Player Color Selection", playerColor); @@ -80,8 +85,9 @@ namespace MultiQuestensions::UI { auto colorPicker = QuestUI::BeatSaberUI::CreateColorPickerModal(parent, "Player Color Selection", playerColor, [&playerColor, sessionManager](UnityEngine::Color value) { playerColor = value; - config.PlayerColor = value; - // getConfig().config["color"].SetString(UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(value), getConfig().config.GetAllocator()); + config.setPlayerColor(value); + // config.PlayerColor = value; + // getConfig().config["PlayerColor"].SetString(UnityEngine::ColorUtility::ToHtmlStringRGB_CPP(value), getConfig().config.GetAllocator()); // getConfig().Write(); // localExtendedPlayer->playerColor = value; localMpexPlayerData->Color = value; From 0eb02b086e7ebbd4997506d74732c17989890973 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 22 Apr 2022 00:24:28 +0200 Subject: [PATCH 28/56] Change config usages --- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 67 +++++++------------ .../SessionManagerAndMpexPlayerHooks.cpp | 58 +--------------- 2 files changed, 24 insertions(+), 101 deletions(-) diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index 909961b..3613e3f 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -120,7 +120,7 @@ namespace MultiQuestensions { { SetAllPlayerPlaceColors(Color::get_black(), true); getLogger().debug("SetDefaultPlayerPlaceColors set local player color"); - SetPlayerPlaceColor(sessionManager->get_localPlayer(), config.PlayerColor, true); + SetPlayerPlaceColor(sessionManager->get_localPlayer(), config.getPlayerColor(), true); using System::Collections::Generic::List_1; for (int i = 0; i < reinterpret_cast*>(sessionManager->get_connectedPlayers())->get_Count(); i++) { auto player = sessionManager->get_connectedPlayers()->get_Item(i); @@ -211,45 +211,6 @@ namespace MultiQuestensions { else return nullptr; } - // void CreateOrUpdateNameTag(IConnectedPlayer* player) - // { - // try { - // //getLogger().debug("Start CreateOrUpdateNameTag: GetAvatarCaptionObject"); - // //Il2CppString* userId; - // //if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) - // // getLogger().debug("CreateOrUpdateNameTag ExtendedPlayer"); - - // //else if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) getLogger().debug("CreateOrUpdateNameTag SimplePlayer"); - // //else { - // // getLogger().debug("CreateOrUpdateNameTag unknown type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - // // return; - // //} - // //getLogger().debug("CreateOrUpdateNameTag player type: %s", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - - // // if (!(il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass) || il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass))) { - // // getLogger().error("REPORT TO ENDER: CreateOrUpdateNameTag unknown type: %s, this shouldn't happen!!!", il2cpp_utils::ClassStandardName(reinterpret_cast(player)->klass).c_str()); - // // return; - // // } - - // auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()/*userId*/); - // if (objAvatarCaption == nullptr) - // return; - - // //getLogger().debug("Found GetAvatarCaptionObject"); - // LobbyAvatarNameTag* nameTag; - // if (!objAvatarCaption->TryGetComponent(byref(nameTag))) { - // //getLogger().debug("Adding new LobbyAvatarNameTag Component"); - // nameTag = objAvatarCaption->AddComponent(); - // } - - // //getLogger().debug("SetPlayerInfo"); - // nameTag->SetPlayerInfo(player); - // } - // catch (const std::runtime_error& e) { - // getLogger().error("REPORT TO ENDER: CreateOrUpdateNameTag Failed: %s", e.what()); - // } - // } - void HandleLobbyAvatarCreated(IConnectedPlayer* player) { auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()); if (objAvatarCaption == nullptr) @@ -262,11 +223,29 @@ namespace MultiQuestensions { nameTag = objAvatarCaption->AddComponent(); } nameTag->SetPlayerInfo(player); + } - //const std::string userId = player->get_userId(); - // if (_extendedPlayers.contains(player->get_userId())) - // player = reinterpret_cast(_extendedPlayers.at(player->get_userId())->get_self()); - // CreateOrUpdateNameTag(player); + void UpdateNameTagIcons() { + getLogger().debug("Start UpdateNameTagIcons"); + for (int i = 0; i < MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Count(); i++) { + auto player = MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Item(i); + auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()); + if (objAvatarCaption == nullptr) { + getLogger().debug("UpdateNameTagIcons: objAvatarCaption is nullptr"); + continue; + } + + //getLogger().debug("Found GetAvatarCaptionObject"); + MQEAvatarNameTag* nameTag; + if (objAvatarCaption->TryGetComponent(byref(nameTag))) { + MultiplayerCore::Players::MpPlayerData* mpPlayerData; + if (MultiplayerCore::Players::MpPlayerManager::TryGetPlayer(player->get_userId(), mpPlayerData)) { + nameTag->SetPlatformData(mpPlayerData); + } else { + getLogger().debug("UpdateNameTagIcons: mpPlayerData is nullptr"); + } + } + } } MAKE_HOOK_MATCH(MultiplayerLobbyAvatarManager_AddPlayer, &MultiplayerLobbyAvatarManager::AddPlayer, void, MultiplayerLobbyAvatarManager* self, IConnectedPlayer* connectedPlayer) { diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index f3b153c..19e112a 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -66,62 +66,6 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl SetPlayerPlaceColor(player, packet->Color, true); getLogger().info("Calling event 'PlayerConnected'"); MultiQuestensions::Players::MpexPlayerManager::PlayerConnected(player, packet); - // CreateOrUpdateNameTag(player); - - //if (extendedPlayers->ContainsKey(player->get_userId())) { - // if (_mpexPlayerData.contains(userId)) { - // SafePtr extendedPlayer = _mpexPlayerData.at(userId); - // //Extensions::ExtendedPlayer* extendedPlayer = extendedPlayers->get_Item(player->get_userId()); - // // extendedPlayer->_connectedPlayer = player; - // // extendedPlayer->platformID = packet->platformID; - // // extendedPlayer->platform = packet->platform; - // // extendedPlayer->playerColor = packet->playerColor; - // // extendedPlayer->mpexVersion = packet->mpexVersion; - - // // Updates Color and NameTag - // SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); - // CreateOrUpdateNameTag(reinterpret_cast(extendedPlayer->get_self())); - // } - // else { - // getLogger().info("Received 'ExtendedPlayerPacket' from '%s' with platformID: '%s' mpexVersion: '%s'", - // std::string(player->get_userId()).c_str(), - // std::string(packet->platformID).c_str(), - // std::string(packet->mpexVersion).c_str() - // ); - // Extensions::ExtendedPlayer* extendedPlayer; - // try { - // extendedPlayer = Extensions::ExtendedPlayer::CS_ctor(player, packet->platformID, packet->platform, packet->mpexVersion, packet->playerColor); - // if (std::string(extendedPlayer->mpexVersion) != MPEX_PROTOCOL) - // { - // getLogger().warning( - // "###################################################################\r\n" - // "Different MultiplayerExtensions protocol detected!\r\n" - // "The player '%s' is using MpEx protocol version %s while you are using MpEx protocol " MPEX_PROTOCOL "\r\n" - // "For best compatibility all players should use a compatible version of MultiplayerExtensions/MultiQuestensions.\r\n" - // "###################################################################", - // std::string(player->get_userName()).c_str(), - // std::string(extendedPlayer->mpexVersion).c_str() - // ); - // } - // } - // catch (const std::runtime_error& e) { - // getLogger().error("REPORT TO ENDER: Exception while trying to create ExtendedPlayer: %s", e.what()); - // } - // if (extendedPlayer) { - // _extendedPlayers.emplace(userId, extendedPlayer); - // //extendedPlayers->Add(player->get_userId(), extendedPlayer); - // //if (!extendedPlayersSPTR) extendedPlayersSPTR = extendedPlayers; - - // //getLogger().debug("SetPlayerPlaceColor"); - // SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); - // //getLogger().debug("CreateOrUpdateNameTag"); - // // This packet is usually received before the avatar is actually created - // CreateOrUpdateNameTag(reinterpret_cast(extendedPlayer->get_self())); - // getLogger().debug("ExtendedPlayerPacket done"); - - // //extendedPlayerConnectedEvent::Invoke(extendedPlayer); - // } - // } } void HandlePlayerConnected(IConnectedPlayer* player) { @@ -169,7 +113,7 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe // localExtendedPlayer = Extensions::ExtendedPlayer::CS_ctor(self->get_localPlayer()); //localExtendedPlayerSPTR = localExtendedPlayer; - localMpexPlayerData->Color = config.PlayerColor; + localMpexPlayerData->Color = config.getPlayerColor(); // if (!UnityEngine::ColorUtility::TryParseHtmlString(il2cpp_utils::newcsstr(getConfig().config["color"].GetString()), localExtendedPlayer->playerColor)) // localExtendedPlayer->playerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f, 1.0f); From bc3c61468e5f46f9496b115a15e173287e5e20fb Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 22 Apr 2022 00:24:55 +0200 Subject: [PATCH 29/56] Potential LagReducer fix --- .../src/Hooks/InstallerHooks.cpp | 95 +++++++++++-------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/MultiQuestensions/src/Hooks/InstallerHooks.cpp b/MultiQuestensions/src/Hooks/InstallerHooks.cpp index 35abc44..7e474ab 100644 --- a/MultiQuestensions/src/Hooks/InstallerHooks.cpp +++ b/MultiQuestensions/src/Hooks/InstallerHooks.cpp @@ -1,54 +1,69 @@ #include "main.hpp" #include "Hooks/Hooks.hpp" -#include "GlobalNamespace/MultiplayerConnectedPlayerInstaller.hpp" -#include "GlobalNamespace/GameplayCoreSceneSetupData.hpp" -#include "GlobalNamespace/GameplayModifiers.hpp" -#include "GlobalNamespace/IDifficultyBeatmap.hpp" -#include "GlobalNamespace/PlayerSpecificSettings.hpp" -#include "GlobalNamespace/PracticeSettings.hpp" -#include "GlobalNamespace/EnvironmentInfoSO.hpp" -#include "GlobalNamespace/ColorScheme.hpp" -#include "GlobalNamespace/MainSettingsModelSO.hpp" +// #include "GlobalNamespace/MultiplayerConnectedPlayerInstaller.hpp" +// #include "GlobalNamespace/GameplayCoreSceneSetupData.hpp" +// #include "GlobalNamespace/GameplayModifiers.hpp" +// #include "GlobalNamespace/IDifficultyBeatmap.hpp" +// #include "GlobalNamespace/PlayerSpecificSettings.hpp" +// #include "GlobalNamespace/PracticeSettings.hpp" +// #include "GlobalNamespace/EnvironmentInfoSO.hpp" +// #include "GlobalNamespace/ColorScheme.hpp" +// #include "GlobalNamespace/MainSettingsModelSO.hpp" +#include "GlobalNamespace/MultiplayerConnectedPlayerBeatmapObjectEventManager.hpp" #include "Config.hpp" using namespace GlobalNamespace; namespace MultiQuestensions { - MAKE_HOOK_MATCH(MultiplayerConnectedPlayerInstaller_InstallBindings, &MultiplayerConnectedPlayerInstaller::InstallBindings, void, MultiplayerConnectedPlayerInstaller* self) { - self->dyn__sceneSetupData() = GameplayCoreSceneSetupData::New_ctor( - self->dyn__sceneSetupData()->dyn_difficultyBeatmap(), - self->dyn__sceneSetupData()->dyn_previewBeatmapLevel(), - self->dyn__sceneSetupData()->dyn_gameplayModifiers()->CopyWith( - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(), - System::Nullable_1(self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() || config.LagReducer, true), - System::Nullable_1() - //zenMode: Plugin.Config.LagReducer - ), - self->dyn__sceneSetupData()->dyn_playerSpecificSettings(), - self->dyn__sceneSetupData()->dyn_practiceSettings(), - self->dyn__sceneSetupData()->dyn_useTestNoteCutSoundEffects(), - self->dyn__sceneSetupData()->dyn_environmentInfo(), - self->dyn__sceneSetupData()->dyn_colorScheme(), - self->dyn__sceneSetupData()->dyn_mainSettingsModel() - ); + // MAKE_HOOK_MATCH(MultiplayerConnectedPlayerInstaller_InstallBindings, &MultiplayerConnectedPlayerInstaller::InstallBindings, void, MultiplayerConnectedPlayerInstaller* self) { + // // getLogger().debug("MultiplayerConnectedPlayerInstaller_InstallBindings"); + // // getLogger().debug("LagReducer: '%s'", config.getLagReducer() ? "true" : "false"); + // // getLogger().debug("ZenMode: '%s'", self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() ? "true" : "false"); + + // self->dyn__sceneSetupData() = GameplayCoreSceneSetupData::New_ctor( + // self->dyn__sceneSetupData()->dyn_difficultyBeatmap(), + // self->dyn__sceneSetupData()->dyn_previewBeatmapLevel(), + // self->dyn__sceneSetupData()->dyn_gameplayModifiers()->CopyWith( + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(), + // System::Nullable_1(self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() || config.getLagReducer(), true), + // System::Nullable_1() + // //zenMode: Plugin.Config.LagReducer + // ), + // self->dyn__sceneSetupData()->dyn_playerSpecificSettings(), + // self->dyn__sceneSetupData()->dyn_practiceSettings(), + // self->dyn__sceneSetupData()->dyn_useTestNoteCutSoundEffects(), + // self->dyn__sceneSetupData()->dyn_environmentInfo(), + // self->dyn__sceneSetupData()->dyn_colorScheme(), + // self->dyn__sceneSetupData()->dyn_mainSettingsModel() + // ); - MultiplayerConnectedPlayerInstaller_InstallBindings(self); + // // getLogger().debug("ZenMode New Value: '%s'", self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() ? "true" : "false"); + + // MultiplayerConnectedPlayerInstaller_InstallBindings(self); + // } + + MAKE_HOOK_MATCH(MultiplayerConnectedPlayerBeatmapObjectEventManager_Start, &MultiplayerConnectedPlayerBeatmapObjectEventManager::Start, void, MultiplayerConnectedPlayerBeatmapObjectEventManager* self) { + // getLogger().debug("MultiplayerConnectedPlayerBeatmapObjectEventManager_Start"); + // getLogger().debug("ZenMode: '%s'", self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() ? "true" : "false"); + if (!config.getLagReducer()) + MultiplayerConnectedPlayerBeatmapObjectEventManager_Start(self); } void Hooks::InstallerHooks() { - INSTALL_HOOK(getLogger(), MultiplayerConnectedPlayerInstaller_InstallBindings); + INSTALL_HOOK(getLogger(), MultiplayerConnectedPlayerBeatmapObjectEventManager_Start); + // INSTALL_HOOK(getLogger(), MultiplayerConnectedPlayerInstaller_InstallBindings); } } \ No newline at end of file From 75da86815ee2ea8d8dbbb0b75a0cf29646847d1b Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 25 Apr 2022 17:59:52 +0200 Subject: [PATCH 30/56] Move Spectator warning down --- MultiQuestensions/include/UI/LobbySetupPanel.hpp | 3 ++- MultiQuestensions/src/UI/LobbySetupPanel.cpp | 4 +++- MultiQuestensions/src/main.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/MultiQuestensions/include/UI/LobbySetupPanel.hpp b/MultiQuestensions/include/UI/LobbySetupPanel.hpp index bbe1338..e9a46a7 100644 --- a/MultiQuestensions/include/UI/LobbySetupPanel.hpp +++ b/MultiQuestensions/include/UI/LobbySetupPanel.hpp @@ -3,6 +3,7 @@ #include "HMUI/CurvedTextMeshPro.hpp" #include "UnityEngine/UI/Toggle.hpp" #include "UnityEngine/RectTransform.hpp" +#include "GlobalNamespace/LobbySetupViewController.hpp" namespace MultiQuestensions::UI { class LobbySetupPanel { @@ -14,7 +15,7 @@ namespace MultiQuestensions::UI { static bool needRefresh; public: - static void AddSetupPanel(UnityEngine::RectTransform* parent, GlobalNamespace::MultiplayerSessionManager* sessionManager); + static void AddSetupPanel(UnityEngine::RectTransform* parent, GlobalNamespace::MultiplayerSessionManager* sessionManager, GlobalNamespace::LobbySetupViewController* lobbySetupViewController); }; //void SetCustomSongs(bool value); } \ No newline at end of file diff --git a/MultiQuestensions/src/UI/LobbySetupPanel.cpp b/MultiQuestensions/src/UI/LobbySetupPanel.cpp index a45c396..30a96c7 100644 --- a/MultiQuestensions/src/UI/LobbySetupPanel.cpp +++ b/MultiQuestensions/src/UI/LobbySetupPanel.cpp @@ -25,7 +25,7 @@ namespace MultiQuestensions::UI { UpdateNameTagIcons(); } - void LobbySetupPanel::AddSetupPanel(UnityEngine::RectTransform* parent, GlobalNamespace::MultiplayerSessionManager* sessionManager) { + void LobbySetupPanel::AddSetupPanel(UnityEngine::RectTransform* parent, GlobalNamespace::MultiplayerSessionManager* sessionManager, GlobalNamespace::LobbySetupViewController* lobbySetupViewController) { auto vertical = QuestUI::BeatSaberUI::CreateVerticalLayoutGroup(parent); auto horizontal = QuestUI::BeatSaberUI::CreateHorizontalLayoutGroup(vertical->get_transform()); @@ -153,6 +153,8 @@ namespace MultiQuestensions::UI { ); QuestUI::BeatSaberUI::AddHoverHint(colorPickerButton->get_gameObject(), "Lets you pick your own personal platform and Name Tag color for everyone to see."); + lobbySetupViewController->dyn__spectatorWarningTextWrapper()->get_transform()->SetParent(parent->get_transform()); + lobbySetupViewController->dyn__spectatorWarningTextWrapper()->get_transform()->set_localPosition({ 0, -20, 0 }); //customSongsToggle = QuestUI::BeatSaberUI::CreateToggle(vertical2->get_transform(), "Custom Songs", getConfig().config["customsongs"].GetBool(), SetCustomSongs); //QuestUI::BeatSaberUI::AddHoverHint(customSongsToggle->get_gameObject(), "Toggles custom songs for all players"); } diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 1e53b22..dd35843 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -85,7 +85,7 @@ MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController: lobbySetupView = self; LobbySetupViewController_DidActivate(self, firstActivation, addedToHierarchy, screenSystemEnabling); if (firstActivation) { - MultiQuestensions::UI::LobbySetupPanel::AddSetupPanel(self->get_rectTransform(), sessionManager); + MultiQuestensions::UI::LobbySetupPanel::AddSetupPanel(self->get_rectTransform(), sessionManager, self); } } From 6bce0ae8d74fb2cafcf15a861c9555ba0868a794 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 25 Apr 2022 18:01:09 +0200 Subject: [PATCH 31/56] Use MpCore events instead of delegates --- .../src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 19e112a..e5a443f 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -92,10 +92,10 @@ void HandlePlayerConnected(IConnectedPlayer* player) { void HandlePlayerDisconnected(IConnectedPlayer* player) { getLogger().info("Reseting platform lights for Player '%s'", std::string(player->get_userId()).c_str()); SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); - _mpexPlayerData.erase(std::string(player->get_userId()).c_str()); + _mpexPlayerData.erase(static_cast(player->get_userId()).c_str()); } -// void HandleDisconnect(DisconnectedReason* reason) { +// void HandleDisconnect(DisconnectedReason reason) { // } @@ -129,8 +129,6 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe // } // ); // reinterpret_cast(UserInfoTask)->ContinueWith(action); - - self->SetLocalPlayerState("modded", true); //} //catch (const std::runtime_error& e) { @@ -139,8 +137,12 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); - self->add_playerConnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerConnected)); - self->add_playerDisconnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerDisconnected)); + MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += HandlePlayerConnected; + MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += HandlePlayerDisconnected; + // MultiplayerCore::Players::MpPlayerManager::disconnectedEvent += HandleDisconnect; + + // self->add_playerConnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerConnected)); + // self->add_playerDisconnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerDisconnected)); // self->add_disconnectedEvent(il2cpp_utils::MakeDelegate*>*>(classof(System::Action_1*>*), static_cast(nullptr), HandleDisconnect)); } From 9246c8751ef0fcf6b1ab2edc7a56077019009618 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 25 Apr 2022 20:36:11 +0200 Subject: [PATCH 32/56] Increase spacing to allow more icons --- MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index a5a9946..28bac36 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -55,7 +55,7 @@ namespace MultiQuestensions::Environments { hLayout->set_childForceExpandHeight(false); hLayout->set_childScaleWidth(false); hLayout->set_childScaleHeight(false); - hLayout->set_spacing(4); + hLayout->set_spacing(8); } // Re-nest name onto bg @@ -63,7 +63,7 @@ namespace MultiQuestensions::Environments { // Take control of name tag ConnectedPlayerName* nativeNameScript; - if (_nameText->TryGetComponent(ByRef(nativeNameScript))) + if (_nameText->TryGetComponent(byref(nativeNameScript))) Object::Destroy(nativeNameScript); _nameText->set_text(Player()); From 1e166ab6341bf2f36cf9336617adbfdc04335bca Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 9 May 2022 21:56:54 +0100 Subject: [PATCH 33/56] Fixed random freezes bug --- MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp index 5510e8f..bc7fdb7 100644 --- a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp +++ b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp @@ -56,7 +56,7 @@ namespace MultiQuestensions::Environments { return Color(a.r + (b.r - a.r) * t_clamp, a.g + (b.g - a.g) * t_clamp, a.b + (b.b - a.b) * t_clamp, a.a + (b.a - a.a) * t_clamp); } - void MQEAvatarPlaceLighting::Update() { + void MQEAvatarPlaceLighting::FixedUpdate() { Color current = GetColor(); if (current == targetColor) From 94af4852322be40bfdb952e786121c67648d04ea Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 9 May 2022 21:58:35 +0100 Subject: [PATCH 34/56] Remembering this --- .../include/Environments/MQEAvatarPlaceLighting.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp index 244c900..4de9d5e 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp @@ -20,7 +20,7 @@ DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarPlaceLighting, U // DECLARE_INSTANCE_METHOD(void, Awake); DECLARE_INSTANCE_METHOD(void, OnEnable); DECLARE_INSTANCE_METHOD(void, OnDisable); - DECLARE_INSTANCE_METHOD(void, Update); + DECLARE_INSTANCE_METHOD(void, FixedUpdate); DECLARE_INSTANCE_METHOD(UnityEngine::Color, GetColor); DECLARE_INSTANCE_METHOD(bool, IsColorVeryCloseToColor, UnityEngine::Color color0, UnityEngine::Color color1); From 7e6524a2c463734bce58c378fb53c2516eae3227 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 9 May 2022 21:54:13 +0100 Subject: [PATCH 35/56] Add .gitattributes. --- .gitattributes | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain From 1e12f042b147993a2e7996b85d465e0a0bbd3d38 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 9 May 2022 21:54:18 +0100 Subject: [PATCH 36/56] Add project files. --- .vscode/settings.json | 3 ++- MultiQuestensions/mod.json | 2 +- MultiQuestensions/src/Assets/Sprites.cpp | 9 +++++++++ .../src/Environments/MQEAvatarPlaceLighting.cpp | 14 ++++++++++++++ .../src/Environments/MQEAvaterNameTag.cpp | 15 +++++++++++---- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 15 +++++++++------ MultiQuestensions/src/Hooks/InstallerHooks.cpp | 2 +- .../Hooks/SessionManagerAndMpexPlayerHooks.cpp | 10 ++++++---- MultiQuestensions/src/main.cpp | 4 ++++ 9 files changed, 57 insertions(+), 17 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 22d790a..bd82047 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "cmake.sourceDirectory": "${workspaceFolder}/MultiQuestensions" + "cmake.sourceDirectory": "${workspaceFolder}/MultiQuestensions", + "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/MultiQuestensions/mod.json b/MultiQuestensions/mod.json index ad23443..a0918c6 100644 --- a/MultiQuestensions/mod.json +++ b/MultiQuestensions/mod.json @@ -3,7 +3,7 @@ "name": "MultiQuestensions", "id": "MultiQuestensions", "author": "EnderdracheLP and Goobie", - "version": "1.0.0-Dev", + "version": "1.0.0", "packageId": "com.beatgames.beatsaber", "packageVersion": "1.21.0", "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", diff --git a/MultiQuestensions/src/Assets/Sprites.cpp b/MultiQuestensions/src/Assets/Sprites.cpp index 4213743..e1b34ca 100644 --- a/MultiQuestensions/src/Assets/Sprites.cpp +++ b/MultiQuestensions/src/Assets/Sprites.cpp @@ -11,6 +11,11 @@ using namespace QuestUI::BeatSaberUI; namespace MultiQuestensions { + Logger& getLogger() { + static Logger* myLogger = new Logger(modInfo, LoggerOptions(false, true)); + return *myLogger; + } + std::string Sprites::Oculus64 = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAAHdbkFIAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAN1sAADdbAZmDAsYAAATaSURBVGhD7ZrNq1ZFHMefey21yDSxNyIKKtEyfIEgWgkhIaUFERFKK1GQJHvHZatCFymE/0ALk9zUImpViwiM3l8X1yRSVCKvZaWm5u3znfnd6zNz3u9zjtxb84EvvzNn3ufMnDMvpzcwQ2Z7Y2NjMzHb0AU0PDQ09LLuO/B8E+UxYzyA+M45DLun1JxjkXeHOM8pQH87PIm5xbt6H9AOH+nCBSgqMYF8AnkBxu/VS+G/BHU9rwrX4GmLchHzcNitDHjN8iEcR3Vv2PlE4LkKLYyF1x4fwuESCCDQalSJBU9MGTLDiae0CPMoivvIn2gPI/CYd3omEiDi1Zjfvauc/nHcn0CjDhK8DIi7VgkYG+12BvyO+iBRZrh3+9vlpcD7Jh/qYjhXDNzXY8Yb5zy6y18GXIYmPgBBFQSJXHBJ1+NrixaCx1/ev5RPLHgikaiCATOMXkHnNHoG4DN0pyVbDYFnokOK2QGaxgUELyQCOOMcWc6hA/6yFMWfg252riyv8x7cYtchFGC7K2fIIfNuDHHv90kEnDVvR/zdy853er1riTTXrpuy1mw/Z8w6wm8CkNlpzGzv6oRlPIKv7Do7O8TzCszz3tUqo2hef+aV0Bqz0TNoBDXlLNqHVlhyiUQikUjkkvkcx/AxuQFzO7oHaRns9/Py0ddVy8PDaD86yNcvmIDUhowXI00oB0HbT6+i3E2hQoiwRbFbRAVR61VDwPUuSvscRtrkDYhnxdrQ1TPsin30icfs2hEXYCcmux3oUcc6iao6rqbld6DLnSsLZShIggIcQTHHUONJKnE2uNhZHrEgWfDUPC5mlXk3hrg/+yQCdpi3Ix4e2sqJ+cHsZPjDbD9XmXXEBdCGXMxLZhtBTTXsbvOugBGzjrgTfo5Z7l0B7yCdkdQdIVoXvofyWvRGOuHEjmNcgLsx+Ztg7fA3mQcdOngEeH6D6aoAGp55rRtCK8xFx1HbNFvuEWG/jzcw2r5cbck2g4gr0Fso7/1QxQH0LOpypZ1IJBKJRCKRSCSmMVXbLIWw0NCpmn4TWYnuQ8uQVsN5K+E20cpch6g6dfsYfYi+ZT2rY8buoeIPoU/RKTRVUFlUpjVWzHYhYS3UX0BdLNbbZhS9iOZZ8UupHAIktBizFy1Bkx4ylxhtwehvrccZGt+7OwWUVojKL8Vor3+WuzH90PnEvTTCF96ZpbABqLwOR95F1ZtZHr2c3ka7kbb+9JtJm+jlqjJtRg+jov3vmC/RgzTCEe+sCQ2gXxVOoirOoF2o3hlIC5DXHLQTnUZVqA7PWdQMZadHOmUItrIL+BHtoIV1enFJIC9tu2uf/6C7UY7qoGO+XMoaQJnU2Q3Xk6//b1h7KM86vU51yDt2KIduswblHRnloWOkTajzXVjlgTZannVQHfJ+4HKUvQRlXkNbddEAtfgvSK1edqrcBPVUdeXrUNOZ5i60lWHjXRFVn0Edm76BnnA3ph+av6yj8v945ySgEfQ75zqUd+A4VdHvpzpwzxyMTxoS06dnMxr0h9ouUdmeQvp9tRalQyAPEtd41CdyPXoAaaLU9QqwCL1vNNF5H2mojtDdG713GjdADA2iGdl8pMXHNehWtABdidQwg+aht7Eqegr9in5CJ9BvaJQKtz3jTCQSiUQi8b+g1/sXRmYDomhz93gAAAAASUVORK5CYII="; std::string Sprites::Steam64 = "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"; @@ -22,18 +27,22 @@ namespace MultiQuestensions { if (ImageConversion::LoadImage(texture, bytes, false)) { return Sprite::Create(texture, UnityEngine::Rect(0.0f, 0.0f, (float)texture->get_width(), (float)texture->get_height()), UnityEngine::Vector2(0, 0), 10.0f, 0u, SpriteMeshType::Tight, UnityEngine::Vector4(0.0f, 0.0f, 0.0f, 0.0f), false); } + getLogger().debug("Failed to load image texture"); return nullptr; } Sprite* Sprites::IconOculus64() { + //getLogger().debug("CreatingOculusImage"); return CreateSpriteFromBase64(Oculus64); } Sprite* Sprites::IconSteam64() { + //getLogger().debug("CreatingSteamIcon"); return CreateSpriteFromBase64(Steam64); } Sprite* Sprites::IconMeta64() { + //getLogger().debug("CreatingMetaIcon"); return CreateSpriteFromBase64(Meta64); } } \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp index bc7fdb7..fbe9276 100644 --- a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp +++ b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp @@ -9,7 +9,13 @@ DEFINE_TYPE(MultiQuestensions::Environments, MQEAvatarPlaceLighting); namespace MultiQuestensions::Environments { + Logger& getLogger() { + static Logger* myLogger = new Logger(modInfo, LoggerOptions(false, true)); + return *myLogger; + } + void MQEAvatarPlaceLighting::New() { + getLogger().debug("MQEAvatarPlaceLighting::New()"); smoothTime = 2.0f; // if (targetColor != UnityEngine::Color::get_black()) targetColor = UnityEngine::Color::get_black(); @@ -40,6 +46,7 @@ namespace MultiQuestensions::Environments { // } void MQEAvatarPlaceLighting::OnEnable() { + getLogger().debug("MQEAvatarPlaceLighting::OnEnable()"); auto lightsArr = this->GetComponentsInChildren(); for (int i = 0; i < lightsArr.Length(); i++) { this->lights.emplace_back(lightsArr.get(i)); @@ -47,16 +54,19 @@ namespace MultiQuestensions::Environments { } void MQEAvatarPlaceLighting::OnDisable() { + getLogger().debug("MQEAvatarPlaceLighting::OnDisable()"); lights.clear(); } inline static Color Lerp(Color const& a, Color const& b, float const& t) { + //getLogger().debug("Color Lerp"); float t_clamp = std::clamp(t, 0.0f, 1.0f); return Color(a.r + (b.r - a.r) * t_clamp, a.g + (b.g - a.g) * t_clamp, a.b + (b.b - a.b) * t_clamp, a.a + (b.a - a.a) * t_clamp); } void MQEAvatarPlaceLighting::FixedUpdate() { + //getLogger().debug("MQEAvatarPlaceLighting::Update()"); Color current = GetColor(); if (current == targetColor) @@ -72,6 +82,7 @@ namespace MultiQuestensions::Environments { } void MQEAvatarPlaceLighting::SetColor(const Color& color, bool immediate) { + //getLogger().debug("MQEAvatarPlaceLighting::SetColor(const Color& color, bool immediate)"); targetColor = color; if (immediate) @@ -81,6 +92,7 @@ namespace MultiQuestensions::Environments { } Color MQEAvatarPlaceLighting::GetColor() { + //getLogger().debug("MQEAvatarPlaceLighting::GetColor()"); if (lights.size() > 0) return lights[0]->get_color(); return Color::get_black(); @@ -88,10 +100,12 @@ namespace MultiQuestensions::Environments { bool MQEAvatarPlaceLighting::IsColorVeryCloseToColor(Color color0, Color color1) { + //getLogger().debug("MQEAvatarPlaceLighting::IsColorVeryCloseToColor"); return (fabs(color0.r - color1.r) < 0.002f && fabs(color0.g - color1.g) < 0.002f && fabs(color0.b - color1.b) < 0.002f && fabs(color0.a - color1.a) < 0.002f); } void MQEAvatarPlaceLighting::SetColor(const Color& color) { + //getLogger().debug("MQEAvatarPlaceLighting::SetColor(const Color& color)"); for (TubeBloomPrePassLight* light : lights) { light->set_color(color); light->Refresh(); diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 28bac36..4a23f0b 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -35,12 +35,14 @@ namespace MultiQuestensions::Environments { void MQEAvatarNameTag::New() { + //getLogger().debug("MQEAvatarNameTag::New()"); _enabled = false; _playerInfo = nullptr; _playerIcons.clear(); } void MQEAvatarNameTag::Awake() { + //getLogger().debug("MQEAvatarNameTag::Awake()"); // Get references _bg = get_transform()->Find(BG())->GetComponent(); _nameText = get_transform()->Find(Name())->GetComponent(); @@ -80,6 +82,7 @@ namespace MultiQuestensions::Environments { void MQEAvatarNameTag::OnEnable() { + //getLogger().debug("MQEAvatarNameTag::OnEnable()"); _enabled = true; // Subscribe to events @@ -93,6 +96,7 @@ namespace MultiQuestensions::Environments { void MQEAvatarNameTag::OnDisable() { + //getLogger().debug("MQEAvatarNameTag::OnDisable()"); _enabled = false; // Unsubscribe from events @@ -103,6 +107,7 @@ namespace MultiQuestensions::Environments { #pragma region Set Player Info void MQEAvatarNameTag::SetPlayerInfo(IConnectedPlayer* player) { + //getLogger().debug("MQEAvatarNameTag::SetPlayerInfo"); _playerInfo = player; if (!_enabled) @@ -125,6 +130,7 @@ namespace MultiQuestensions::Environments { } void MQEAvatarNameTag::SetPlatformData(MultiplayerCore::Players::MpPlayerData* data) { + //getLogger().debug("MQEAvatarNameTag::SetPlatformData"); using MultiplayerCore::Players::Platform; switch (data->platform) { @@ -175,6 +181,7 @@ namespace MultiQuestensions::Environments { void MQEAvatarNameTag::SetSimplePlayerInfo(IConnectedPlayer* simplePlayer) { + //getLogger().debug("SetSimplePlayerInfo"); _playerInfo = simplePlayer; if (!_enabled) @@ -189,14 +196,14 @@ namespace MultiQuestensions::Environments { using MultiplayerCore::Players::MpPlayerData; void MQEAvatarNameTag::HandlePlatformData(IConnectedPlayer* player, MpPlayerData* data) { - getLogger().debug("HandlePlatformData"); + //getLogger().debug("HandlePlatformData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) SetPlatformData(data); } using MultiQuestensions::Players::MpexPlayerData; void MQEAvatarNameTag::HandleMpexData(IConnectedPlayer* player, MpexPlayerData* data) { - getLogger().debug("HandleMpexData"); + //getLogger().debug("HandleMpexData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) _nameText->set_color(data->Color); } @@ -205,7 +212,7 @@ namespace MultiQuestensions::Environments { #pragma region Set Icons void MQEAvatarNameTag::SetIcon(PlayerIconSlot slot, Sprite* sprite) { - getLogger().debug("SetIcon Sprite %p", sprite); + //getLogger().debug("SetIcon Sprite %p", sprite); if (!_enabled) return; @@ -240,7 +247,7 @@ namespace MultiQuestensions::Environments { void MQEAvatarNameTag::RemoveIcon(PlayerIconSlot slot) { - //getLogger().debug("RemoveIcon"); + //getLogger().debug("MQEAvatarNameTag::RemoveIcon"); if (!_enabled) return; diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index 3613e3f..971e10a 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -79,8 +79,6 @@ namespace MultiQuestensions { { if (!initialized) return; - //getLogger().debug("SetPlayerPlaceColor"); - MQEAvatarPlaceLighting* place = GetConnectedPlayerPlace(player); if (place == nullptr) @@ -110,6 +108,7 @@ namespace MultiQuestensions { void SetAllPlayerPlaceColors(Color color, bool immediate = false) { + getLogger().debug("Setting all base colors"); for (MQEAvatarPlaceLighting* place : avatarPlaces) { place->SetColor(color, immediate); @@ -143,7 +142,7 @@ namespace MultiQuestensions { void HandleLobbyEnvironmentLoaded() { initialized = false; - //getLogger().debug("HandleLobbyEnvironmentLoaded Started"); + getLogger().debug("HandleLobbyEnvironmentLoaded Started"); auto nativeAvatarPlaces = Resources::FindObjectsOfTypeAll(); for (int i = 0; i < nativeAvatarPlaces.Length(); i++) { @@ -164,7 +163,7 @@ namespace MultiQuestensions { initialized = true; SetDefaultPlayerPlaceColors(); - //getLogger().debug("HandleLobbyEnvironmentLoaded Finished"); + getLogger().debug("HandleLobbyEnvironmentLoaded Finished"); } MAKE_HOOK_MATCH(MultiplayerLobbyController_ActivateMultiplayerLobby, &MultiplayerLobbyController::ActivateMultiplayerLobby, void, MultiplayerLobbyController* self) { @@ -179,6 +178,7 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(LightWithIdMonoBehaviour_RegisterLight, &LightWithIdMonoBehaviour::RegisterLight, void, LightWithIdMonoBehaviour* self) { + getLogger().debug("MQE registering light"); if (!(self && self->get_transform() && self->get_transform()->get_parent() && self->get_transform()->get_parent()->get_name()->Contains("LobbyAvatarPlace"))) LightWithIdMonoBehaviour_RegisterLight(self); } @@ -195,7 +195,7 @@ namespace MultiQuestensions { if (_refPlayerIdToAvatarMap != nullptr) { MultiplayerLobbyAvatarController* value; - //getLogger().debug("Start GetAvatarController return MultiplayerLobbyAvatarController"); + getLogger().debug("Start GetAvatarController return MultiplayerLobbyAvatarController"); return _refPlayerIdToAvatarMap->TryGetValue(userId, byref(value)) ? value : nullptr; } @@ -213,6 +213,7 @@ namespace MultiQuestensions { void HandleLobbyAvatarCreated(IConnectedPlayer* player) { auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()); + //getLogger().debug("Finding GetAvatarCaptionObject"); if (objAvatarCaption == nullptr) return; @@ -230,8 +231,9 @@ namespace MultiQuestensions { for (int i = 0; i < MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Count(); i++) { auto player = MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Item(i); auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()); + //getLogger().debug("Finding GetAvatarCaptionObject"); if (objAvatarCaption == nullptr) { - getLogger().debug("UpdateNameTagIcons: objAvatarCaption is nullptr"); + //getLogger().debug("UpdateNameTagIcons: objAvatarCaption is nullptr"); continue; } @@ -249,6 +251,7 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(MultiplayerLobbyAvatarManager_AddPlayer, &MultiplayerLobbyAvatarManager::AddPlayer, void, MultiplayerLobbyAvatarManager* self, IConnectedPlayer* connectedPlayer) { + getLogger().debug("MultiplayerLobbyAvatarManager::AddPlayer"); MultiplayerLobbyAvatarManager_AddPlayer(self, connectedPlayer); _avatarManager = self; HandleLobbyAvatarCreated(connectedPlayer); diff --git a/MultiQuestensions/src/Hooks/InstallerHooks.cpp b/MultiQuestensions/src/Hooks/InstallerHooks.cpp index 7e474ab..81bedec 100644 --- a/MultiQuestensions/src/Hooks/InstallerHooks.cpp +++ b/MultiQuestensions/src/Hooks/InstallerHooks.cpp @@ -54,7 +54,7 @@ namespace MultiQuestensions { // } MAKE_HOOK_MATCH(MultiplayerConnectedPlayerBeatmapObjectEventManager_Start, &MultiplayerConnectedPlayerBeatmapObjectEventManager::Start, void, MultiplayerConnectedPlayerBeatmapObjectEventManager* self) { - // getLogger().debug("MultiplayerConnectedPlayerBeatmapObjectEventManager_Start"); + //getLogger().debug("MultiplayerConnectedPlayerBeatmapObjectEventManager_Start, checking if lag reducer is enabled"); // getLogger().debug("ZenMode: '%s'", self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() ? "true" : "false"); if (!config.getLagReducer()) MultiplayerConnectedPlayerBeatmapObjectEventManager_Start(self); diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index e5a443f..d9e1521 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -35,21 +35,26 @@ IPlatformUserModel* platformUserModel; MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::PlayerConnected; bool MultiQuestensions::Players::MpexPlayerManager::TryGetPlayer(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { + //getLogger().debug("bool TryingToGetPlayer"); if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { player = static_cast(_mpexPlayerData.at(playerId)); return true; } + //getLogger().debug("bool player not found"); return false; } MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetPlayer(std::string playerId) { + //getLogger().debug("MpexPlayerData GetPlayer"); if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { return static_cast(_mpexPlayerData.at(playerId)); } + //getLogger().debug("player not found"); return nullptr; } static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* player) { + getLogger().debug("HandleMpexData"); const std::string userId = to_utf8(csstrtostr(player->get_userId())); if (_mpexPlayerData.contains(userId)) { @@ -90,15 +95,12 @@ void HandlePlayerConnected(IConnectedPlayer* player) { } void HandlePlayerDisconnected(IConnectedPlayer* player) { + //getLogger().debug("HandlePlayerDisconnected"); getLogger().info("Reseting platform lights for Player '%s'", std::string(player->get_userId()).c_str()); SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); _mpexPlayerData.erase(static_cast(player->get_userId()).c_str()); } -// void HandleDisconnect(DisconnectedReason reason) { - -// } - MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, MultiplayerSessionManager* self) { sessionManager = self; diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index dd35843..620e0c6 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -68,6 +68,7 @@ namespace MultiQuestensions { LobbySetupViewController* lobbySetupView; bool AllPlayersModded() { + getLogger().debug("MQE AllPlayersModded"); for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState("modded")) return false; } @@ -77,11 +78,13 @@ namespace MultiQuestensions { // LobbyPlayersDataModel Activate MAKE_HOOK_MATCH(LobbyPlayersActivate, &LobbyPlayersDataModel::Activate, void, LobbyPlayersDataModel* self) { + getLogger().debug("LobbyPlayersDataModel::Activate"); lobbyPlayersDataModel = self; LobbyPlayersActivate(lobbyPlayersDataModel); } MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController::DidActivate, void, LobbySetupViewController* self, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) { + getLogger().debug("LobbySetupViewController::DidActivate"); lobbySetupView = self; LobbySetupViewController_DidActivate(self, firstActivation, addedToHierarchy, screenSystemEnabling); if (firstActivation) { @@ -90,6 +93,7 @@ MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController: } MAKE_HOOK_MATCH(LobbyGameStateController_Activate, &LobbyGameStateController::Activate, void, LobbyGameStateController* self) { + getLogger().debug("LobbyGameStateController::Activate"); lobbyGameStateController = self; LobbyGameStateController_Activate(self); } From 5b4ef556b3ad9857d27a3793218699eaa36a06c9 Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 17 May 2022 20:25:50 +0100 Subject: [PATCH 37/56] AAAAA --- .../include/Environments/MQEAvatarNameTag.hpp | 2 +- .../Hooks/EnvironmentAndAvatarHooks.hpp | 2 - .../shared/Players/MpexPlayerManager.hpp | 3 +- .../Environments/MQEAvatarPlaceLighting.cpp | 6 +- .../src/Environments/MQEAvaterNameTag.cpp | 31 +++---- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 57 ++++++------ .../src/Hooks/InstallerHooks.cpp | 48 ----------- .../SessionManagerAndMpexPlayerHooks.cpp | 86 +++++++++---------- MultiQuestensions/src/main.cpp | 3 - 9 files changed, 89 insertions(+), 149 deletions(-) diff --git a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp index b01281e..8e7b4c7 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp @@ -1,6 +1,5 @@ #pragma once #include "custom-types/shared/macros.hpp" -// #include "Extensions/ExtendedPlayer.hpp" #include "Players/MpexPlayerData.hpp" #include "MultiplayerCore/shared/Players/MpPlayerData.hpp" #include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" @@ -38,6 +37,7 @@ DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarNameTag, UnityEn MultiplayerCore::event_handler _platformDataEventHandler; MultiplayerCore::event_handler _mpexPlayerDataEventHandler; + std::map _playerIcons; diff --git a/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp b/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp index a8f7478..0417f37 100644 --- a/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp +++ b/MultiQuestensions/include/Hooks/EnvironmentAndAvatarHooks.hpp @@ -5,8 +5,6 @@ namespace MultiQuestensions { extern void SetPlayerPlaceColor(GlobalNamespace::IConnectedPlayer* player, const UnityEngine::Color& color, bool priority); extern void UpdateNameTagIcons(); - // extern void CreateOrUpdateNameTag(GlobalNamespace::IConnectedPlayer* player); - // extern void SetPlatformData(MultiplayerCore::Players::MpPlayerData* data); } #include "GlobalNamespace/MultiplayerSessionManager.hpp" diff --git a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp index b94a592..7a84c81 100644 --- a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp +++ b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp @@ -5,7 +5,8 @@ namespace MultiQuestensions::Players { class MpexPlayerManager { public: - static MultiplayerCore::event PlayerConnected; + //static MultiplayerCore::event_handler _PlayerConnectedHandler; + static MultiplayerCore::event RecievedMpExPlayerData; static bool TryGetPlayer(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player); static MpexPlayerData* GetPlayer(std::string playerId); }; diff --git a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp index fbe9276..172c1e1 100644 --- a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp +++ b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp @@ -15,7 +15,7 @@ namespace MultiQuestensions::Environments { } void MQEAvatarPlaceLighting::New() { - getLogger().debug("MQEAvatarPlaceLighting::New()"); + //getLogger().debug("MQEAvatarPlaceLighting::New()"); smoothTime = 2.0f; // if (targetColor != UnityEngine::Color::get_black()) targetColor = UnityEngine::Color::get_black(); @@ -46,7 +46,7 @@ namespace MultiQuestensions::Environments { // } void MQEAvatarPlaceLighting::OnEnable() { - getLogger().debug("MQEAvatarPlaceLighting::OnEnable()"); + //getLogger().debug("MQEAvatarPlaceLighting::OnEnable()"); auto lightsArr = this->GetComponentsInChildren(); for (int i = 0; i < lightsArr.Length(); i++) { this->lights.emplace_back(lightsArr.get(i)); @@ -54,7 +54,7 @@ namespace MultiQuestensions::Environments { } void MQEAvatarPlaceLighting::OnDisable() { - getLogger().debug("MQEAvatarPlaceLighting::OnDisable()"); + //getLogger().debug("MQEAvatarPlaceLighting::OnDisable()"); lights.clear(); } diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 4a23f0b..95d7d55 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -18,6 +18,10 @@ using namespace HMUI; DEFINE_TYPE(MultiQuestensions::Environments, MQEAvatarNameTag); namespace MultiQuestensions::Environments { + + public MultiplayerCore::event_handler _platformDataEventHandler; + + static StringW BG() { static ConstString bg("BG"); return bg; @@ -86,8 +90,8 @@ namespace MultiQuestensions::Environments { _enabled = true; // Subscribe to events - MultiplayerCore::Players::MpPlayerManager::PlayerConnected += _platformDataEventHandler; - MultiQuestensions::Players::MpexPlayerManager::PlayerConnected += _mpexPlayerDataEventHandler; + MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData += _platformDataEventHandler; + MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData += _mpexPlayerDataEventHandler; // Set player info if (_playerInfo != nullptr) @@ -100,8 +104,8 @@ namespace MultiQuestensions::Environments { _enabled = false; // Unsubscribe from events - MultiplayerCore::Players::MpPlayerManager::PlayerConnected -= _platformDataEventHandler; - MultiQuestensions::Players::MpexPlayerManager::PlayerConnected -= _mpexPlayerDataEventHandler; + MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData -= _platformDataEventHandler; + MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData -= _mpexPlayerDataEventHandler; } #pragma region Set Player Info @@ -123,10 +127,6 @@ namespace MultiQuestensions::Environments { MultiplayerCore::Players::MpPlayerData* data; if (MultiplayerCore::Players::MpPlayerManager::TryGetPlayer(userId, data)) SetPlatformData(data); - // if (il2cpp_utils::AssignableFrom(reinterpret_cast(player)->klass)) - // SetExtendedPlayerInfo(reinterpret_cast(player)); - // else - // SetSimplePlayerInfo(player); } void MQEAvatarNameTag::SetPlatformData(MultiplayerCore::Players::MpPlayerData* data) { @@ -188,22 +188,18 @@ namespace MultiQuestensions::Environments { return; SetPlayerInfo(simplePlayer); - // _nameText->set_text(simplePlayer->get_userName()); - // _nameText->set_color(Color::get_white()); - - // RemoveIcon(PlayerIconSlot::Platform); } using MultiplayerCore::Players::MpPlayerData; - void MQEAvatarNameTag::HandlePlatformData(IConnectedPlayer* player, MpPlayerData* data) { - //getLogger().debug("HandlePlatformData"); + void MQEAvatarNameTag::HandlePlatformData(IConnectedPlayer* player, MpPlayerData* data) { + getLogger().debug("HandlePlatformData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) SetPlatformData(data); } using MultiQuestensions::Players::MpexPlayerData; void MQEAvatarNameTag::HandleMpexData(IConnectedPlayer* player, MpexPlayerData* data) { - //getLogger().debug("HandleMpexData"); + getLogger().debug("HandleMpexData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) _nameText->set_color(data->Color); } @@ -212,7 +208,7 @@ namespace MultiQuestensions::Environments { #pragma region Set Icons void MQEAvatarNameTag::SetIcon(PlayerIconSlot slot, Sprite* sprite) { - //getLogger().debug("SetIcon Sprite %p", sprite); + getLogger().debug("SetIcon Sprite %p", sprite); if (!_enabled) return; @@ -220,7 +216,7 @@ namespace MultiQuestensions::Environments { HMUI::ImageView* imageView; if (!_playerIcons.contains(slot)) { - //getLogger().debug("SetIcon, create new Icon"); + getLogger().debug("SetIcon, create new Icon"); auto iconObj = GameObject::New_ctor(string_format("MQEPlayerIcon(%d)", (int)slot).c_str()); iconObj->get_transform()->SetParent(_bg->get_transform(), false); iconObj->get_transform()->SetSiblingIndex((int)slot); @@ -248,7 +244,6 @@ namespace MultiQuestensions::Environments { void MQEAvatarNameTag::RemoveIcon(PlayerIconSlot slot) { //getLogger().debug("MQEAvatarNameTag::RemoveIcon"); - if (!_enabled) return; if (_playerIcons.contains(slot)) diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index 971e10a..2650f2b 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -60,7 +60,7 @@ namespace MultiQuestensions { #pragma region LobbyAvatarPlaceLigting MQEAvatarPlaceLighting* GetConnectedPlayerPlace(IConnectedPlayer* player) { - //getLogger().debug("GetConnectedPlayerPlace"); + //getLogger().debug("GetConnectedPlayerPlace, lighting"); int sortIndex = _lobbyStateDataModel->get_localPlayer()->get_sortIndex(); //getLogger().debug("GetConnectedPlayerPlace sortIndex %d, angleBetweenPlayersWithEvenAdjustment %f", sortIndex, angleBetweenPlayersWithEvenAdjustment); //static auto* sortIndexMethod = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(IConnectedPlayer*), "get_sortIndex", 0)); @@ -71,18 +71,22 @@ namespace MultiQuestensions { for (auto* place : avatarPlaces) { if (place->get_transform()->get_position() == playerWorldPosition && place->get_isActiveAndEnabled()) return place; } + //getLogger().debug("GetConnectedPlayerPlace, lighting is NULLptr"); return nullptr; //return Array::Find(_avatarPlaces, place => place.transform.position == playerWorldPosition && place.isActiveAndEnabled); } void SetPlayerPlaceColor(IConnectedPlayer* player, const Color& color, bool priority) { + //getLogger().debug("SetPlayerPlaceColor"); if (!initialized) return; MQEAvatarPlaceLighting* place = GetConnectedPlayerPlace(player); - if (place == nullptr) + if (place == nullptr){ + //getLogger().debug("Place was null, returning"); return; + } // getLogger().debug("SetPlayerPlaceColor player %s userId %s", static_cast(player->get_userName()).c_str(), static_cast(player->get_userId()).c_str()); @@ -91,6 +95,7 @@ namespace MultiQuestensions { // getLogger().debug("SetPlayerPlaceColor current TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); if (!priority && place->targetColor != Color::get_black() && place->targetColor != Config::DefaultPlayerColor) { + //getLogger().debug("Default color, returning"); // getLogger().debug("SetPlayerPlaceColor not priority and TargetColor check is priority '%s' check is black '%s', check is DefaultPlayerColor '%s' check full eval '%s'", !priority ? "true" : "false", place->targetColor != Color::get_black() ? "true" : "false", place->targetColor != Config::DefaultPlayerColor ? "true" : "false", (!priority && place->targetColor != Color::get_black() && place->targetColor != Config::DefaultPlayerColor) ? "true" : "false"); // getLogger().debug("SetPlayerPlaceColor TargetColor %f, %f, %f, %f", place->targetColor.r, place->targetColor.g, place->targetColor.b, place->targetColor.a); @@ -102,13 +107,13 @@ namespace MultiQuestensions { return; } - getLogger().debug("SetPlayerPlaceColor setting color"); + //getLogger().debug("SetPlayerPlaceColor setting color"); place->SetColor(color, false); } void SetAllPlayerPlaceColors(Color color, bool immediate = false) { - getLogger().debug("Setting all base colors"); + //getLogger().debug("SetAllPlayerPlaceColors"); for (MQEAvatarPlaceLighting* place : avatarPlaces) { place->SetColor(color, immediate); @@ -118,19 +123,19 @@ namespace MultiQuestensions { static void SetDefaultPlayerPlaceColors() { SetAllPlayerPlaceColors(Color::get_black(), true); - getLogger().debug("SetDefaultPlayerPlaceColors set local player color"); + //getLogger().debug("SetDefaultPlayerPlaceColors, set local player color"); SetPlayerPlaceColor(sessionManager->get_localPlayer(), config.getPlayerColor(), true); using System::Collections::Generic::List_1; for (int i = 0; i < reinterpret_cast*>(sessionManager->get_connectedPlayers())->get_Count(); i++) { auto player = sessionManager->get_connectedPlayers()->get_Item(i); std::string userId = player->get_userId(); if (userId == static_cast(sessionManager->get_localPlayer()->get_userId())) continue; - getLogger().debug("SetDefaultPlayerPlaceColors set player color for userId %s", userId.c_str()); + //getLogger().debug("SetDefaultPlayerPlaceColors, set player color for userId %s", userId.c_str()); if (_mpexPlayerData.contains(userId)) { - getLogger().debug("SetDefaultPlayerPlaceColors found MpexPlayerData setting color for player %s", userId.c_str()); + //getLogger().debug("SetDefaultPlayerPlaceColors, found MpexPlayerData setting color for player %s", userId.c_str()); SetPlayerPlaceColor(player, _mpexPlayerData.at(userId)->Color, true); } else { - getLogger().debug("SetDefaultPlayerPlaceColors did not find MpexPlayerData setting default color for player %s", userId.c_str()); + //getLogger().debug("SetDefaultPlayerPlaceColors, did not find MpexPlayerData setting default color for player %s", userId.c_str()); SetPlayerPlaceColor(player, Config::DefaultPlayerColor, true); } } @@ -142,7 +147,7 @@ namespace MultiQuestensions { void HandleLobbyEnvironmentLoaded() { initialized = false; - getLogger().debug("HandleLobbyEnvironmentLoaded Started"); + getLogger().debug("HandleLobbyEnvironmentLoaded start"); auto nativeAvatarPlaces = Resources::FindObjectsOfTypeAll(); for (int i = 0; i < nativeAvatarPlaces.Length(); i++) { @@ -167,6 +172,7 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(MultiplayerLobbyController_ActivateMultiplayerLobby, &MultiplayerLobbyController::ActivateMultiplayerLobby, void, MultiplayerLobbyController* self) { + getLogger().debug("MultiplayerLobbyController::ActivateMultiplayerLobby"); _placeManager = Resources::FindObjectsOfTypeAll()[0]; _menuEnvironmentManager = Resources::FindObjectsOfTypeAll()[0]; _stageManager = Resources::FindObjectsOfTypeAll()[0]; @@ -178,9 +184,15 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(LightWithIdMonoBehaviour_RegisterLight, &LightWithIdMonoBehaviour::RegisterLight, void, LightWithIdMonoBehaviour* self) { - getLogger().debug("MQE registering light"); - if (!(self && self->get_transform() && self->get_transform()->get_parent() && self->get_transform()->get_parent()->get_name()->Contains("LobbyAvatarPlace"))) + if ((self && self->get_transform() && self->get_transform()->get_parent() && self->get_transform()->get_parent()->get_name()->Contains("LobbyAvatarPlace"))){ + if(!self->dyn__isRegistered()){ + //getLogger().debug("MQE registering a MQEAvatarPlaceLighting or light that has the lobby avatar place as a parent"); + LightWithIdMonoBehaviour_RegisterLight(self); + } + } + else{ LightWithIdMonoBehaviour_RegisterLight(self); + } } #pragma endregion @@ -195,11 +207,11 @@ namespace MultiQuestensions { if (_refPlayerIdToAvatarMap != nullptr) { MultiplayerLobbyAvatarController* value; - getLogger().debug("Start GetAvatarController return MultiplayerLobbyAvatarController"); + //getLogger().debug("Start GetAvatarController return MultiplayerLobbyAvatarController"); return _refPlayerIdToAvatarMap->TryGetValue(userId, byref(value)) ? value : nullptr; } - //getLogger().debug("GetAvatarController return nullptr, this part should never be triggered"); + getLogger().debug("GetAvatarController return nullptr, this part should never be triggered"); return nullptr; } @@ -217,10 +229,9 @@ namespace MultiQuestensions { if (objAvatarCaption == nullptr) return; - //getLogger().debug("Found GetAvatarCaptionObject"); MQEAvatarNameTag* nameTag; if (!objAvatarCaption->TryGetComponent(byref(nameTag))) { - //getLogger().debug("Adding new LobbyAvatarNameTag Component"); + getLogger().debug("Adding new LobbyAvatarNameTag Component"); nameTag = objAvatarCaption->AddComponent(); } nameTag->SetPlayerInfo(player); @@ -231,9 +242,9 @@ namespace MultiQuestensions { for (int i = 0; i < MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Count(); i++) { auto player = MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Item(i); auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()); - //getLogger().debug("Finding GetAvatarCaptionObject"); + getLogger().debug("Finding GetAvatarCaptionObject"); if (objAvatarCaption == nullptr) { - //getLogger().debug("UpdateNameTagIcons: objAvatarCaption is nullptr"); + //getLogger().debug("GetAvatarCaptionObject is nullptr, returning"); continue; } @@ -251,25 +262,17 @@ namespace MultiQuestensions { } MAKE_HOOK_MATCH(MultiplayerLobbyAvatarManager_AddPlayer, &MultiplayerLobbyAvatarManager::AddPlayer, void, MultiplayerLobbyAvatarManager* self, IConnectedPlayer* connectedPlayer) { - getLogger().debug("MultiplayerLobbyAvatarManager::AddPlayer"); + //getLogger().debug("MultiplayerLobbyAvatarManager::AddPlayer"); MultiplayerLobbyAvatarManager_AddPlayer(self, connectedPlayer); _avatarManager = self; - HandleLobbyAvatarCreated(connectedPlayer); + HandleLobbyAvatarCreated(connectedPlayer);//TODO que this so that it is ran when the player returns to the lobby? } - // MAKE_HOOK_MATCH(AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet, &AvatarPoseRestrictions::HandleAvatarPoseControllerPositionsWillBeSet, void, AvatarPoseRestrictions* self, Quaternion headRotation, Vector3 headPosition, Vector3 leftHandPosition, Vector3 rightHandPosition, ByRef newHeadPosition, ByRef newLeftHandPosition, ByRef newRightHandPosition) { - // newHeadPosition.heldRef = headPosition; - // newLeftHandPosition.heldRef = self->LimitHandPositionRelativeToHead(leftHandPosition, headPosition); - // newRightHandPosition.heldRef = self->LimitHandPositionRelativeToHead(rightHandPosition, headPosition); - // //AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet(self, headRotation, headPosition, leftHandPosition, rightHandPosition, newHeadPosition, newLeftHandPosition, newRightHandPosition); - // } - #pragma endregion void Hooks::EnvironmentHooks() { INSTALL_HOOK(getLogger(), MultiplayerLobbyController_ActivateMultiplayerLobby); INSTALL_HOOK(getLogger(), LightWithIdMonoBehaviour_RegisterLight); INSTALL_HOOK(getLogger(), MultiplayerLobbyAvatarManager_AddPlayer); - // INSTALL_HOOK_ORIG(getLogger(), AvatarPoseRestrictions_HandleAvatarPoseControllerPositionsWillBeSet); } } \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/InstallerHooks.cpp b/MultiQuestensions/src/Hooks/InstallerHooks.cpp index 81bedec..3f4f591 100644 --- a/MultiQuestensions/src/Hooks/InstallerHooks.cpp +++ b/MultiQuestensions/src/Hooks/InstallerHooks.cpp @@ -1,57 +1,10 @@ #include "main.hpp" #include "Hooks/Hooks.hpp" -// #include "GlobalNamespace/MultiplayerConnectedPlayerInstaller.hpp" -// #include "GlobalNamespace/GameplayCoreSceneSetupData.hpp" -// #include "GlobalNamespace/GameplayModifiers.hpp" -// #include "GlobalNamespace/IDifficultyBeatmap.hpp" -// #include "GlobalNamespace/PlayerSpecificSettings.hpp" -// #include "GlobalNamespace/PracticeSettings.hpp" -// #include "GlobalNamespace/EnvironmentInfoSO.hpp" -// #include "GlobalNamespace/ColorScheme.hpp" -// #include "GlobalNamespace/MainSettingsModelSO.hpp" #include "GlobalNamespace/MultiplayerConnectedPlayerBeatmapObjectEventManager.hpp" #include "Config.hpp" using namespace GlobalNamespace; namespace MultiQuestensions { - // MAKE_HOOK_MATCH(MultiplayerConnectedPlayerInstaller_InstallBindings, &MultiplayerConnectedPlayerInstaller::InstallBindings, void, MultiplayerConnectedPlayerInstaller* self) { - // // getLogger().debug("MultiplayerConnectedPlayerInstaller_InstallBindings"); - // // getLogger().debug("LagReducer: '%s'", config.getLagReducer() ? "true" : "false"); - // // getLogger().debug("ZenMode: '%s'", self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() ? "true" : "false"); - - // self->dyn__sceneSetupData() = GameplayCoreSceneSetupData::New_ctor( - // self->dyn__sceneSetupData()->dyn_difficultyBeatmap(), - // self->dyn__sceneSetupData()->dyn_previewBeatmapLevel(), - // self->dyn__sceneSetupData()->dyn_gameplayModifiers()->CopyWith( - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(), - // System::Nullable_1(self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() || config.getLagReducer(), true), - // System::Nullable_1() - // //zenMode: Plugin.Config.LagReducer - // ), - // self->dyn__sceneSetupData()->dyn_playerSpecificSettings(), - // self->dyn__sceneSetupData()->dyn_practiceSettings(), - // self->dyn__sceneSetupData()->dyn_useTestNoteCutSoundEffects(), - // self->dyn__sceneSetupData()->dyn_environmentInfo(), - // self->dyn__sceneSetupData()->dyn_colorScheme(), - // self->dyn__sceneSetupData()->dyn_mainSettingsModel() - // ); - - // // getLogger().debug("ZenMode New Value: '%s'", self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() ? "true" : "false"); - - // MultiplayerConnectedPlayerInstaller_InstallBindings(self); - // } MAKE_HOOK_MATCH(MultiplayerConnectedPlayerBeatmapObjectEventManager_Start, &MultiplayerConnectedPlayerBeatmapObjectEventManager::Start, void, MultiplayerConnectedPlayerBeatmapObjectEventManager* self) { //getLogger().debug("MultiplayerConnectedPlayerBeatmapObjectEventManager_Start, checking if lag reducer is enabled"); @@ -63,7 +16,6 @@ namespace MultiQuestensions { void Hooks::InstallerHooks() { INSTALL_HOOK(getLogger(), MultiplayerConnectedPlayerBeatmapObjectEventManager_Start); - // INSTALL_HOOK(getLogger(), MultiplayerConnectedPlayerInstaller_InstallBindings); } } \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index d9e1521..51e4208 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -11,6 +11,8 @@ #include "UnityEngine/Resources.hpp" #include "GlobalNamespace/UserInfo.hpp" #include "GlobalNamespace/MultiplayerSessionManager_SessionType.hpp" +#include "GlobalNamespace/DisconnectedReason.hpp" + #include "CodegenExtensions/ColorUtility.hpp" @@ -19,9 +21,14 @@ #include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" #include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" + +#include "Environments/MQEAvatarNameTag.hpp" + using namespace MultiQuestensions; using namespace MultiplayerCore::Networking; using namespace GlobalNamespace; +using namespace MultiQuestensions::Environments; // std::map> _extendedPlayers; std::map> _mpexPlayerData; @@ -32,24 +39,25 @@ std::map> _mpexPlayerData; SafePtr localMpexPlayerData; IPlatformUserModel* platformUserModel; -MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::PlayerConnected; + +MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected(player)); +MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected(player)); +MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect(reason)); + +MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData; bool MultiQuestensions::Players::MpexPlayerManager::TryGetPlayer(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { - //getLogger().debug("bool TryingToGetPlayer"); if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { player = static_cast(_mpexPlayerData.at(playerId)); return true; } - //getLogger().debug("bool player not found"); return false; } MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetPlayer(std::string playerId) { - //getLogger().debug("MpexPlayerData GetPlayer"); if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { return static_cast(_mpexPlayerData.at(playerId)); } - //getLogger().debug("player not found"); return nullptr; } @@ -69,16 +77,16 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl } SetPlayerPlaceColor(player, packet->Color, true); - getLogger().info("Calling event 'PlayerConnected'"); - MultiQuestensions::Players::MpexPlayerManager::PlayerConnected(player, packet); + getLogger().info("Calling event 'RecievedMpExPlayerData'"); + MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData(player, packet); } void HandlePlayerConnected(IConnectedPlayer* player) { try { - getLogger().debug("HandlePlayerConnected"); + getLogger().debug("MQE HandlePlayerConnected"); if (player) { const std::string userId = player->get_userId(); - getLogger().info("Player '%s' joined", userId.c_str()); + getLogger().info("MQE Player '%s' joined", userId.c_str()); getLogger().debug("Sending MpexPlayerData"); if (localMpexPlayerData) { @@ -95,10 +103,22 @@ void HandlePlayerConnected(IConnectedPlayer* player) { } void HandlePlayerDisconnected(IConnectedPlayer* player) { - //getLogger().debug("HandlePlayerDisconnected"); - getLogger().info("Reseting platform lights for Player '%s'", std::string(player->get_userId()).c_str()); - SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); - _mpexPlayerData.erase(static_cast(player->get_userId()).c_str()); + if (player) { + const std::string userId = to_utf8(csstrtostr(player->get_userId())); + if (_mpexPlayerData.contains(userId)) { + getLogger().info("Reseting platform lights for Player '%s'", userId.c_str()); + SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); + _mpexPlayerData.erase(userId); + } + } +} + +void HandleDisconnect(DisconnectedReason reason) { + getLogger().info("Clearing MPEX player data"); + _mpexPlayerData.clear(); + MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; + MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent -= _PlayerDisconnectedHandler; + MultiplayerCore::Players::MpPlayerManager::disconnectedEvent -= _DisconnectedHandler; } MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, MultiplayerSessionManager* self) { @@ -109,43 +129,17 @@ MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, Mu MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSession, void, MultiplayerSessionManager* self, MultiplayerSessionManager_SessionType sessionType, ConnectedPlayerManager* connectedPlayerManager) { SessionManager_StartSession(self, sessionType, connectedPlayerManager); - getLogger().debug("MultiplayerSessionManager.StartSession, creating localMpexPlayerData"); - //try { - localMpexPlayerData = Players::MpexPlayerData::New_ctor(); - // localExtendedPlayer = Extensions::ExtendedPlayer::CS_ctor(self->get_localPlayer()); - //localExtendedPlayerSPTR = localExtendedPlayer; - - localMpexPlayerData->Color = config.getPlayerColor(); - // if (!UnityEngine::ColorUtility::TryParseHtmlString(il2cpp_utils::newcsstr(getConfig().config["color"].GetString()), localExtendedPlayer->playerColor)) - // localExtendedPlayer->playerColor = UnityEngine::Color(0.031f, 0.752f, 1.0f, 1.0f); - - // static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll().get(0); - // static auto UserInfoTask = localNetworkPlayerModel->dyn__platformUserModel()->GetUserInfo(); - // static auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function*)>)[&](System::Threading::Tasks::Task_1* userInfoTask) { - // auto userInfo = userInfoTask->get_Result(); - // if (userInfo) { - // localExtendedPlayer->platformID = userInfo->dyn_platformUserId(); - // localExtendedPlayer->platform = (Extensions::Platform)userInfo->dyn_platform().value; - // } - // else getLogger().error("Failed to get local network player!"); - // } - // ); - // reinterpret_cast(UserInfoTask)->ContinueWith(action); - - //} - //catch (const std::runtime_error& e) { - // getLogger().error("%s", e.what()); - //} + + localMpexPlayerData = Players::MpexPlayerData::New_ctor(); + localMpexPlayerData->Color = config.getPlayerColor(); MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); - MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += HandlePlayerConnected; - MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += HandlePlayerDisconnected; - // MultiplayerCore::Players::MpPlayerManager::disconnectedEvent += HandleDisconnect; - // self->add_playerConnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerConnected)); - // self->add_playerDisconnectedEvent(il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), static_cast(nullptr), HandlePlayerDisconnected)); - // self->add_disconnectedEvent(il2cpp_utils::MakeDelegate*>*>(classof(System::Action_1*>*), static_cast(nullptr), HandleDisconnect)); + + MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; + MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; + MultiplayerCore::Players::MpPlayerManager::disconnectedEvent += _DisconnectedHandler; } diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 620e0c6..859da1f 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -78,13 +78,11 @@ namespace MultiQuestensions { // LobbyPlayersDataModel Activate MAKE_HOOK_MATCH(LobbyPlayersActivate, &LobbyPlayersDataModel::Activate, void, LobbyPlayersDataModel* self) { - getLogger().debug("LobbyPlayersDataModel::Activate"); lobbyPlayersDataModel = self; LobbyPlayersActivate(lobbyPlayersDataModel); } MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController::DidActivate, void, LobbySetupViewController* self, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) { - getLogger().debug("LobbySetupViewController::DidActivate"); lobbySetupView = self; LobbySetupViewController_DidActivate(self, firstActivation, addedToHierarchy, screenSystemEnabling); if (firstActivation) { @@ -93,7 +91,6 @@ MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController: } MAKE_HOOK_MATCH(LobbyGameStateController_Activate, &LobbyGameStateController::Activate, void, LobbyGameStateController* self) { - getLogger().debug("LobbyGameStateController::Activate"); lobbyGameStateController = self; LobbyGameStateController_Activate(self); } From da283cc91c12b14561cd7b71f7a37c64721ba04a Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 17 May 2022 21:07:26 +0100 Subject: [PATCH 38/56] Fixed events --- .../Hooks/SessionManagerAndExtendedPlayerHooks.hpp | 9 ++++++++- MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp | 4 ---- .../src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 9 +++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index 9cc593e..5d64c62 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -1,5 +1,12 @@ #pragma once #include "Players/MpexPlayerData.hpp" +#include "GlobalNamespace/IConnectedPlayer.hpp" +#include "GlobalNamespace/DisconnectedReason.hpp" extern SafePtr localMpexPlayerData; -extern std::map> _mpexPlayerData; \ No newline at end of file +extern std::map> _mpexPlayerData; + + +extern void HandlePlayerConnected(GlobalNamespace::IConnectedPlayer* player); +extern void HandlePlayerDisconnected(GlobalNamespace::IConnectedPlayer* player); +extern void HandleDisconnect(GlobalNamespace::DisconnectedReason reason); diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 95d7d55..1e1b943 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -18,10 +18,6 @@ using namespace HMUI; DEFINE_TYPE(MultiQuestensions::Environments, MQEAvatarNameTag); namespace MultiQuestensions::Environments { - - public MultiplayerCore::event_handler _platformDataEventHandler; - - static StringW BG() { static ConstString bg("BG"); return bg; diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 51e4208..7ac7b11 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -40,9 +40,10 @@ SafePtr localMpexPlayerData; IPlatformUserModel* platformUserModel; -MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected(player)); -MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected(player)); -MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect(reason)); +MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerConnected); +MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected); +MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect); + MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData; @@ -113,7 +114,7 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { } } -void HandleDisconnect(DisconnectedReason reason) { +void HandleDisconnect(DisconnectedReason reason ) { getLogger().info("Clearing MPEX player data"); _mpexPlayerData.clear(); MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; From db82aba373fdeb0b2efff446a6b79622434fb19c Mon Sep 17 00:00:00 2001 From: cubic Date: Tue, 17 May 2022 21:33:52 +0100 Subject: [PATCH 39/56] backtohowitwas --- MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 1e1b943..7189ebe 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -17,7 +17,7 @@ using namespace HMUI; DEFINE_TYPE(MultiQuestensions::Environments, MQEAvatarNameTag); -namespace MultiQuestensions::Environments { +namespace MultiQuestensions::Environments { static StringW BG() { static ConstString bg("BG"); return bg; From 342bdf328fada37c8fb411ef04d7ce3fe68edf84 Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 18 May 2022 03:32:42 +0100 Subject: [PATCH 40/56] Events are now handled here and no longer in mp core --- .../include/Environments/MQEAvatarNameTag.hpp | 12 +- .../Environments/MQEAvatarPlaceLighting.hpp | 4 +- .../SessionManagerAndExtendedPlayerHooks.hpp | 3 + .../shared/Players/MpPlayerData.hpp | 32 +++ .../shared/Players/MpexPlayerManager.hpp | 25 +- MultiQuestensions/shared/Utils/event.hpp | 233 ++++++++++++++++++ .../src/Environments/MQEAvaterNameTag.cpp | 59 ++--- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 10 +- .../SessionManagerAndMpexPlayerHooks.cpp | 227 ++++++++++++++--- .../src/Players/MpPlayerData.cpp | 39 +++ 10 files changed, 546 insertions(+), 98 deletions(-) create mode 100644 MultiQuestensions/shared/Players/MpPlayerData.hpp create mode 100644 MultiQuestensions/shared/Utils/event.hpp create mode 100644 MultiQuestensions/src/Players/MpPlayerData.cpp diff --git a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp index 8e7b4c7..7fa2b26 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp @@ -1,8 +1,8 @@ #pragma once #include "custom-types/shared/macros.hpp" #include "Players/MpexPlayerData.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" +#include "Players/MpPlayerData.hpp" +#include "Players/MpexPlayerManager.hpp" #include "UnityEngine/MonoBehaviour.hpp" #include "HMUI/ImageView.hpp" #include "HMUI/CurvedTextMeshPro.hpp" @@ -24,9 +24,9 @@ DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarNameTag, UnityEn DECLARE_INSTANCE_METHOD(void, SetPlayerInfo, GlobalNamespace::IConnectedPlayer* player); // DECLARE_INSTANCE_METHOD(void, SetExtendedPlayerInfo, MultiQuestensions::Extensions::ExtendedPlayer* extendedPlayer); - DECLARE_INSTANCE_METHOD(void, SetPlatformData, MultiplayerCore::Players::MpPlayerData* data); + DECLARE_INSTANCE_METHOD(void, SetPlatformData, MultiQuestensions::Players::MpPlayerData* data); DECLARE_INSTANCE_METHOD(void, SetSimplePlayerInfo, GlobalNamespace::IConnectedPlayer* simplePlayer); - DECLARE_INSTANCE_METHOD(void, HandlePlatformData, GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data); + DECLARE_INSTANCE_METHOD(void, HandlePlatformData, GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpPlayerData* data); DECLARE_INSTANCE_METHOD(void, HandleMpexData, GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpexPlayerData* data); enum PlayerIconSlot { @@ -35,8 +35,8 @@ DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarNameTag, UnityEn bool _enabled; - MultiplayerCore::event_handler _platformDataEventHandler; - MultiplayerCore::event_handler _mpexPlayerDataEventHandler; + MultiQuestensions::event_handler _platformDataEventHandler; + MultiQuestensions::event_handler _mpexPlayerDataEventHandler; std::map _playerIcons; diff --git a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp index 4de9d5e..b43a69d 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp @@ -5,9 +5,7 @@ #include "UnityEngine/Color.hpp" #include "Players/MpexPlayerManager.hpp" - -#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" -#include "MultiplayerCore/shared/Utils/event.hpp" +#include "Utils/event.hpp" DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarPlaceLighting, UnityEngine::MonoBehaviour, std::vector lights; diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index 5d64c62..03c541e 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -1,11 +1,14 @@ #pragma once #include "Players/MpexPlayerData.hpp" +#include "Players/MpPlayerData.hpp" #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/DisconnectedReason.hpp" extern SafePtr localMpexPlayerData; extern std::map> _mpexPlayerData; +extern SafePtr localPlayer; +extern std::map> _playerData; extern void HandlePlayerConnected(GlobalNamespace::IConnectedPlayer* player); extern void HandlePlayerDisconnected(GlobalNamespace::IConnectedPlayer* player); diff --git a/MultiQuestensions/shared/Players/MpPlayerData.hpp b/MultiQuestensions/shared/Players/MpPlayerData.hpp new file mode 100644 index 0000000..892cd05 --- /dev/null +++ b/MultiQuestensions/shared/Players/MpPlayerData.hpp @@ -0,0 +1,32 @@ +#pragma once +#include "custom-types/shared/macros.hpp" +#include "GlobalNamespace/IConnectedPlayer.hpp" +#include "MultiplayerCore/shared/Networking/Abstractions/MpPacket.hpp" + +namespace MultiQuestensions::Players { +enum class Platform + { + Unknown = 0, + Steam = 1, + OculusPC = 2, + OculusQuest = 3, + PS4 = 4 + }; +} + +DECLARE_CLASS_CUSTOM_DLL(MultiQuestensions::Players, MpPlayerData, MultiplayerCore::Networking::Abstractions::MpPacket, "MultiQuestensions.Players", + + DECLARE_CTOR(New); + + // Player and platform information + DECLARE_INSTANCE_FIELD(StringW, platformId); + + DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); + DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Deserialize", 1), LiteNetLib::Utils::NetDataReader* reader); + + public: + Platform platform; + + static MpPlayerData* Init(StringW platformID, Platform platform); +) +//#undef MPDInterfaces \ No newline at end of file diff --git a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp index 7a84c81..06340be 100644 --- a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp +++ b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp @@ -1,13 +1,28 @@ #pragma once #include "MpexPlayerData.hpp" -#include "MultiplayerCore/shared/Utils/event.hpp" +#include "MpPlayerData.hpp" +#include "Utils/event.hpp" namespace MultiQuestensions::Players { class MpexPlayerManager { public: - //static MultiplayerCore::event_handler _PlayerConnectedHandler; - static MultiplayerCore::event RecievedMpExPlayerData; - static bool TryGetPlayer(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player); - static MpexPlayerData* GetPlayer(std::string playerId); + + + static bool TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player); + static MpexPlayerData* GetMpexPlayerData(std::string playerId); + + static bool TryGetMpPlayerData(std::string playerId, MultiQuestensions::Players::MpPlayerData*& player); + static MultiQuestensions::Players::MpPlayerData* GetMpPlayerData(std::string playerId); + + static event RecievedPlayerData; + static event RecievedMpExPlayerData; + + //C++ equivalent to basegame events + static event playerConnectedEvent; + static event playerDisconnectedEvent; + static event disconnectedEvent; + + + }; } \ No newline at end of file diff --git a/MultiQuestensions/shared/Utils/event.hpp b/MultiQuestensions/shared/Utils/event.hpp new file mode 100644 index 0000000..612a317 --- /dev/null +++ b/MultiQuestensions/shared/Utils/event.hpp @@ -0,0 +1,233 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +namespace MultiQuestensions { + template class event_handler + { + public: + typedef std::function handler_func_type; + typedef unsigned int handler_id_type; + + explicit event_handler(const handler_func_type& handlerFunc) + : m_handlerFunc(handlerFunc) + { + m_handlerId = ++m_handlerIdCounter; + } + + // copy constructor + event_handler(const event_handler& src) + : m_handlerFunc(src.m_handlerFunc), m_handlerId(src.m_handlerId) + { + } + + // move constructor + event_handler(event_handler&& src) + : m_handlerFunc(std::move(src.m_handlerFunc)), m_handlerId(src.m_handlerId) + { + } + + // copy assignment operator + event_handler& operator=(const event_handler& src) + { + m_handlerFunc = src.m_handlerFunc; + m_handlerId = src.m_handlerId; + + return *this; + } + + // move assignment operator + event_handler& operator=(event_handler&& src) + { + std::swap(m_handlerFunc, src.m_handlerFunc); + m_handlerId = src.m_handlerId; + + return *this; + } + + // function call operator + void operator()(Args... params) const + { + if (m_handlerFunc) + { + m_handlerFunc(params...); + } + } + + bool operator==(const event_handler& other) const + { + return m_handlerId == other.m_handlerId; + } + + operator bool() const + { + return m_handlerFunc; + } + + handler_id_type id() const + { + return m_handlerId; + } + + private: + handler_func_type m_handlerFunc; + handler_id_type m_handlerId; + static std::atomic_uint m_handlerIdCounter; + }; + + template std::atomic_uint event_handler::m_handlerIdCounter(0); + + template class event + { + public: + typedef event_handler handler_type; + + event() + { + } + + // copy constructor + event(const event& src) + { + std::lock_guard lock(src.m_handlersLocker); + + m_handlers = src.m_handlers; + } + + // move constructor + event(event&& src) + { + std::lock_guard lock(src.m_handlersLocker); + + m_handlers = std::move(src.m_handlers); + } + + // copy assignment operator + event& operator=(const event& src) + { + std::lock_guard lock(m_handlersLocker); + std::lock_guard lock2(src.m_handlersLocker); + + m_handlers = src.m_handlers; + + return *this; + } + + // move assignment operator + event& operator=(event&& src) + { + std::lock_guard lock(m_handlersLocker); + std::lock_guard lock2(src.m_handlersLocker); + + std::swap(m_handlers, src.m_handlers); + + return *this; + } + + typename handler_type::handler_id_type add(const handler_type& handler) + { + std::lock_guard lock(m_handlersLocker); + + m_handlers.push_back(handler); + + return handler.id(); + } + + inline typename handler_type::handler_id_type add(const typename handler_type::handler_func_type& handler) + { + return add(handler_type(handler)); + } + + bool remove(const handler_type& handler) + { + std::lock_guard lock(m_handlersLocker); + + auto it = std::find(m_handlers.begin(), m_handlers.end(), handler); + if (it != m_handlers.end()) + { + m_handlers.erase(it); + return true; + } + + return false; + } + + bool remove_id(const typename handler_type::handler_id_type& handlerId) + { + std::lock_guard lock(m_handlersLocker); + + auto it = std::find_if(m_handlers.begin(), m_handlers.end(), + [handlerId](const handler_type& handler) { return handler.id() == handlerId; }); + if (it != m_handlers.end()) + { + m_handlers.erase(it); + return true; + } + + return false; + } + + void call(Args... params) const + { + handler_collection_type handlersCopy = get_handlers_copy(); + + call_impl(handlersCopy, params...); + } + + std::future call_async(Args... params) const + { + return std::async(std::launch::async, [this](Args... asyncParams) { call(asyncParams...); }, params...); + } + + inline void operator()(Args... params) const + { + call(params...); + } + + inline typename handler_type::handler_id_type operator+=(const handler_type& handler) + { + return add(handler); + } + + inline typename handler_type::handler_id_type operator+=(const typename handler_type::handler_func_type& handler) + { + return add(handler); + } + + inline bool operator-=(const handler_type& handler) + { + return remove(handler); + } + + protected: + typedef std::list handler_collection_type; + + void call_impl(const handler_collection_type& handlers, Args... params) const + { + for (const auto& handler : handlers) + { + handler(params...); + } + } + + handler_collection_type get_handlers_copy() const + { + std::lock_guard lock(m_handlersLocker); + + // Since the function return value is by copy, + // before the function returns (and destruct the lock_guard object), + // it creates a copy of the m_handlers container. + + return m_handlers; + } + + private: + handler_collection_type m_handlers; + mutable std::mutex m_handlersLocker; + }; +} \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 7189ebe..baebf02 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -9,7 +9,9 @@ #include "GlobalNamespace/ConnectedPlayerName.hpp" #include "UnityEngine/Object.hpp" #include "Players/MpexPlayerManager.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" +#include "Players/MpPlayerData.hpp" +#include "Utils/event.hpp" + using namespace GlobalNamespace; using namespace UnityEngine::UI; using namespace UnityEngine; @@ -70,12 +72,12 @@ namespace MultiQuestensions::Environments { _nameText->set_text(Player()); // Create Event handlers - _platformDataEventHandler = MultiplayerCore::event_handler( - [this](GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data) { + _platformDataEventHandler = event_handler( + [this](GlobalNamespace::IConnectedPlayer* player, Players::MpPlayerData* data) { HandlePlatformData(player, data); }); - _mpexPlayerDataEventHandler = MultiplayerCore::event_handler( - [this](GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpexPlayerData* data) { + _mpexPlayerDataEventHandler = event_handler( + [this](GlobalNamespace::IConnectedPlayer* player, Players::MpexPlayerData* data) { HandleMpexData(player, data); }); } @@ -86,8 +88,8 @@ namespace MultiQuestensions::Environments { _enabled = true; // Subscribe to events - MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData += _platformDataEventHandler; - MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData += _mpexPlayerDataEventHandler; + Players::MpexPlayerManager::RecievedPlayerData += _platformDataEventHandler; + Players::MpexPlayerManager::RecievedMpExPlayerData += _mpexPlayerDataEventHandler; // Set player info if (_playerInfo != nullptr) @@ -100,8 +102,8 @@ namespace MultiQuestensions::Environments { _enabled = false; // Unsubscribe from events - MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData -= _platformDataEventHandler; - MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData -= _mpexPlayerDataEventHandler; + Players::MpexPlayerManager::RecievedPlayerData -= _platformDataEventHandler; + Players::MpexPlayerManager::RecievedMpExPlayerData -= _mpexPlayerDataEventHandler; } #pragma region Set Player Info @@ -120,14 +122,14 @@ namespace MultiQuestensions::Environments { RemoveIcon(PlayerIconSlot::Platform); - MultiplayerCore::Players::MpPlayerData* data; - if (MultiplayerCore::Players::MpPlayerManager::TryGetPlayer(userId, data)) + Players::MpPlayerData* data; + if (Players::MpexPlayerManager::TryGetMpPlayerData(userId, data)) SetPlatformData(data); } - void MQEAvatarNameTag::SetPlatformData(MultiplayerCore::Players::MpPlayerData* data) { + void MQEAvatarNameTag::SetPlatformData(Players::MpPlayerData* data) { //getLogger().debug("MQEAvatarNameTag::SetPlatformData"); - using MultiplayerCore::Players::Platform; + using Players::Platform; switch (data->platform) { case Platform::Steam: @@ -148,33 +150,6 @@ namespace MultiQuestensions::Environments { } } - // void LobbyAvatarNameTag::SetExtendedPlayerInfo(ExtendedPlayer* extendedPlayer) - // { - // _playerInfo = reinterpret_cast(extendedPlayer); - - // if (!_enabled) - // return; - - // _nameText->set_text(extendedPlayer->get_userName()); - // _nameText->set_color(extendedPlayer->get_playerColor()); - - // //getLogger().debug("SetExtendedPlayerInfo platform: %d", (int)extendedPlayer->get_platform()); - - // switch (extendedPlayer->get_platform()) - // { - // case Extensions::Platform::Steam: - // SetIcon(PlayerIconSlot::Platform, Sprites::IconSteam64()); - // break; - // case Extensions::Platform::OculusQuest: - // case Extensions::Platform::OculusPC: - // SetIcon(PlayerIconSlot::Platform, Sprites::IconOculus64()); - // break; - // default: - // RemoveIcon(PlayerIconSlot::Platform); - // break; - // } - // } - void MQEAvatarNameTag::SetSimplePlayerInfo(IConnectedPlayer* simplePlayer) { //getLogger().debug("SetSimplePlayerInfo"); @@ -186,14 +161,14 @@ namespace MultiQuestensions::Environments { SetPlayerInfo(simplePlayer); } - using MultiplayerCore::Players::MpPlayerData; + using Players::MpPlayerData; void MQEAvatarNameTag::HandlePlatformData(IConnectedPlayer* player, MpPlayerData* data) { getLogger().debug("HandlePlatformData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) SetPlatformData(data); } - using MultiQuestensions::Players::MpexPlayerData; + using Players::MpexPlayerData; void MQEAvatarNameTag::HandleMpexData(IConnectedPlayer* player, MpexPlayerData* data) { getLogger().debug("HandleMpexData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index 2650f2b..ad5e695 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -5,6 +5,7 @@ #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" #include "Environments/MQEAvatarPlaceLighting.hpp" #include "Environments/MQEAvatarNameTag.hpp" +#include "Players/MpexPlayerManager.hpp" #include "Config.hpp" #include "GlobalNamespace/MultiplayerLobbyController.hpp" @@ -20,7 +21,6 @@ #include "GlobalNamespace/MultiplayerLobbyAvatarManager.hpp" #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/ConnectedPlayerManager_ConnectedPlayer.hpp" -// #include "GlobalNamespace/AvatarPoseRestrictions.hpp" #include "GlobalNamespace/GameplayServerConfiguration.hpp" #include "System/Collections/Generic/List_1.hpp" @@ -28,8 +28,6 @@ #include "UnityEngine/Resources.hpp" #include "UnityEngine/Transform.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" - using namespace GlobalNamespace; using namespace UnityEngine; using namespace MultiQuestensions::Environments; @@ -251,8 +249,8 @@ namespace MultiQuestensions { //getLogger().debug("Found GetAvatarCaptionObject"); MQEAvatarNameTag* nameTag; if (objAvatarCaption->TryGetComponent(byref(nameTag))) { - MultiplayerCore::Players::MpPlayerData* mpPlayerData; - if (MultiplayerCore::Players::MpPlayerManager::TryGetPlayer(player->get_userId(), mpPlayerData)) { + MultiQuestensions::Players::MpPlayerData* mpPlayerData; + if (MultiQuestensions::Players::MpexPlayerManager::TryGetMpPlayerData(player->get_userId(), mpPlayerData)) { nameTag->SetPlatformData(mpPlayerData); } else { getLogger().debug("UpdateNameTagIcons: mpPlayerData is nullptr"); @@ -265,7 +263,7 @@ namespace MultiQuestensions { //getLogger().debug("MultiplayerLobbyAvatarManager::AddPlayer"); MultiplayerLobbyAvatarManager_AddPlayer(self, connectedPlayer); _avatarManager = self; - HandleLobbyAvatarCreated(connectedPlayer);//TODO que this so that it is ran when the player returns to the lobby? + HandleLobbyAvatarCreated(connectedPlayer); } #pragma endregion diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 7ac7b11..e4ad7cb 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -20,34 +20,36 @@ #include "questui/shared/CustomTypes/Components/MainThreadScheduler.hpp" #include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" - -#include "Environments/MQEAvatarNameTag.hpp" +#include "MultiplayerCore/shared/CodegenExtensions/EnumUtils.hpp" +#include "Players/MpexPlayerManager.hpp" +#include "Players/MpPlayerData.hpp" using namespace MultiQuestensions; using namespace MultiplayerCore::Networking; using namespace GlobalNamespace; -using namespace MultiQuestensions::Environments; -// std::map> _extendedPlayers; -std::map> _mpexPlayerData; -//System::Collections::Generic::Dictionary_2* extendedPlayers; -//SafePtr*> extendedPlayersSPTR; -//SafePtr localExtendedPlayerSPTR; -// SafePtr localExtendedPlayer; SafePtr localMpexPlayerData; +std::map> _mpexPlayerData; + +SafePtr localPlayer; +std::map> _playerData; + IPlatformUserModel* platformUserModel; +event MultiQuestensions::Players::MpexPlayerManager::RecievedPlayerData; +event MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData; + +event MultiQuestensions::Players::MpexPlayerManager::disconnectedEvent; +event MultiQuestensions::Players::MpexPlayerManager::playerConnectedEvent; +event MultiQuestensions::Players::MpexPlayerManager::playerDisconnectedEvent; -MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerConnected); -MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected); -MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect); +event_handler _PlayerConnectedHandler = MultiQuestensions::event_handler(HandlePlayerConnected); +event_handler _PlayerDisconnectedHandler = MultiQuestensions::event_handler(HandlePlayerDisconnected); +event_handler _DisconnectedHandler = MultiQuestensions::event_handler(HandleDisconnect); -MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData; -bool MultiQuestensions::Players::MpexPlayerManager::TryGetPlayer(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { +bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { player = static_cast(_mpexPlayerData.at(playerId)); return true; @@ -55,15 +57,50 @@ bool MultiQuestensions::Players::MpexPlayerManager::TryGetPlayer(std::string pla return false; } -MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetPlayer(std::string playerId) { +MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpexPlayerData(std::string playerId) { if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { return static_cast(_mpexPlayerData.at(playerId)); } return nullptr; } + +bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpPlayerData(std::string playerId, Players::MpPlayerData*& player) { + if (_playerData.find(playerId) != _playerData.end()) { + player = static_cast(_playerData.at(playerId)); + return true; + } + return false; +} + +Players::MpPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpPlayerData(std::string playerId) { + if (_playerData.find(playerId) != _playerData.end()) { + return static_cast(_playerData.at(playerId)); + } + return nullptr; +} + + + +static void HandlePlayerData(Players::MpPlayerData* playerData, IConnectedPlayer* player) { + if (_playerData.contains(static_cast(player->get_userId()))) { + getLogger().debug("HandlePlayerData, player already exists"); + _playerData.at(static_cast(player->get_userId())) = playerData; + } + else { + getLogger().info("Received new 'MpPlayerData' from '%s' with platformID: '%s' platform: '%d'", + to_utf8(csstrtostr(player->get_userId())).c_str(), + to_utf8(csstrtostr(playerData->platformId)).c_str(), + (int)playerData->platform + ); + _playerData.emplace(static_cast(player->get_userId()), playerData); + } + getLogger().debug("MpPlayerData firing event"); + MultiQuestensions::Players::MpexPlayerManager::RecievedPlayerData(player, playerData); + getLogger().debug("MpPlayerData done"); +} + static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* player) { - getLogger().debug("HandleMpexData"); const std::string userId = to_utf8(csstrtostr(player->get_userId())); if (_mpexPlayerData.contains(userId)) { @@ -78,22 +115,32 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl } SetPlayerPlaceColor(player, packet->Color, true); - getLogger().info("Calling event 'RecievedMpExPlayerData'"); + getLogger().info("Calling event 'PlayerConnected'"); MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData(player, packet); } + void HandlePlayerConnected(IConnectedPlayer* player) { try { - getLogger().debug("MQE HandlePlayerConnected"); + getLogger().debug("MpEx HandlePlayerConnected"); if (player) { - const std::string userId = player->get_userId(); - getLogger().info("MQE Player '%s' joined", userId.c_str()); + getLogger().info("Player '%s' joined", static_cast(player->get_userId()).c_str()); + if (localPlayer->platformId) + { + getLogger().debug("Sending MpPlayerData with platformID: '%s' platform: '%d'", + static_cast(localPlayer->platformId).c_str(), + (int)localPlayer->platform + ); + MultiplayerCore::mpPacketSerializer->Send(localPlayer); + } + getLogger().debug("MpPlayerData sent"); + getLogger().debug("Sending MpexPlayerData"); if (localMpexPlayerData) { MultiplayerCore::mpPacketSerializer->Send(localMpexPlayerData->ToSerializable()); + getLogger().debug("MpexPlayerData sent"); } - getLogger().debug("MpexPlayerData sent"); SetPlayerPlaceColor(player, Config::DefaultPlayerColor, false); } @@ -104,47 +151,155 @@ void HandlePlayerConnected(IConnectedPlayer* player) { } void HandlePlayerDisconnected(IConnectedPlayer* player) { - if (player) { + try { const std::string userId = to_utf8(csstrtostr(player->get_userId())); - if (_mpexPlayerData.contains(userId)) { - getLogger().info("Reseting platform lights for Player '%s'", userId.c_str()); - SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); - _mpexPlayerData.erase(userId); + getLogger().info("Player '%s' left", userId.c_str()); + + if (player) { + if(_playerData.contains(userId)){ + _playerData.at(userId).~SafePtr(); + _playerData.erase(userId); + } + if (_mpexPlayerData.contains(userId)) { + getLogger().info("Reseting platform lights for Player '%s'", userId.c_str()); + SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); + _mpexPlayerData.at(userId).~SafePtr(); + _mpexPlayerData.erase(userId); + } } } + catch (const std::runtime_error& e) { + getLogger().error("REPORT TO ENDER: %s", e.what()); + } } -void HandleDisconnect(DisconnectedReason reason ) { + +void HandleDisconnect(DisconnectedReason reason) { + getLogger().info("Disconnected from server reason: '%s'", MultiplayerCore::EnumUtils::GetEnumName(reason).c_str()); + _playerData.clear(); getLogger().info("Clearing MPEX player data"); _mpexPlayerData.clear(); - MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; - MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent -= _PlayerDisconnectedHandler; - MultiplayerCore::Players::MpPlayerManager::disconnectedEvent -= _DisconnectedHandler; + getLogger().info("MQE Removing connected/disconnected/disconnect events"); + Players::MpexPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; + Players::MpexPlayerManager::playerDisconnectedEvent -= _PlayerDisconnectedHandler; + Players::MpexPlayerManager::disconnectedEvent -= _DisconnectedHandler; +} + +MAKE_HOOK_MATCH(MultiplayerSessionManager_HandlePlayerConnected, &MultiplayerSessionManager::HandlePlayerConnected, void, MultiplayerSessionManager* self, IConnectedPlayer* player) { + getLogger().debug("MultiplayerSessionManager_HandlePlayerConnected"); + MultiplayerSessionManager_HandlePlayerConnected(self, player); + if(player){ + getLogger().debug("MultiplayerSessionManager_HandlePlayerConnected, triggering MQE event"); + Players::MpexPlayerManager::playerConnectedEvent(player); + } +} + +MAKE_HOOK_MATCH(MultiplayerSessionManager_HandlePlayerDisconnected, &MultiplayerSessionManager::HandlePlayerDisconnected, void, MultiplayerSessionManager* self, IConnectedPlayer* player) { + getLogger().debug("MultiplayerSessionManager_HandlePlayerDisconnected"); + MultiplayerSessionManager_HandlePlayerDisconnected(self, player); + if(player){ + getLogger().debug("MultiplayerSessionManager_HandlePlayerDisconnected, triggering MQE event"); + Players::MpexPlayerManager::playerDisconnectedEvent(player); + } +} + +MAKE_HOOK_MATCH(MultiplayerSessionManager_HandleDisconnected, &MultiplayerSessionManager::HandleDisconnected, void, MultiplayerSessionManager* self, DisconnectedReason disconnectedReason) { + getLogger().debug("MultiplayerSessionManager_HandleDisconnected, triggeing event first"); + Players::MpexPlayerManager::disconnectedEvent(disconnectedReason); + getLogger().debug("MultiplayerSessionManager_HandleDisconnected, triggering base game"); + MultiplayerSessionManager_HandleDisconnected(self, disconnectedReason); } + + MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, MultiplayerSessionManager* self) { sessionManager = self; SessionManagerStart(sessionManager); } +Players::Platform getPlatform(UserInfo::Platform platform) { + switch (platform.value) { + case UserInfo::Platform::Oculus: + getLogger().debug("Platform: Oculus = OculusQuest"); + return Players::Platform::OculusQuest; // If platform is Oculus, we assume the user is using Quest + case UserInfo::Platform::PS4: + getLogger().debug("Platform: PS4"); + return Players::Platform::PS4; + case UserInfo::Platform::Steam: + getLogger().debug("Platform: Steam"); + return Players::Platform::Steam; + case UserInfo::Platform::Test: + getLogger().debug("Platform: Test = Unknown"); + return Players::Platform::Unknown; + default: + try { + getLogger().debug("Platform: %s", MultiplayerCore::EnumUtils::GetEnumName(platform).c_str()); + } + catch (const std::runtime_error& e) { + getLogger().error("REPORT TO ENDER: %s", e.what()); + } + catch (const std::exception& e) { + getLogger().error("REPORT TO ENDER: %s", e.what()); + } + catch (...) { + getLogger().error("REPORT TO ENDER: Unknown exception"); + } + getLogger().debug("Platform: %d", (int)platform.value); + return (Players::Platform)platform.value; + } +} + + + + MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSession, void, MultiplayerSessionManager* self, MultiplayerSessionManager_SessionType sessionType, ConnectedPlayerManager* connectedPlayerManager) { SessionManager_StartSession(self, sessionType, connectedPlayerManager); + getLogger().debug("MultiplayerSessionManager.StartSession, creating localPlayer"); + + + static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll().get(0); + static auto UserInfoTask = localNetworkPlayerModel->dyn__platformUserModel()->GetUserInfo(); + static auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function*)>)[&](System::Threading::Tasks::Task_1* userInfoTask) { + auto userInfo = userInfoTask->get_Result(); + if (userInfo) { + if (!localPlayer) localPlayer = Players::MpPlayerData::Init(userInfo->dyn_platformUserId(), getPlatform(userInfo->dyn_platform())); + else { + localPlayer->platformId = userInfo->dyn_platformUserId(); + localPlayer->platform = getPlatform(userInfo->dyn_platform()); + } + } + else getLogger().error("Failed to get local network player!"); + } + ); + reinterpret_cast(UserInfoTask)->ContinueWith(action); + + + + getLogger().debug("MultiplayerSessionManager.StartSession, creating localMpexPlayerData"); + localMpexPlayerData = Players::MpexPlayerData::New_ctor(); localMpexPlayerData->Color = config.getPlayerColor(); + //mpPacketSerializer->RegisterCallback(HandlePlayerData); + MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandlePlayerData); + getLogger().debug("Callback HandlePlayerData Registered"); MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); + Players::MpexPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; + Players::MpexPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; + Players::MpexPlayerManager::disconnectedEvent += _DisconnectedHandler; - - MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; - MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; - MultiplayerCore::Players::MpPlayerManager::disconnectedEvent += _DisconnectedHandler; } + void MultiQuestensions::Hooks::SessionManagerAndExtendedPlayerHooks() { INSTALL_HOOK(getLogger(), SessionManagerStart); INSTALL_HOOK(getLogger(), SessionManager_StartSession); + + INSTALL_HOOK(getLogger(), MultiplayerSessionManager_HandlePlayerConnected); + INSTALL_HOOK(getLogger(), MultiplayerSessionManager_HandlePlayerDisconnected); + INSTALL_HOOK(getLogger(), MultiplayerSessionManager_HandleDisconnected); } \ No newline at end of file diff --git a/MultiQuestensions/src/Players/MpPlayerData.cpp b/MultiQuestensions/src/Players/MpPlayerData.cpp new file mode 100644 index 0000000..24302fd --- /dev/null +++ b/MultiQuestensions/src/Players/MpPlayerData.cpp @@ -0,0 +1,39 @@ +#include "main.hpp" +#include "Players/MpPlayerData.hpp" + +DEFINE_TYPE(MultiQuestensions::Players, MpPlayerData) + +namespace MultiQuestensions::Players { +#pragma region MpPlayerData + void MpPlayerData::New() { + getLogger().debug("Creating MpPlayerData"); + } + + MpPlayerData* MpPlayerData::Init(StringW platformID, Platform platform) + { + auto mpPlayerData = THROW_UNLESS(il2cpp_utils::New()); + + mpPlayerData->platformId = platformID; + mpPlayerData->platform = platform; + getLogger().debug("Creating MpPlayerData finished"); + return mpPlayerData; + } + + + void MpPlayerData::Serialize(LiteNetLib::Utils::NetDataWriter* writer) { + getLogger().debug("MpPlayerData::Serialize"); + + writer->Put(platformId); + writer->Put((int)platform); + getLogger().debug("Serialize MpPlayerData done"); + } + + void MpPlayerData::Deserialize(LiteNetLib::Utils::NetDataReader* reader) { + getLogger().debug("MpPlayerData::Deserialize"); + + this->platformId = reader->GetString(); + this->platform = (Platform)reader->GetInt(); + getLogger().debug("Deserialize MpPlayerData done"); + } +#pragma endregion +} \ No newline at end of file From 5e34d5c2159e40443d6161899f576e5500510f63 Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 21 May 2022 16:37:35 +0100 Subject: [PATCH 41/56] Bumped Beatsaber hook version and delegate to get local playerdata is only ran once --- MultiQuestensions/mod.json | 16 +++----------- MultiQuestensions/mod.template.json | 12 +---------- MultiQuestensions/qpm.json | 14 +++++-------- .../SessionManagerAndMpexPlayerHooks.cpp | 21 +++++++++++-------- 4 files changed, 21 insertions(+), 42 deletions(-) diff --git a/MultiQuestensions/mod.json b/MultiQuestensions/mod.json index a0918c6..3418090 100644 --- a/MultiQuestensions/mod.json +++ b/MultiQuestensions/mod.json @@ -1,5 +1,5 @@ { - "_QPVersion": "0.1.2", + "_QPVersion": "0.1.1", "name": "MultiQuestensions", "id": "MultiQuestensions", "author": "EnderdracheLP and Goobie", @@ -8,20 +8,10 @@ "packageVersion": "1.21.0", "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", "dependencies": [ - { - "version": "^1.4.0", - "id": "BeatTogether", - "downloadIfMissing": "https://github.com/pythonology/BeatTogether.Quest/releases/download/v1.4.0/BeatTogether_v1.4.0.qmod" - }, - { - "version": "^1.0.0", - "id": "MultiplayerCore.Quest", - "downloadIfMissing": "https://github.com/EnderdracheLP/MultiplayerCore.Quest/releases/download/v1.0.0/MultiplayerCore.qmod" - }, { "version": "^0.15.9", "id": "custom-types", - "downloadIfMissing": "https://github.com/sc2ad/Il2CppQuestTypePatching/releases/download/v0.15.9/CustomTypes.qmod" + "downloadIfMissing": "https://github.com/sc2ad/Il2CppQuestTypePatching/releases/download/v0.15.10/CustomTypes.qmod" }, { "version": "^0.22.0", @@ -38,7 +28,7 @@ "libMultiQuestensions.so" ], "libraryFiles": [ - "libbeatsaber-hook_3_7_4.so" + "libbeatsaber-hook_3_8_5.so" ], "fileCopies": [], "copyExtensions": [] diff --git a/MultiQuestensions/mod.template.json b/MultiQuestensions/mod.template.json index e1e70d0..6d708d9 100644 --- a/MultiQuestensions/mod.template.json +++ b/MultiQuestensions/mod.template.json @@ -1,5 +1,5 @@ { - "_QPVersion": "0.1.2", + "_QPVersion": "0.1.1", "name": "${mod_name}", "id": "${mod_id}", "author": "EnderdracheLP and Goobie", @@ -8,16 +8,6 @@ "packageVersion": "1.21.0", "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", "dependencies": [ - { - "version": "^1.4.0", - "id": "BeatTogether", - "downloadIfMissing": "https://github.com/pythonology/BeatTogether.Quest/releases/download/v1.4.0/BeatTogether_v1.4.0.qmod" - }, - { - "version": "^1.0.0", - "id": "MultiplayerCore.Quest", - "downloadIfMissing": "https://github.com/EnderdracheLP/MultiplayerCore.Quest/releases/download/v1.0.0/MultiplayerCore.qmod" - } ], "modFiles": [], "libraryFiles": [], diff --git a/MultiQuestensions/qpm.json b/MultiQuestensions/qpm.json index 163b50c..9ab653f 100644 --- a/MultiQuestensions/qpm.json +++ b/MultiQuestensions/qpm.json @@ -11,15 +11,6 @@ } }, "dependencies": [ - { - "id": "beatsaber-hook", - "versionRange": "=3.7.4", - "additionalData": { - "extraFiles": [ - "src/inline-hook" - ] - } - }, { "id": "codegen", "versionRange": "^0.22.0", @@ -44,6 +35,11 @@ "id": "modloader", "versionRange": "*", "additionalData": {} + }, + { + "id": "beatsaber-hook", + "versionRange": "^3.8.5", + "additionalData": {} } ], "additionalData": {} diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index e4ad7cb..ee79fdf 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -251,14 +251,10 @@ Players::Platform getPlatform(UserInfo::Platform platform) { } - - MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSession, void, MultiplayerSessionManager* self, MultiplayerSessionManager_SessionType sessionType, ConnectedPlayerManager* connectedPlayerManager) { SessionManager_StartSession(self, sessionType, connectedPlayerManager); - getLogger().debug("MultiplayerSessionManager.StartSession, creating localPlayer"); - - + static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll().get(0); static auto UserInfoTask = localNetworkPlayerModel->dyn__platformUserModel()->GetUserInfo(); static auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function*)>)[&](System::Threading::Tasks::Task_1* userInfoTask) { @@ -268,19 +264,26 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe else { localPlayer->platformId = userInfo->dyn_platformUserId(); localPlayer->platform = getPlatform(userInfo->dyn_platform()); + getLogger().error("got local network player, it will be null after this so no repeats"); } } else getLogger().error("Failed to get local network player!"); } ); - reinterpret_cast(UserInfoTask)->ContinueWith(action); - + if(action){ + reinterpret_cast(UserInfoTask)->ContinueWith(action); + action = nullptr; + } + getLogger().debug("MultiplayerSessionManager.StartSession, creating localMpexPlayerData"); - localMpexPlayerData = Players::MpexPlayerData::New_ctor(); - localMpexPlayerData->Color = config.getPlayerColor(); + if(!localMpexPlayerData){ + localMpexPlayerData = Players::MpexPlayerData::New_ctor(); + localMpexPlayerData->Color = config.getPlayerColor(); + } + //mpPacketSerializer->RegisterCallback(HandlePlayerData); MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandlePlayerData); From 9f693d7923472a6a46aea64ae1949095967dc0bb Mon Sep 17 00:00:00 2001 From: cubic Date: Sun, 22 May 2022 12:58:51 +0100 Subject: [PATCH 42/56] May have fixed lights and icons not showing and dissapearing correctly --- .../SessionManagerAndMpexPlayerHooks.cpp | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index ee79fdf..cb6e874 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -50,19 +50,19 @@ event_handler _DisconnectedHandler = MultiQ bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { - if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { - player = static_cast(_mpexPlayerData.at(playerId)); - return true; - } - return false; - } + if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { + player = static_cast(_mpexPlayerData.at(playerId)); + return true; + } + return false; +} MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpexPlayerData(std::string playerId) { - if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { - return static_cast(_mpexPlayerData.at(playerId)); - } - return nullptr; - } + if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { + return static_cast(_mpexPlayerData.at(playerId)); + } + return nullptr; +} bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpPlayerData(std::string playerId, Players::MpPlayerData*& player) { @@ -83,40 +83,45 @@ Players::MpPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpPlaye static void HandlePlayerData(Players::MpPlayerData* playerData, IConnectedPlayer* player) { - if (_playerData.contains(static_cast(player->get_userId()))) { - getLogger().debug("HandlePlayerData, player already exists"); - _playerData.at(static_cast(player->get_userId())) = playerData; - } - else { - getLogger().info("Received new 'MpPlayerData' from '%s' with platformID: '%s' platform: '%d'", - to_utf8(csstrtostr(player->get_userId())).c_str(), - to_utf8(csstrtostr(playerData->platformId)).c_str(), - (int)playerData->platform - ); - _playerData.emplace(static_cast(player->get_userId()), playerData); + if(player){ + const std::string userId = to_utf8(csstrtostr(player->get_userId())); + if (_playerData.contains(userId)) { + getLogger().debug("HandlePlayerData, player already exists"); + _playerData.at(userId) = playerData; + } + else { + getLogger().info("Received new 'MpPlayerData' from '%s' with platformID: '%s' platform: '%d'", + to_utf8(csstrtostr(player->get_userId())).c_str(), + to_utf8(csstrtostr(playerData->platformId)).c_str(), + (int)playerData->platform + ); + _playerData.emplace(userId, playerData); + } + getLogger().debug("MpPlayerData firing event"); + MultiQuestensions::Players::MpexPlayerManager::RecievedPlayerData(player, playerData); + getLogger().debug("MpPlayerData done"); } - getLogger().debug("MpPlayerData firing event"); - MultiQuestensions::Players::MpexPlayerManager::RecievedPlayerData(player, playerData); - getLogger().debug("MpPlayerData done"); } static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* player) { - const std::string userId = to_utf8(csstrtostr(player->get_userId())); + if(player){ + const std::string userId = to_utf8(csstrtostr(player->get_userId())); + if (_mpexPlayerData.contains(userId)) { + getLogger().info("Recieved 'MpexPlayerData', player already exists"); + _mpexPlayerData[userId] = packet; + } + else { + getLogger().info("Received 'MpexPlayerData' from '%s' with color: '%f, %f, %f, %f'", + userId.c_str(), + packet->Color.r, packet->Color.g, packet->Color.b, packet->Color.a + ); + _mpexPlayerData.emplace(userId, packet); + } - if (_mpexPlayerData.contains(userId)) { - _mpexPlayerData[userId] = packet; - } - else { - getLogger().info("Received 'MpexPlayerData' from '%s' with color: '%f, %f, %f, %f'", - userId.c_str(), - packet->Color.r, packet->Color.g, packet->Color.b, packet->Color.a - ); - _mpexPlayerData.emplace(userId, packet); + SetPlayerPlaceColor(player, packet->Color, true); + getLogger().info("Calling event 'RecievedMpExPlayerData'"); + MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData(player, packet); } - - SetPlayerPlaceColor(player, packet->Color, true); - getLogger().info("Calling event 'PlayerConnected'"); - MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData(player, packet); } @@ -152,10 +157,10 @@ void HandlePlayerConnected(IConnectedPlayer* player) { void HandlePlayerDisconnected(IConnectedPlayer* player) { try { - const std::string userId = to_utf8(csstrtostr(player->get_userId())); - getLogger().info("Player '%s' left", userId.c_str()); - + getLogger().debug("MpEx HandlePlayerDisconnected"); if (player) { + const std::string userId = to_utf8(csstrtostr(player->get_userId())); + getLogger().info("Player '%s' left", userId.c_str()); if(_playerData.contains(userId)){ _playerData.at(userId).~SafePtr(); _playerData.erase(userId); @@ -185,29 +190,24 @@ void HandleDisconnect(DisconnectedReason reason) { Players::MpexPlayerManager::disconnectedEvent -= _DisconnectedHandler; } -MAKE_HOOK_MATCH(MultiplayerSessionManager_HandlePlayerConnected, &MultiplayerSessionManager::HandlePlayerConnected, void, MultiplayerSessionManager* self, IConnectedPlayer* player) { - getLogger().debug("MultiplayerSessionManager_HandlePlayerConnected"); - MultiplayerSessionManager_HandlePlayerConnected(self, player); - if(player){ - getLogger().debug("MultiplayerSessionManager_HandlePlayerConnected, triggering MQE event"); - Players::MpexPlayerManager::playerConnectedEvent(player); - } +MAKE_HOOK_MATCH(LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected, &LobbyPlayersDataModel::HandleMultiplayerSessionManagerPlayerConnected, void, LobbyPlayersDataModel* self, IConnectedPlayer* player) { + getLogger().debug("LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected"); + LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected(self, player); + getLogger().debug("LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected, triggering MQE event"); + Players::MpexPlayerManager::playerConnectedEvent(player); } -MAKE_HOOK_MATCH(MultiplayerSessionManager_HandlePlayerDisconnected, &MultiplayerSessionManager::HandlePlayerDisconnected, void, MultiplayerSessionManager* self, IConnectedPlayer* player) { - getLogger().debug("MultiplayerSessionManager_HandlePlayerDisconnected"); - MultiplayerSessionManager_HandlePlayerDisconnected(self, player); - if(player){ - getLogger().debug("MultiplayerSessionManager_HandlePlayerDisconnected, triggering MQE event"); - Players::MpexPlayerManager::playerDisconnectedEvent(player); - } +MAKE_HOOK_MATCH(LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected, &LobbyPlayersDataModel::HandleMultiplayerSessionManagerPlayerDisconnected, void, LobbyPlayersDataModel* self, IConnectedPlayer* player) { + getLogger().debug("LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected"); + LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected(self, player); + getLogger().debug("LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected, triggering MQE event"); + Players::MpexPlayerManager::playerDisconnectedEvent(player); } -MAKE_HOOK_MATCH(MultiplayerSessionManager_HandleDisconnected, &MultiplayerSessionManager::HandleDisconnected, void, MultiplayerSessionManager* self, DisconnectedReason disconnectedReason) { - getLogger().debug("MultiplayerSessionManager_HandleDisconnected, triggeing event first"); +MAKE_HOOK_MATCH(LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected, &LobbyGameStateController::HandleMultiplayerSessionManagerDisconnected, void, LobbyGameStateController* self, DisconnectedReason disconnectedReason) { + getLogger().debug("LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected"); + LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected(self, disconnectedReason); Players::MpexPlayerManager::disconnectedEvent(disconnectedReason); - getLogger().debug("MultiplayerSessionManager_HandleDisconnected, triggering base game"); - MultiplayerSessionManager_HandleDisconnected(self, disconnectedReason); } @@ -276,7 +276,7 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe } - + getLogger().debug("MultiplayerSessionManager.StartSession, creating localMpexPlayerData"); if(!localMpexPlayerData){ @@ -302,7 +302,7 @@ void MultiQuestensions::Hooks::SessionManagerAndExtendedPlayerHooks() { INSTALL_HOOK(getLogger(), SessionManagerStart); INSTALL_HOOK(getLogger(), SessionManager_StartSession); - INSTALL_HOOK(getLogger(), MultiplayerSessionManager_HandlePlayerConnected); - INSTALL_HOOK(getLogger(), MultiplayerSessionManager_HandlePlayerDisconnected); - INSTALL_HOOK(getLogger(), MultiplayerSessionManager_HandleDisconnected); + INSTALL_HOOK(getLogger(), LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected); + INSTALL_HOOK(getLogger(), LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected); + INSTALL_HOOK(getLogger(), LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected); } \ No newline at end of file From 41911f707707ce78869d23a58b9f2d35b1dc238d Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 23 May 2022 22:08:11 +0100 Subject: [PATCH 43/56] Removed event stuff and sent it back to MPCore Removed some ~safeptr stuff --- .../include/Environments/MQEAvatarNameTag.hpp | 10 +- .../SessionManagerAndExtendedPlayerHooks.hpp | 4 - .../shared/Players/MpPlayerData.hpp | 32 --- .../shared/Players/MpexPlayerManager.hpp | 19 +- MultiQuestensions/shared/Utils/event.hpp | 233 ------------------ .../src/Environments/MQEAvaterNameTag.cpp | 23 +- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 5 +- .../SessionManagerAndMpexPlayerHooks.cpp | 170 +------------ .../src/Players/MpPlayerData.cpp | 39 --- 9 files changed, 37 insertions(+), 498 deletions(-) delete mode 100644 MultiQuestensions/shared/Players/MpPlayerData.hpp delete mode 100644 MultiQuestensions/shared/Utils/event.hpp delete mode 100644 MultiQuestensions/src/Players/MpPlayerData.cpp diff --git a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp index 7fa2b26..92b8fe6 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp @@ -1,7 +1,7 @@ #pragma once #include "custom-types/shared/macros.hpp" #include "Players/MpexPlayerData.hpp" -#include "Players/MpPlayerData.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" #include "Players/MpexPlayerManager.hpp" #include "UnityEngine/MonoBehaviour.hpp" #include "HMUI/ImageView.hpp" @@ -24,9 +24,9 @@ DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarNameTag, UnityEn DECLARE_INSTANCE_METHOD(void, SetPlayerInfo, GlobalNamespace::IConnectedPlayer* player); // DECLARE_INSTANCE_METHOD(void, SetExtendedPlayerInfo, MultiQuestensions::Extensions::ExtendedPlayer* extendedPlayer); - DECLARE_INSTANCE_METHOD(void, SetPlatformData, MultiQuestensions::Players::MpPlayerData* data); + DECLARE_INSTANCE_METHOD(void, SetPlatformData, MultiplayerCore::Players::MpPlayerData* data); DECLARE_INSTANCE_METHOD(void, SetSimplePlayerInfo, GlobalNamespace::IConnectedPlayer* simplePlayer); - DECLARE_INSTANCE_METHOD(void, HandlePlatformData, GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpPlayerData* data); + DECLARE_INSTANCE_METHOD(void, HandlePlatformData, GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data); DECLARE_INSTANCE_METHOD(void, HandleMpexData, GlobalNamespace::IConnectedPlayer* player, MultiQuestensions::Players::MpexPlayerData* data); enum PlayerIconSlot { @@ -35,8 +35,8 @@ DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarNameTag, UnityEn bool _enabled; - MultiQuestensions::event_handler _platformDataEventHandler; - MultiQuestensions::event_handler _mpexPlayerDataEventHandler; + MultiplayerCore::event_handler _platformDataEventHandler; + MultiplayerCore::event_handler _mpexPlayerDataEventHandler; std::map _playerIcons; diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index 03c541e..eb0b206 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -1,15 +1,11 @@ #pragma once #include "Players/MpexPlayerData.hpp" -#include "Players/MpPlayerData.hpp" #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/DisconnectedReason.hpp" extern SafePtr localMpexPlayerData; extern std::map> _mpexPlayerData; -extern SafePtr localPlayer; -extern std::map> _playerData; - extern void HandlePlayerConnected(GlobalNamespace::IConnectedPlayer* player); extern void HandlePlayerDisconnected(GlobalNamespace::IConnectedPlayer* player); extern void HandleDisconnect(GlobalNamespace::DisconnectedReason reason); diff --git a/MultiQuestensions/shared/Players/MpPlayerData.hpp b/MultiQuestensions/shared/Players/MpPlayerData.hpp deleted file mode 100644 index 892cd05..0000000 --- a/MultiQuestensions/shared/Players/MpPlayerData.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "custom-types/shared/macros.hpp" -#include "GlobalNamespace/IConnectedPlayer.hpp" -#include "MultiplayerCore/shared/Networking/Abstractions/MpPacket.hpp" - -namespace MultiQuestensions::Players { -enum class Platform - { - Unknown = 0, - Steam = 1, - OculusPC = 2, - OculusQuest = 3, - PS4 = 4 - }; -} - -DECLARE_CLASS_CUSTOM_DLL(MultiQuestensions::Players, MpPlayerData, MultiplayerCore::Networking::Abstractions::MpPacket, "MultiQuestensions.Players", - - DECLARE_CTOR(New); - - // Player and platform information - DECLARE_INSTANCE_FIELD(StringW, platformId); - - DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); - DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Deserialize", 1), LiteNetLib::Utils::NetDataReader* reader); - - public: - Platform platform; - - static MpPlayerData* Init(StringW platformID, Platform platform); -) -//#undef MPDInterfaces \ No newline at end of file diff --git a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp index 06340be..0596c8e 100644 --- a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp +++ b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp @@ -1,7 +1,8 @@ #pragma once #include "MpexPlayerData.hpp" -#include "MpPlayerData.hpp" -#include "Utils/event.hpp" +#include "MultiplayerCore/shared/Utils/event.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" + namespace MultiQuestensions::Players { class MpexPlayerManager { @@ -11,18 +12,6 @@ namespace MultiQuestensions::Players { static bool TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player); static MpexPlayerData* GetMpexPlayerData(std::string playerId); - static bool TryGetMpPlayerData(std::string playerId, MultiQuestensions::Players::MpPlayerData*& player); - static MultiQuestensions::Players::MpPlayerData* GetMpPlayerData(std::string playerId); - - static event RecievedPlayerData; - static event RecievedMpExPlayerData; - - //C++ equivalent to basegame events - static event playerConnectedEvent; - static event playerDisconnectedEvent; - static event disconnectedEvent; - - - + static MultiplayerCore::event RecievedMpExPlayerData; }; } \ No newline at end of file diff --git a/MultiQuestensions/shared/Utils/event.hpp b/MultiQuestensions/shared/Utils/event.hpp deleted file mode 100644 index 612a317..0000000 --- a/MultiQuestensions/shared/Utils/event.hpp +++ /dev/null @@ -1,233 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -namespace MultiQuestensions { - template class event_handler - { - public: - typedef std::function handler_func_type; - typedef unsigned int handler_id_type; - - explicit event_handler(const handler_func_type& handlerFunc) - : m_handlerFunc(handlerFunc) - { - m_handlerId = ++m_handlerIdCounter; - } - - // copy constructor - event_handler(const event_handler& src) - : m_handlerFunc(src.m_handlerFunc), m_handlerId(src.m_handlerId) - { - } - - // move constructor - event_handler(event_handler&& src) - : m_handlerFunc(std::move(src.m_handlerFunc)), m_handlerId(src.m_handlerId) - { - } - - // copy assignment operator - event_handler& operator=(const event_handler& src) - { - m_handlerFunc = src.m_handlerFunc; - m_handlerId = src.m_handlerId; - - return *this; - } - - // move assignment operator - event_handler& operator=(event_handler&& src) - { - std::swap(m_handlerFunc, src.m_handlerFunc); - m_handlerId = src.m_handlerId; - - return *this; - } - - // function call operator - void operator()(Args... params) const - { - if (m_handlerFunc) - { - m_handlerFunc(params...); - } - } - - bool operator==(const event_handler& other) const - { - return m_handlerId == other.m_handlerId; - } - - operator bool() const - { - return m_handlerFunc; - } - - handler_id_type id() const - { - return m_handlerId; - } - - private: - handler_func_type m_handlerFunc; - handler_id_type m_handlerId; - static std::atomic_uint m_handlerIdCounter; - }; - - template std::atomic_uint event_handler::m_handlerIdCounter(0); - - template class event - { - public: - typedef event_handler handler_type; - - event() - { - } - - // copy constructor - event(const event& src) - { - std::lock_guard lock(src.m_handlersLocker); - - m_handlers = src.m_handlers; - } - - // move constructor - event(event&& src) - { - std::lock_guard lock(src.m_handlersLocker); - - m_handlers = std::move(src.m_handlers); - } - - // copy assignment operator - event& operator=(const event& src) - { - std::lock_guard lock(m_handlersLocker); - std::lock_guard lock2(src.m_handlersLocker); - - m_handlers = src.m_handlers; - - return *this; - } - - // move assignment operator - event& operator=(event&& src) - { - std::lock_guard lock(m_handlersLocker); - std::lock_guard lock2(src.m_handlersLocker); - - std::swap(m_handlers, src.m_handlers); - - return *this; - } - - typename handler_type::handler_id_type add(const handler_type& handler) - { - std::lock_guard lock(m_handlersLocker); - - m_handlers.push_back(handler); - - return handler.id(); - } - - inline typename handler_type::handler_id_type add(const typename handler_type::handler_func_type& handler) - { - return add(handler_type(handler)); - } - - bool remove(const handler_type& handler) - { - std::lock_guard lock(m_handlersLocker); - - auto it = std::find(m_handlers.begin(), m_handlers.end(), handler); - if (it != m_handlers.end()) - { - m_handlers.erase(it); - return true; - } - - return false; - } - - bool remove_id(const typename handler_type::handler_id_type& handlerId) - { - std::lock_guard lock(m_handlersLocker); - - auto it = std::find_if(m_handlers.begin(), m_handlers.end(), - [handlerId](const handler_type& handler) { return handler.id() == handlerId; }); - if (it != m_handlers.end()) - { - m_handlers.erase(it); - return true; - } - - return false; - } - - void call(Args... params) const - { - handler_collection_type handlersCopy = get_handlers_copy(); - - call_impl(handlersCopy, params...); - } - - std::future call_async(Args... params) const - { - return std::async(std::launch::async, [this](Args... asyncParams) { call(asyncParams...); }, params...); - } - - inline void operator()(Args... params) const - { - call(params...); - } - - inline typename handler_type::handler_id_type operator+=(const handler_type& handler) - { - return add(handler); - } - - inline typename handler_type::handler_id_type operator+=(const typename handler_type::handler_func_type& handler) - { - return add(handler); - } - - inline bool operator-=(const handler_type& handler) - { - return remove(handler); - } - - protected: - typedef std::list handler_collection_type; - - void call_impl(const handler_collection_type& handlers, Args... params) const - { - for (const auto& handler : handlers) - { - handler(params...); - } - } - - handler_collection_type get_handlers_copy() const - { - std::lock_guard lock(m_handlersLocker); - - // Since the function return value is by copy, - // before the function returns (and destruct the lock_guard object), - // it creates a copy of the m_handlers container. - - return m_handlers; - } - - private: - handler_collection_type m_handlers; - mutable std::mutex m_handlersLocker; - }; -} \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index baebf02..fe74298 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -9,7 +9,8 @@ #include "GlobalNamespace/ConnectedPlayerName.hpp" #include "UnityEngine/Object.hpp" #include "Players/MpexPlayerManager.hpp" -#include "Players/MpPlayerData.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" #include "Utils/event.hpp" using namespace GlobalNamespace; @@ -72,11 +73,11 @@ namespace MultiQuestensions::Environments { _nameText->set_text(Player()); // Create Event handlers - _platformDataEventHandler = event_handler( - [this](GlobalNamespace::IConnectedPlayer* player, Players::MpPlayerData* data) { + _platformDataEventHandler = MultiplayerCore::event_handler( + [this](GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data) { HandlePlatformData(player, data); }); - _mpexPlayerDataEventHandler = event_handler( + _mpexPlayerDataEventHandler = MultiplayerCore::event_handler( [this](GlobalNamespace::IConnectedPlayer* player, Players::MpexPlayerData* data) { HandleMpexData(player, data); }); @@ -88,7 +89,7 @@ namespace MultiQuestensions::Environments { _enabled = true; // Subscribe to events - Players::MpexPlayerManager::RecievedPlayerData += _platformDataEventHandler; + MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData += _platformDataEventHandler; Players::MpexPlayerManager::RecievedMpExPlayerData += _mpexPlayerDataEventHandler; // Set player info @@ -102,7 +103,7 @@ namespace MultiQuestensions::Environments { _enabled = false; // Unsubscribe from events - Players::MpexPlayerManager::RecievedPlayerData -= _platformDataEventHandler; + MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData -= _platformDataEventHandler; Players::MpexPlayerManager::RecievedMpExPlayerData -= _mpexPlayerDataEventHandler; } @@ -122,14 +123,14 @@ namespace MultiQuestensions::Environments { RemoveIcon(PlayerIconSlot::Platform); - Players::MpPlayerData* data; - if (Players::MpexPlayerManager::TryGetMpPlayerData(userId, data)) + MultiplayerCore::Players::MpPlayerData* data; + if (MultiplayerCore::Players::MpPlayerManager::TryGetMpPlayerData(userId, data)) SetPlatformData(data); } - void MQEAvatarNameTag::SetPlatformData(Players::MpPlayerData* data) { + void MQEAvatarNameTag::SetPlatformData(MultiplayerCore::Players::MpPlayerData* data) { //getLogger().debug("MQEAvatarNameTag::SetPlatformData"); - using Players::Platform; + using MultiplayerCore::Players::Platform; switch (data->platform) { case Platform::Steam: @@ -161,7 +162,7 @@ namespace MultiQuestensions::Environments { SetPlayerInfo(simplePlayer); } - using Players::MpPlayerData; + using MultiplayerCore::Players::MpPlayerData; void MQEAvatarNameTag::HandlePlatformData(IConnectedPlayer* player, MpPlayerData* data) { getLogger().debug("HandlePlatformData"); if (data && player && _playerInfo && player->get_userId() == _playerInfo->get_userId()) diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index ad5e695..a060951 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -7,6 +7,7 @@ #include "Environments/MQEAvatarNameTag.hpp" #include "Players/MpexPlayerManager.hpp" #include "Config.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" #include "GlobalNamespace/MultiplayerLobbyController.hpp" #include "GlobalNamespace/LightWithIdMonoBehaviour.hpp" @@ -249,8 +250,8 @@ namespace MultiQuestensions { //getLogger().debug("Found GetAvatarCaptionObject"); MQEAvatarNameTag* nameTag; if (objAvatarCaption->TryGetComponent(byref(nameTag))) { - MultiQuestensions::Players::MpPlayerData* mpPlayerData; - if (MultiQuestensions::Players::MpexPlayerManager::TryGetMpPlayerData(player->get_userId(), mpPlayerData)) { + MultiplayerCore::Players::MpPlayerData* mpPlayerData; + if (MultiplayerCore::Players::MpPlayerManager::TryGetMpPlayerData(player->get_userId(), mpPlayerData)) { nameTag->SetPlatformData(mpPlayerData); } else { getLogger().debug("UpdateNameTagIcons: mpPlayerData is nullptr"); diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index cb6e874..e026f02 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -22,7 +22,9 @@ #include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" #include "MultiplayerCore/shared/CodegenExtensions/EnumUtils.hpp" #include "Players/MpexPlayerManager.hpp" -#include "Players/MpPlayerData.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" +#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" + using namespace MultiQuestensions; using namespace MultiplayerCore::Networking; @@ -31,22 +33,13 @@ using namespace GlobalNamespace; SafePtr localMpexPlayerData; std::map> _mpexPlayerData; -SafePtr localPlayer; -std::map> _playerData; - IPlatformUserModel* platformUserModel; -event MultiQuestensions::Players::MpexPlayerManager::RecievedPlayerData; -event MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData; - -event MultiQuestensions::Players::MpexPlayerManager::disconnectedEvent; -event MultiQuestensions::Players::MpexPlayerManager::playerConnectedEvent; -event MultiQuestensions::Players::MpexPlayerManager::playerDisconnectedEvent; - +MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData; -event_handler _PlayerConnectedHandler = MultiQuestensions::event_handler(HandlePlayerConnected); -event_handler _PlayerDisconnectedHandler = MultiQuestensions::event_handler(HandlePlayerDisconnected); -event_handler _DisconnectedHandler = MultiQuestensions::event_handler(HandleDisconnect); +MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerConnected); +MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected); +MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect); bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { @@ -64,45 +57,6 @@ MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlay return nullptr; } - -bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpPlayerData(std::string playerId, Players::MpPlayerData*& player) { - if (_playerData.find(playerId) != _playerData.end()) { - player = static_cast(_playerData.at(playerId)); - return true; - } - return false; -} - -Players::MpPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpPlayerData(std::string playerId) { - if (_playerData.find(playerId) != _playerData.end()) { - return static_cast(_playerData.at(playerId)); - } - return nullptr; -} - - - -static void HandlePlayerData(Players::MpPlayerData* playerData, IConnectedPlayer* player) { - if(player){ - const std::string userId = to_utf8(csstrtostr(player->get_userId())); - if (_playerData.contains(userId)) { - getLogger().debug("HandlePlayerData, player already exists"); - _playerData.at(userId) = playerData; - } - else { - getLogger().info("Received new 'MpPlayerData' from '%s' with platformID: '%s' platform: '%d'", - to_utf8(csstrtostr(player->get_userId())).c_str(), - to_utf8(csstrtostr(playerData->platformId)).c_str(), - (int)playerData->platform - ); - _playerData.emplace(userId, playerData); - } - getLogger().debug("MpPlayerData firing event"); - MultiQuestensions::Players::MpexPlayerManager::RecievedPlayerData(player, playerData); - getLogger().debug("MpPlayerData done"); - } -} - static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* player) { if(player){ const std::string userId = to_utf8(csstrtostr(player->get_userId())); @@ -130,16 +84,6 @@ void HandlePlayerConnected(IConnectedPlayer* player) { getLogger().debug("MpEx HandlePlayerConnected"); if (player) { getLogger().info("Player '%s' joined", static_cast(player->get_userId()).c_str()); - if (localPlayer->platformId) - { - getLogger().debug("Sending MpPlayerData with platformID: '%s' platform: '%d'", - static_cast(localPlayer->platformId).c_str(), - (int)localPlayer->platform - ); - MultiplayerCore::mpPacketSerializer->Send(localPlayer); - } - getLogger().debug("MpPlayerData sent"); - getLogger().debug("Sending MpexPlayerData"); if (localMpexPlayerData) { @@ -161,10 +105,6 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { if (player) { const std::string userId = to_utf8(csstrtostr(player->get_userId())); getLogger().info("Player '%s' left", userId.c_str()); - if(_playerData.contains(userId)){ - _playerData.at(userId).~SafePtr(); - _playerData.erase(userId); - } if (_mpexPlayerData.contains(userId)) { getLogger().info("Reseting platform lights for Player '%s'", userId.c_str()); SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); @@ -181,36 +121,14 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { void HandleDisconnect(DisconnectedReason reason) { getLogger().info("Disconnected from server reason: '%s'", MultiplayerCore::EnumUtils::GetEnumName(reason).c_str()); - _playerData.clear(); getLogger().info("Clearing MPEX player data"); _mpexPlayerData.clear(); getLogger().info("MQE Removing connected/disconnected/disconnect events"); - Players::MpexPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; - Players::MpexPlayerManager::playerDisconnectedEvent -= _PlayerDisconnectedHandler; - Players::MpexPlayerManager::disconnectedEvent -= _DisconnectedHandler; + MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; + MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent -= _PlayerDisconnectedHandler; + MultiplayerCore::Players::MpPlayerManager::disconnectedEvent -= _DisconnectedHandler; } -MAKE_HOOK_MATCH(LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected, &LobbyPlayersDataModel::HandleMultiplayerSessionManagerPlayerConnected, void, LobbyPlayersDataModel* self, IConnectedPlayer* player) { - getLogger().debug("LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected"); - LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected(self, player); - getLogger().debug("LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected, triggering MQE event"); - Players::MpexPlayerManager::playerConnectedEvent(player); -} - -MAKE_HOOK_MATCH(LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected, &LobbyPlayersDataModel::HandleMultiplayerSessionManagerPlayerDisconnected, void, LobbyPlayersDataModel* self, IConnectedPlayer* player) { - getLogger().debug("LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected"); - LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected(self, player); - getLogger().debug("LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected, triggering MQE event"); - Players::MpexPlayerManager::playerDisconnectedEvent(player); -} - -MAKE_HOOK_MATCH(LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected, &LobbyGameStateController::HandleMultiplayerSessionManagerDisconnected, void, LobbyGameStateController* self, DisconnectedReason disconnectedReason) { - getLogger().debug("LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected"); - LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected(self, disconnectedReason); - Players::MpexPlayerManager::disconnectedEvent(disconnectedReason); -} - - MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, MultiplayerSessionManager* self) { @@ -218,64 +136,8 @@ MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, Mu SessionManagerStart(sessionManager); } -Players::Platform getPlatform(UserInfo::Platform platform) { - switch (platform.value) { - case UserInfo::Platform::Oculus: - getLogger().debug("Platform: Oculus = OculusQuest"); - return Players::Platform::OculusQuest; // If platform is Oculus, we assume the user is using Quest - case UserInfo::Platform::PS4: - getLogger().debug("Platform: PS4"); - return Players::Platform::PS4; - case UserInfo::Platform::Steam: - getLogger().debug("Platform: Steam"); - return Players::Platform::Steam; - case UserInfo::Platform::Test: - getLogger().debug("Platform: Test = Unknown"); - return Players::Platform::Unknown; - default: - try { - getLogger().debug("Platform: %s", MultiplayerCore::EnumUtils::GetEnumName(platform).c_str()); - } - catch (const std::runtime_error& e) { - getLogger().error("REPORT TO ENDER: %s", e.what()); - } - catch (const std::exception& e) { - getLogger().error("REPORT TO ENDER: %s", e.what()); - } - catch (...) { - getLogger().error("REPORT TO ENDER: Unknown exception"); - } - getLogger().debug("Platform: %d", (int)platform.value); - return (Players::Platform)platform.value; - } -} - - MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSession, void, MultiplayerSessionManager* self, MultiplayerSessionManager_SessionType sessionType, ConnectedPlayerManager* connectedPlayerManager) { SessionManager_StartSession(self, sessionType, connectedPlayerManager); - getLogger().debug("MultiplayerSessionManager.StartSession, creating localPlayer"); - - static auto localNetworkPlayerModel = UnityEngine::Resources::FindObjectsOfTypeAll().get(0); - static auto UserInfoTask = localNetworkPlayerModel->dyn__platformUserModel()->GetUserInfo(); - static auto action = il2cpp_utils::MakeDelegate*>(classof(System::Action_1*), (std::function*)>)[&](System::Threading::Tasks::Task_1* userInfoTask) { - auto userInfo = userInfoTask->get_Result(); - if (userInfo) { - if (!localPlayer) localPlayer = Players::MpPlayerData::Init(userInfo->dyn_platformUserId(), getPlatform(userInfo->dyn_platform())); - else { - localPlayer->platformId = userInfo->dyn_platformUserId(); - localPlayer->platform = getPlatform(userInfo->dyn_platform()); - getLogger().error("got local network player, it will be null after this so no repeats"); - } - } - else getLogger().error("Failed to get local network player!"); - } - ); - if(action){ - reinterpret_cast(UserInfoTask)->ContinueWith(action); - action = nullptr; - } - - getLogger().debug("MultiplayerSessionManager.StartSession, creating localMpexPlayerData"); @@ -285,14 +147,12 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe } - //mpPacketSerializer->RegisterCallback(HandlePlayerData); - MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandlePlayerData); getLogger().debug("Callback HandlePlayerData Registered"); MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); - Players::MpexPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; - Players::MpexPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; - Players::MpexPlayerManager::disconnectedEvent += _DisconnectedHandler; + MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; + MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; + MultiplayerCore::Players::MpPlayerManager::disconnectedEvent += _DisconnectedHandler; } @@ -301,8 +161,4 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe void MultiQuestensions::Hooks::SessionManagerAndExtendedPlayerHooks() { INSTALL_HOOK(getLogger(), SessionManagerStart); INSTALL_HOOK(getLogger(), SessionManager_StartSession); - - INSTALL_HOOK(getLogger(), LobbyPlayersDataModel_sHandleMultiplayerSessionManagerPlayerConnected); - INSTALL_HOOK(getLogger(), LobbyPlayersDataModel_HandleMultiplayerSessionManagerPlayerDisconnected); - INSTALL_HOOK(getLogger(), LobbyGameStateController_HandleMultiplayerSessionManagerDisconnected); } \ No newline at end of file diff --git a/MultiQuestensions/src/Players/MpPlayerData.cpp b/MultiQuestensions/src/Players/MpPlayerData.cpp deleted file mode 100644 index 24302fd..0000000 --- a/MultiQuestensions/src/Players/MpPlayerData.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "main.hpp" -#include "Players/MpPlayerData.hpp" - -DEFINE_TYPE(MultiQuestensions::Players, MpPlayerData) - -namespace MultiQuestensions::Players { -#pragma region MpPlayerData - void MpPlayerData::New() { - getLogger().debug("Creating MpPlayerData"); - } - - MpPlayerData* MpPlayerData::Init(StringW platformID, Platform platform) - { - auto mpPlayerData = THROW_UNLESS(il2cpp_utils::New()); - - mpPlayerData->platformId = platformID; - mpPlayerData->platform = platform; - getLogger().debug("Creating MpPlayerData finished"); - return mpPlayerData; - } - - - void MpPlayerData::Serialize(LiteNetLib::Utils::NetDataWriter* writer) { - getLogger().debug("MpPlayerData::Serialize"); - - writer->Put(platformId); - writer->Put((int)platform); - getLogger().debug("Serialize MpPlayerData done"); - } - - void MpPlayerData::Deserialize(LiteNetLib::Utils::NetDataReader* reader) { - getLogger().debug("MpPlayerData::Deserialize"); - - this->platformId = reader->GetString(); - this->platform = (Platform)reader->GetInt(); - getLogger().debug("Deserialize MpPlayerData done"); - } -#pragma endregion -} \ No newline at end of file From 942a1e8afea0c1ddd00c0329d9f0b10c7c4c7558 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 23 May 2022 22:20:06 +0100 Subject: [PATCH 44/56] Fixed event dependency --- .../include/Environments/MQEAvatarPlaceLighting.hpp | 2 +- MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp index b43a69d..345ab2c 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp @@ -5,7 +5,7 @@ #include "UnityEngine/Color.hpp" #include "Players/MpexPlayerManager.hpp" -#include "Utils/event.hpp" +#include "MultiplayerCore/shared/Utils/event.hpp" DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarPlaceLighting, UnityEngine::MonoBehaviour, std::vector lights; diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index fe74298..6e9cc7d 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -11,7 +11,7 @@ #include "Players/MpexPlayerManager.hpp" #include "MultiplayerCore/shared/Players/MpPlayerData.hpp" #include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" -#include "Utils/event.hpp" +#include "MultiplayerCore/shared/Utils/event.hpp" using namespace GlobalNamespace; using namespace UnityEngine::UI; From cbea2a945a907363668098bbd07a7dd7a73287d3 Mon Sep 17 00:00:00 2001 From: cubic Date: Mon, 23 May 2022 23:46:44 +0100 Subject: [PATCH 45/56] Unordered_map instead of map --- .../include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp | 2 +- .../src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index eb0b206..14684a6 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -4,7 +4,7 @@ #include "GlobalNamespace/DisconnectedReason.hpp" extern SafePtr localMpexPlayerData; -extern std::map> _mpexPlayerData; +extern std::unordered_map> _mpexPlayerData; extern void HandlePlayerConnected(GlobalNamespace::IConnectedPlayer* player); extern void HandlePlayerDisconnected(GlobalNamespace::IConnectedPlayer* player); diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index e026f02..11de2d8 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -31,7 +31,7 @@ using namespace MultiplayerCore::Networking; using namespace GlobalNamespace; SafePtr localMpexPlayerData; -std::map> _mpexPlayerData; +std::unordered_map> _mpexPlayerData; IPlatformUserModel* platformUserModel; From c845c8d18d887d8a366b7e782672e3eb1e776dfb Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 25 May 2022 00:10:12 +0100 Subject: [PATCH 46/56] Removed safeptr stuff Should work with the safeptr removal MPCore branch --- .../include/Environments/MQEAvatarNameTag.hpp | 1 - .../SessionManagerAndExtendedPlayerHooks.hpp | 4 ++-- .../shared/Players/MpexPlayerManager.hpp | 2 +- .../src/Environments/MQEAvaterNameTag.cpp | 8 ++++---- .../SessionManagerAndMpexPlayerHooks.cpp | 19 +++++++++---------- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp index 92b8fe6..3d1f4be 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp @@ -23,7 +23,6 @@ DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarNameTag, UnityEn DECLARE_INSTANCE_METHOD(void, OnDisable); DECLARE_INSTANCE_METHOD(void, SetPlayerInfo, GlobalNamespace::IConnectedPlayer* player); - // DECLARE_INSTANCE_METHOD(void, SetExtendedPlayerInfo, MultiQuestensions::Extensions::ExtendedPlayer* extendedPlayer); DECLARE_INSTANCE_METHOD(void, SetPlatformData, MultiplayerCore::Players::MpPlayerData* data); DECLARE_INSTANCE_METHOD(void, SetSimplePlayerInfo, GlobalNamespace::IConnectedPlayer* simplePlayer); DECLARE_INSTANCE_METHOD(void, HandlePlatformData, GlobalNamespace::IConnectedPlayer* player, MultiplayerCore::Players::MpPlayerData* data); diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index 14684a6..2f3a77c 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -3,8 +3,8 @@ #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/DisconnectedReason.hpp" -extern SafePtr localMpexPlayerData; -extern std::unordered_map> _mpexPlayerData; +extern MultiQuestensions::Players::MpexPlayerData* localMpexPlayerData; +extern std::unordered_map _mpexPlayerData; extern void HandlePlayerConnected(GlobalNamespace::IConnectedPlayer* player); extern void HandlePlayerDisconnected(GlobalNamespace::IConnectedPlayer* player); diff --git a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp index 0596c8e..c895f1b 100644 --- a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp +++ b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp @@ -12,6 +12,6 @@ namespace MultiQuestensions::Players { static bool TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player); static MpexPlayerData* GetMpexPlayerData(std::string playerId); - static MultiplayerCore::event RecievedMpExPlayerData; + static MultiplayerCore::event ReceivedMpExPlayerData; }; } \ No newline at end of file diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 6e9cc7d..828bd30 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -89,8 +89,8 @@ namespace MultiQuestensions::Environments { _enabled = true; // Subscribe to events - MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData += _platformDataEventHandler; - Players::MpexPlayerManager::RecievedMpExPlayerData += _mpexPlayerDataEventHandler; + MultiplayerCore::Players::MpPlayerManager::ReceivedPlayerData += _platformDataEventHandler; + Players::MpexPlayerManager::ReceivedMpExPlayerData += _mpexPlayerDataEventHandler; // Set player info if (_playerInfo != nullptr) @@ -103,8 +103,8 @@ namespace MultiQuestensions::Environments { _enabled = false; // Unsubscribe from events - MultiplayerCore::Players::MpPlayerManager::RecievedPlayerData -= _platformDataEventHandler; - Players::MpexPlayerManager::RecievedMpExPlayerData -= _mpexPlayerDataEventHandler; + MultiplayerCore::Players::MpPlayerManager::ReceivedPlayerData -= _platformDataEventHandler; + Players::MpexPlayerManager::ReceivedMpExPlayerData -= _mpexPlayerDataEventHandler; } #pragma region Set Player Info diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 11de2d8..f771156 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -30,12 +30,12 @@ using namespace MultiQuestensions; using namespace MultiplayerCore::Networking; using namespace GlobalNamespace; -SafePtr localMpexPlayerData; -std::unordered_map> _mpexPlayerData; +Players::MpexPlayerData* localMpexPlayerData; +std::unordered_map _mpexPlayerData; IPlatformUserModel* platformUserModel; -MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData; +MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::ReceivedMpExPlayerData; MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerConnected); MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected); @@ -44,7 +44,7 @@ MultiplayerCore::event_handler _Disconnecte bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { - player = static_cast(_mpexPlayerData.at(playerId)); + player = _mpexPlayerData.at(playerId); return true; } return false; @@ -52,7 +52,7 @@ bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::st MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpexPlayerData(std::string playerId) { if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { - return static_cast(_mpexPlayerData.at(playerId)); + return _mpexPlayerData.at(playerId); } return nullptr; } @@ -73,8 +73,8 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl } SetPlayerPlaceColor(player, packet->Color, true); - getLogger().info("Calling event 'RecievedMpExPlayerData'"); - MultiQuestensions::Players::MpexPlayerManager::RecievedMpExPlayerData(player, packet); + getLogger().info("Calling event 'ReceivedMpExPlayerData'"); + MultiQuestensions::Players::MpexPlayerManager::ReceivedMpExPlayerData(player, packet); } } @@ -108,7 +108,6 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { if (_mpexPlayerData.contains(userId)) { getLogger().info("Reseting platform lights for Player '%s'", userId.c_str()); SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); - _mpexPlayerData.at(userId).~SafePtr(); _mpexPlayerData.erase(userId); } } @@ -147,8 +146,8 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe } - getLogger().debug("Callback HandlePlayerData Registered"); - MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); + getLogger().debug("Callback HandlePlayerData Registered"); + MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); //TODO should be fine? MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; From be3fabe232f3d97290799059d83f58a7e8ac6d59 Mon Sep 17 00:00:00 2001 From: cubic Date: Wed, 25 May 2022 17:50:27 +0100 Subject: [PATCH 47/56] Now uses the register packet event from mp core --- .../SessionManagerAndExtendedPlayerHooks.hpp | 4 ++++ .../Hooks/SessionManagerAndMpexPlayerHooks.cpp | 16 ++++++++++++---- MultiQuestensions/src/UI/LobbySetupPanel.cpp | 3 +++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index 2f3a77c..ccc0b07 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -2,6 +2,8 @@ #include "Players/MpexPlayerData.hpp" #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/DisconnectedReason.hpp" +#include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" +#include "MultiplayerCore/shared/Networking/MpNetworkingEvents.hpp" extern MultiQuestensions::Players::MpexPlayerData* localMpexPlayerData; extern std::unordered_map _mpexPlayerData; @@ -9,3 +11,5 @@ extern std::unordered_map MultiQuestensions::Players::MpexPlayerManager::ReceivedMpExPlayerData; +MultiplayerCore::event_handler _RegisterMpexPacketsHandler = MultiplayerCore::event_handler(HandleRegisterMpexPackets); + + MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerConnected); MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected); MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect); @@ -78,6 +83,11 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl } } +void HandleRegisterMpexPackets(MultiplayerCore::Networking::MpPacketSerializer* _mpPacketSerializer) { + + _mpPacketSerializer->RegisterCallback(HandleMpexData); + getLogger().debug("Callback HandleMpexData Registered"); +} void HandlePlayerConnected(IConnectedPlayer* player) { try { @@ -145,10 +155,6 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe localMpexPlayerData->Color = config.getPlayerColor(); } - - getLogger().debug("Callback HandlePlayerData Registered"); - MultiplayerCore::Networking::MpPacketSerializer::RegisterCallbackStatic(HandleMpexData); //TODO should be fine? - MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; MultiplayerCore::Players::MpPlayerManager::disconnectedEvent += _DisconnectedHandler; @@ -158,6 +164,8 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe void MultiQuestensions::Hooks::SessionManagerAndExtendedPlayerHooks() { + MultiplayerCore::Networking::MpNetworkingEvents::RegisterPackets += _RegisterMpexPacketsHandler; + INSTALL_HOOK(getLogger(), SessionManagerStart); INSTALL_HOOK(getLogger(), SessionManager_StartSession); } \ No newline at end of file diff --git a/MultiQuestensions/src/UI/LobbySetupPanel.cpp b/MultiQuestensions/src/UI/LobbySetupPanel.cpp index 30a96c7..f73c44d 100644 --- a/MultiQuestensions/src/UI/LobbySetupPanel.cpp +++ b/MultiQuestensions/src/UI/LobbySetupPanel.cpp @@ -83,6 +83,7 @@ namespace MultiQuestensions::UI { //QuestUI::BeatSaberUI::CreateColorPickerModal(parent->get_transform(), "Player Color Selection", playerColor); auto colorPicker = QuestUI::BeatSaberUI::CreateColorPickerModal(parent, "Player Color Selection", playerColor, + //Done [&playerColor, sessionManager](UnityEngine::Color value) { playerColor = value; config.setPlayerColor(value); @@ -97,12 +98,14 @@ namespace MultiQuestensions::UI { // packetManager->Send(reinterpret_cast(localPlayerPacket)); MultiplayerCore::mpPacketSerializer->Send(localMpexPlayerData); }, + //Cancel [sessionManager] { SetPlayerPlaceColor(sessionManager->get_localPlayer(), localMpexPlayerData->Color, true); //Extensions::ExtendedPlayerPacket* localPlayerPacket = Extensions::ExtendedPlayerPacket::Init(localExtendedPlayer->get_platformID(), localExtendedPlayer->get_platform(), localExtendedPlayer->get_playerColor()); //getLogger().debug("LocalPlayer Color is, R: %f G: %f B: %f", localPlayerPacket->playerColor.r, localPlayerPacket->playerColor.g, localPlayerPacket->playerColor.b); //packetManager->Send(reinterpret_cast(localPlayerPacket)); }, + //OnChange [sessionManager](UnityEngine::Color value) { SetPlayerPlaceColor(sessionManager->get_localPlayer(), value, true); // TODO: Uncomment when MpEx supports live platform color updates or maybe not because that might be too much packets sent From 931d3809af6f17134531cebf7c9f66c8c3d3a537 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 27 May 2022 23:37:00 +0200 Subject: [PATCH 48/56] Update for 1.22.0 MPCore scads_refactor branch --- .../include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp | 2 +- MultiQuestensions/qpm.json | 6 +++--- .../src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index ccc0b07..3ef1a71 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -10,6 +10,6 @@ extern std::unordered_map MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerConnected); MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected); -MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect); +MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect); bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { @@ -128,7 +128,7 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { } -void HandleDisconnect(DisconnectedReason reason) { +void HandleDisconnect(DisconnectedReason reason, GlobalNamespace::IConnectedPlayer* locPlayer) { getLogger().info("Disconnected from server reason: '%s'", MultiplayerCore::EnumUtils::GetEnumName(reason).c_str()); getLogger().info("Clearing MPEX player data"); _mpexPlayerData.clear(); From 24436406c299181c0cb2c49556f96f4d3a65c9b4 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Fri, 27 May 2022 23:37:41 +0200 Subject: [PATCH 49/56] Remove generated mod.json --- MultiQuestensions/mod.json | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 MultiQuestensions/mod.json diff --git a/MultiQuestensions/mod.json b/MultiQuestensions/mod.json deleted file mode 100644 index 3418090..0000000 --- a/MultiQuestensions/mod.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "_QPVersion": "0.1.1", - "name": "MultiQuestensions", - "id": "MultiQuestensions", - "author": "EnderdracheLP and Goobie", - "version": "1.0.0", - "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.21.0", - "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", - "dependencies": [ - { - "version": "^0.15.9", - "id": "custom-types", - "downloadIfMissing": "https://github.com/sc2ad/Il2CppQuestTypePatching/releases/download/v0.15.10/CustomTypes.qmod" - }, - { - "version": "^0.22.0", - "id": "codegen", - "downloadIfMissing": "https://github.com/sc2ad/BeatSaber-Quest-Codegen/releases/download/v0.22.0/Codegen.qmod" - }, - { - "version": "^0.13.1", - "id": "questui", - "downloadIfMissing": "https://github.com/darknight1050/questui/releases/download/v0.13.5/QuestUI.qmod" - } - ], - "modFiles": [ - "libMultiQuestensions.so" - ], - "libraryFiles": [ - "libbeatsaber-hook_3_8_5.so" - ], - "fileCopies": [], - "copyExtensions": [] -} \ No newline at end of file From f6a09a6826f05d28856a52fc58b7264c1b56cf67 Mon Sep 17 00:00:00 2001 From: Michael R Date: Sat, 28 May 2022 00:07:28 +0200 Subject: [PATCH 50/56] Bump mod.template.json Gameversion --- MultiQuestensions/mod.template.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MultiQuestensions/mod.template.json b/MultiQuestensions/mod.template.json index 6d708d9..3b3555d 100644 --- a/MultiQuestensions/mod.template.json +++ b/MultiQuestensions/mod.template.json @@ -5,7 +5,7 @@ "author": "EnderdracheLP and Goobie", "version": "${version}", "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.21.0", + "packageVersion": "1.22.0", "description": "Lightweight port of MultiplayerExtensions, the PC mod that adds features to Multiplayer.!", "dependencies": [ ], @@ -13,4 +13,4 @@ "libraryFiles": [], "fileCopies": [], "copyExtensions": [] -} \ No newline at end of file +} From a07ac5b4c651e5be9beb84833d91ff1eccd5385c Mon Sep 17 00:00:00 2001 From: cubic Date: Sat, 28 May 2022 13:15:20 +0100 Subject: [PATCH 51/56] Removed deprecated dyn__'s And changed sessionmanager stff to use MPCore events instead of hooks --- MultiQuestensions/include/GlobalFields.hpp | 4 +- .../SessionManagerAndExtendedPlayerHooks.hpp | 7 ++- MultiQuestensions/qpm.json | 6 ++- .../shared/Players/MpexPlayerManager.hpp | 4 +- .../Environments/MQEAvatarPlaceLighting.cpp | 6 +-- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 23 ++++----- .../src/Hooks/InstallerHooks.cpp | 1 - .../SessionManagerAndMpexPlayerHooks.cpp | 49 +++++++++---------- MultiQuestensions/src/UI/LobbySetupPanel.cpp | 4 +- MultiQuestensions/src/main.cpp | 10 ++-- 10 files changed, 58 insertions(+), 56 deletions(-) diff --git a/MultiQuestensions/include/GlobalFields.hpp b/MultiQuestensions/include/GlobalFields.hpp index b5ed5c9..86f315a 100644 --- a/MultiQuestensions/include/GlobalFields.hpp +++ b/MultiQuestensions/include/GlobalFields.hpp @@ -1,6 +1,6 @@ #pragma once //#include "main.hpp" -#include "GlobalNamespace/MultiplayerSessionManager.hpp" +//#include "GlobalNamespace/MultiplayerSessionManager.hpp" #include "GlobalNamespace/LobbyPlayersDataModel.hpp" #include "GlobalNamespace/LobbyGameStateController.hpp" @@ -10,7 +10,7 @@ //#include "System/Collections/Generic/Dictionary_2.hpp" namespace MultiQuestensions { // Plugin setup stuff - extern GlobalNamespace::MultiplayerSessionManager* sessionManager; + //extern GlobalNamespace::MultiplayerSessionManager* sessionManager; extern GlobalNamespace::LobbyPlayersDataModel* lobbyPlayersDataModel; extern GlobalNamespace::LobbyGameStateController* lobbyGameStateController; } diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index 3ef1a71..2588eae 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -10,6 +10,9 @@ extern std::unordered_map ReceivedMpExPlayerData; }; diff --git a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp index 172c1e1..81d1e63 100644 --- a/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp +++ b/MultiQuestensions/src/Environments/MQEAvatarPlaceLighting.cpp @@ -35,9 +35,9 @@ namespace MultiQuestensions::Environments { // // return; // // } - // // for (int i = 0; i < _sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - // // if (_sessionManager->dyn__connectedPlayers()->get_Item(i)->get_sortIndex() == SortIndex) { - // // auto player = _sessionManager->dyn__connectedPlayers()->get_Item(i); + // // for (int i = 0; i < _sessionManager->connectedPlayers->get_Count(); i++) { + // // if (_sessionManager->connectedPlayers->get_Item(i)->get_sortIndex() == SortIndex) { + // // auto player = _sessionManager->connectedPlayers->get_Item(i); // // auto mpexPlayerData = MpexPlayerManager::GetPlayer(player->get_playerId()); // // this->SetColor(mpexPlayerData ? mpexPlayerData->get_color() : Config::DefaultPlayerColor, true); // // return; diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index a060951..ca199d4 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -1,6 +1,7 @@ #include "main.hpp" #include "Hooks/Hooks.hpp" #include "GlobalFields.hpp" +#include "MultiplayerCore/shared/GlobalFields.hpp" #include "Hooks/EnvironmentAndAvatarHooks.hpp" #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" #include "Environments/MQEAvatarPlaceLighting.hpp" @@ -123,12 +124,12 @@ namespace MultiQuestensions { { SetAllPlayerPlaceColors(Color::get_black(), true); //getLogger().debug("SetDefaultPlayerPlaceColors, set local player color"); - SetPlayerPlaceColor(sessionManager->get_localPlayer(), config.getPlayerColor(), true); + SetPlayerPlaceColor(MultiplayerCore::_multiplayerSessionManager->get_localPlayer(), config.getPlayerColor(), true); using System::Collections::Generic::List_1; - for (int i = 0; i < reinterpret_cast*>(sessionManager->get_connectedPlayers())->get_Count(); i++) { - auto player = sessionManager->get_connectedPlayers()->get_Item(i); + for (int i = 0; i < reinterpret_cast*>(MultiplayerCore::_multiplayerSessionManager->get_connectedPlayers())->get_Count(); i++) { + auto player = MultiplayerCore::_multiplayerSessionManager->get_connectedPlayers()->get_Item(i); std::string userId = player->get_userId(); - if (userId == static_cast(sessionManager->get_localPlayer()->get_userId())) continue; + if (userId == static_cast(MultiplayerCore::_multiplayerSessionManager->get_localPlayer()->get_userId())) continue; //getLogger().debug("SetDefaultPlayerPlaceColors, set player color for userId %s", userId.c_str()); if (_mpexPlayerData.contains(userId)) { //getLogger().debug("SetDefaultPlayerPlaceColors, found MpexPlayerData setting color for player %s", userId.c_str()); @@ -159,8 +160,8 @@ namespace MultiQuestensions { avatarPlaces.push_back(avatarPlace); } - innerCircleRadius = _placeManager->dyn__innerCircleRadius(); - minOuterCircleRadius = _placeManager->dyn__minOuterCircleRadius(); + innerCircleRadius = _placeManager->innerCircleRadius; + minOuterCircleRadius = _placeManager->minOuterCircleRadius; angleBetweenPlayersWithEvenAdjustment = MultiplayerPlayerPlacement::GetAngleBetweenPlayersWithEvenAdjustment(_lobbyStateDataModel->get_configuration().maxPlayerCount, MultiplayerPlayerLayout::Circle); outerCircleRadius = fmax(MultiplayerPlayerPlacement::GetOuterCircleRadius(angleBetweenPlayersWithEvenAdjustment, innerCircleRadius), minOuterCircleRadius); @@ -175,7 +176,7 @@ namespace MultiQuestensions { _placeManager = Resources::FindObjectsOfTypeAll()[0]; _menuEnvironmentManager = Resources::FindObjectsOfTypeAll()[0]; _stageManager = Resources::FindObjectsOfTypeAll()[0]; - _lobbyStateDataModel = _placeManager->dyn__lobbyStateDataModel(); + _lobbyStateDataModel = _placeManager->lobbyStateDataModel; MultiplayerLobbyController_ActivateMultiplayerLobby(self); @@ -184,7 +185,7 @@ namespace MultiQuestensions { MAKE_HOOK_MATCH(LightWithIdMonoBehaviour_RegisterLight, &LightWithIdMonoBehaviour::RegisterLight, void, LightWithIdMonoBehaviour* self) { if ((self && self->get_transform() && self->get_transform()->get_parent() && self->get_transform()->get_parent()->get_name()->Contains("LobbyAvatarPlace"))){ - if(!self->dyn__isRegistered()){ + if(!self->isRegistered){ //getLogger().debug("MQE registering a MQEAvatarPlaceLighting or light that has the lobby avatar place as a parent"); LightWithIdMonoBehaviour_RegisterLight(self); } @@ -200,7 +201,7 @@ namespace MultiQuestensions { { //getLogger().debug("Start GetAvatarController: _refPlayerIdToAvatarMap"); if (_refPlayerIdToAvatarMap == nullptr && _avatarManager) - _refPlayerIdToAvatarMap = _avatarManager->dyn__playerIdToAvatarMap(); + _refPlayerIdToAvatarMap = _avatarManager->playerIdToAvatarMap; //getLogger().debug("Start GetAvatarController: _refPlayerIdToAvatarMap Done"); @@ -238,8 +239,8 @@ namespace MultiQuestensions { void UpdateNameTagIcons() { getLogger().debug("Start UpdateNameTagIcons"); - for (int i = 0; i < MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Count(); i++) { - auto player = MultiplayerCore::_multiplayerSessionManager->dyn__connectedPlayers()->get_Item(i); + for (int i = 0; i < MultiplayerCore::_multiplayerSessionManager->connectedPlayers->get_Count(); i++) { + auto player = MultiplayerCore::_multiplayerSessionManager->connectedPlayers->get_Item(i); auto objAvatarCaption = GetAvatarCaptionObject(player->get_userId()); getLogger().debug("Finding GetAvatarCaptionObject"); if (objAvatarCaption == nullptr) { diff --git a/MultiQuestensions/src/Hooks/InstallerHooks.cpp b/MultiQuestensions/src/Hooks/InstallerHooks.cpp index 3f4f591..c62110b 100644 --- a/MultiQuestensions/src/Hooks/InstallerHooks.cpp +++ b/MultiQuestensions/src/Hooks/InstallerHooks.cpp @@ -8,7 +8,6 @@ namespace MultiQuestensions { MAKE_HOOK_MATCH(MultiplayerConnectedPlayerBeatmapObjectEventManager_Start, &MultiplayerConnectedPlayerBeatmapObjectEventManager::Start, void, MultiplayerConnectedPlayerBeatmapObjectEventManager* self) { //getLogger().debug("MultiplayerConnectedPlayerBeatmapObjectEventManager_Start, checking if lag reducer is enabled"); - // getLogger().debug("ZenMode: '%s'", self->dyn__sceneSetupData()->dyn_gameplayModifiers()->dyn__zenMode() ? "true" : "false"); if (!config.getLagReducer()) MultiplayerConnectedPlayerBeatmapObjectEventManager_Start(self); } diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index c863a1c..544c218 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -26,7 +26,7 @@ #include "Players/MpexPlayerManager.hpp" #include "MultiplayerCore/shared/Players/MpPlayerData.hpp" #include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" - +#include "MultiplayerCore/shared/GlobalFields.hpp" using namespace MultiQuestensions; using namespace MultiplayerCore::Networking; @@ -35,19 +35,21 @@ using namespace GlobalNamespace; Players::MpexPlayerData* localMpexPlayerData; std::unordered_map _mpexPlayerData; -IPlatformUserModel* platformUserModel; +IPlatformUserModel* platformUserModel; //TODO what is this used for and why is it here MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::ReceivedMpExPlayerData; MultiplayerCore::event_handler _RegisterMpexPacketsHandler = MultiplayerCore::event_handler(HandleRegisterMpexPackets); +MultiplayerCore::event_handler _UnRegisterMpexPacketsHandler = MultiplayerCore::event_handler(HandleUnRegisterMpexPackets); MultiplayerCore::event_handler _PlayerConnectedHandler = MultiplayerCore::event_handler(HandlePlayerConnected); MultiplayerCore::event_handler _PlayerDisconnectedHandler = MultiplayerCore::event_handler(HandlePlayerDisconnected); +MultiplayerCore::event_handler _ConnectingHandler = MultiplayerCore::event_handler(HandleConnecting); MultiplayerCore::event_handler _DisconnectedHandler = MultiplayerCore::event_handler(HandleDisconnect); -bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::string playerId, MultiQuestensions::Players::MpexPlayerData*& player) { +bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::string const& playerId, MultiQuestensions::Players::MpexPlayerData*& player) { if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { player = _mpexPlayerData.at(playerId); return true; @@ -55,7 +57,7 @@ bool MultiQuestensions::Players::MpexPlayerManager::TryGetMpexPlayerData(std::st return false; } -MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpexPlayerData(std::string playerId) { +MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlayerManager::GetMpexPlayerData(std::string const& playerId) { if (_mpexPlayerData.find(playerId) != _mpexPlayerData.end()) { return _mpexPlayerData.at(playerId); } @@ -64,7 +66,7 @@ MultiQuestensions::Players::MpexPlayerData* MultiQuestensions::Players::MpexPlay static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* player) { if(player){ - const std::string userId = to_utf8(csstrtostr(player->get_userId())); + std::string const& userId = player->get_userId(); if (_mpexPlayerData.contains(userId)) { getLogger().info("Recieved 'MpexPlayerData', player already exists"); _mpexPlayerData[userId] = packet; @@ -76,7 +78,6 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl ); _mpexPlayerData.emplace(userId, packet); } - SetPlayerPlaceColor(player, packet->Color, true); getLogger().info("Calling event 'ReceivedMpExPlayerData'"); MultiQuestensions::Players::MpexPlayerManager::ReceivedMpExPlayerData(player, packet); @@ -84,23 +85,25 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl } void HandleRegisterMpexPackets(MultiplayerCore::Networking::MpPacketSerializer* _mpPacketSerializer) { - _mpPacketSerializer->RegisterCallback(HandleMpexData); getLogger().debug("Callback HandleMpexData Registered"); } +void HandleUnRegisterMpexPackets(MultiplayerCore::Networking::MpPacketSerializer* _mpPacketSerializer) { + _mpPacketSerializer->UnregisterCallback(); + getLogger().debug("Callback HandleMpexData UnRegistered"); +} void HandlePlayerConnected(IConnectedPlayer* player) { try { getLogger().debug("MpEx HandlePlayerConnected"); if (player) { - getLogger().info("Player '%s' joined", static_cast(player->get_userId()).c_str()); + getLogger().info("MpExPlayer '%s' joined", static_cast(player->get_userId()).c_str()); getLogger().debug("Sending MpexPlayerData"); if (localMpexPlayerData) { MultiplayerCore::mpPacketSerializer->Send(localMpexPlayerData->ToSerializable()); getLogger().debug("MpexPlayerData sent"); } - SetPlayerPlaceColor(player, Config::DefaultPlayerColor, false); } } @@ -113,7 +116,7 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { try { getLogger().debug("MpEx HandlePlayerDisconnected"); if (player) { - const std::string userId = to_utf8(csstrtostr(player->get_userId())); + std::string const& userId = player->get_userId(); getLogger().info("Player '%s' left", userId.c_str()); if (_mpexPlayerData.contains(userId)) { getLogger().info("Reseting platform lights for Player '%s'", userId.c_str()); @@ -122,13 +125,13 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { } } } - catch (const std::runtime_error& e) { + catch (const std::runtime_error& e) { getLogger().error("REPORT TO ENDER: %s", e.what()); } } -void HandleDisconnect(DisconnectedReason reason, GlobalNamespace::IConnectedPlayer* locPlayer) { +void HandleDisconnect(DisconnectedReason reason, GlobalNamespace::IConnectedPlayer* localPlayer) { getLogger().info("Disconnected from server reason: '%s'", MultiplayerCore::EnumUtils::GetEnumName(reason).c_str()); getLogger().info("Clearing MPEX player data"); _mpexPlayerData.clear(); @@ -136,24 +139,20 @@ void HandleDisconnect(DisconnectedReason reason, GlobalNamespace::IConnectedPlay MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent -= _PlayerDisconnectedHandler; MultiplayerCore::Players::MpPlayerManager::disconnectedEvent -= _DisconnectedHandler; -} - -MAKE_HOOK_MATCH(SessionManagerStart, &MultiplayerSessionManager::Start, void, MultiplayerSessionManager* self) { - - sessionManager = self; - SessionManagerStart(sessionManager); + MultiplayerCore::Networking::MpNetworkingEvents::RegisterPackets -= _RegisterMpexPacketsHandler; + MultiplayerCore::Networking::MpNetworkingEvents::UnRegisterPackets -= _UnRegisterMpexPacketsHandler; } -MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSession, void, MultiplayerSessionManager* self, MultiplayerSessionManager_SessionType sessionType, ConnectedPlayerManager* connectedPlayerManager) { - SessionManager_StartSession(self, sessionType, connectedPlayerManager); - - getLogger().debug("MultiplayerSessionManager.StartSession, creating localMpexPlayerData"); +void HandleConnecting(GlobalNamespace::IConnectedPlayer* localPlayer){ + getLogger().debug("HandleConnecting, creating localMpexPlayerData and registering events"); if(!localMpexPlayerData){ localMpexPlayerData = Players::MpexPlayerData::New_ctor(); localMpexPlayerData->Color = config.getPlayerColor(); } + MultiplayerCore::Networking::MpNetworkingEvents::RegisterPackets += _RegisterMpexPacketsHandler; + MultiplayerCore::Networking::MpNetworkingEvents::UnRegisterPackets += _UnRegisterMpexPacketsHandler; MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent += _PlayerConnectedHandler; MultiplayerCore::Players::MpPlayerManager::playerDisconnectedEvent += _PlayerDisconnectedHandler; @@ -161,11 +160,7 @@ MAKE_HOOK_MATCH(SessionManager_StartSession, &MultiplayerSessionManager::StartSe } - - void MultiQuestensions::Hooks::SessionManagerAndExtendedPlayerHooks() { - MultiplayerCore::Networking::MpNetworkingEvents::RegisterPackets += _RegisterMpexPacketsHandler; - INSTALL_HOOK(getLogger(), SessionManagerStart); - INSTALL_HOOK(getLogger(), SessionManager_StartSession); + MultiplayerCore::Players::MpPlayerManager::connectingEvent += _ConnectingHandler; } \ No newline at end of file diff --git a/MultiQuestensions/src/UI/LobbySetupPanel.cpp b/MultiQuestensions/src/UI/LobbySetupPanel.cpp index f73c44d..0962c87 100644 --- a/MultiQuestensions/src/UI/LobbySetupPanel.cpp +++ b/MultiQuestensions/src/UI/LobbySetupPanel.cpp @@ -156,8 +156,8 @@ namespace MultiQuestensions::UI { ); QuestUI::BeatSaberUI::AddHoverHint(colorPickerButton->get_gameObject(), "Lets you pick your own personal platform and Name Tag color for everyone to see."); - lobbySetupViewController->dyn__spectatorWarningTextWrapper()->get_transform()->SetParent(parent->get_transform()); - lobbySetupViewController->dyn__spectatorWarningTextWrapper()->get_transform()->set_localPosition({ 0, -20, 0 }); + lobbySetupViewController->spectatorWarningTextWrapper->get_transform()->SetParent(parent->get_transform()); + lobbySetupViewController->spectatorWarningTextWrapper->get_transform()->set_localPosition({ 0, -20, 0 }); //customSongsToggle = QuestUI::BeatSaberUI::CreateToggle(vertical2->get_transform(), "Custom Songs", getConfig().config["customsongs"].GetBool(), SetCustomSongs); //QuestUI::BeatSaberUI::AddHoverHint(customSongsToggle->get_gameObject(), "Toggles custom songs for all players"); } diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 859da1f..100707c 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -14,6 +14,7 @@ #include "custom-types/shared/register.hpp" #include "questui/shared/QuestUI.hpp" #include "questui/shared/BeatSaberUI.hpp" +#include "MultiplayerCore/shared/GlobalFields.hpp" //#include "GlobalNamespace/LobbySetupViewController.hpp" @@ -60,17 +61,16 @@ Config MultiQuestensions::config; namespace MultiQuestensions { // Plugin setup stuff - GlobalNamespace::MultiplayerSessionManager* sessionManager; + //GlobalNamespace::MultiplayerSessionManager* sessionManager; GlobalNamespace::LobbyPlayersDataModel* lobbyPlayersDataModel; - // MultiQuestensions::PacketManager* packetManager; GlobalNamespace::LobbyGameStateController* lobbyGameStateController; LobbySetupViewController* lobbySetupView; bool AllPlayersModded() { getLogger().debug("MQE AllPlayersModded"); - for (int i = 0; i < sessionManager->dyn__connectedPlayers()->get_Count(); i++) { - if (!sessionManager->dyn__connectedPlayers()->get_Item(i)->HasState("modded")) return false; + for (int i = 0; i < MultiplayerCore::_multiplayerSessionManager->connectedPlayers->get_Count(); i++) { + if (!MultiplayerCore::_multiplayerSessionManager->connectedPlayers->get_Item(i)->HasState("modded")) return false; } return true; } @@ -86,7 +86,7 @@ MAKE_HOOK_MATCH(LobbySetupViewController_DidActivate, &LobbySetupViewController: lobbySetupView = self; LobbySetupViewController_DidActivate(self, firstActivation, addedToHierarchy, screenSystemEnabling); if (firstActivation) { - MultiQuestensions::UI::LobbySetupPanel::AddSetupPanel(self->get_rectTransform(), sessionManager, self); + MultiQuestensions::UI::LobbySetupPanel::AddSetupPanel(self->get_rectTransform(), MultiplayerCore::_multiplayerSessionManager, self); } } From c9829a0533472f3019473e7d452b1179ebc0f336 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 29 May 2022 22:29:05 +0200 Subject: [PATCH 52/56] Fix localMpexPlayerData being invalid --- .../src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 544c218..516ecb3 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -6,7 +6,6 @@ #include "Players/MpexPlayerManager.hpp" #include "Config.hpp" -#include "GlobalNamespace/IPlatformUserModel.hpp" #include "GlobalNamespace/LocalNetworkPlayerModel.hpp" #include "UnityEngine/Resources.hpp" #include "GlobalNamespace/UserInfo.hpp" @@ -33,10 +32,9 @@ using namespace MultiplayerCore::Networking; using namespace GlobalNamespace; Players::MpexPlayerData* localMpexPlayerData; +// TODO: Check the Players::MpexPlayerData* instances don't get GC'd before getting placed in their CT std::unordered_map _mpexPlayerData; -IPlatformUserModel* platformUserModel; //TODO what is this used for and why is it here - MultiplayerCore::event MultiQuestensions::Players::MpexPlayerManager::ReceivedMpExPlayerData; MultiplayerCore::event_handler _RegisterMpexPacketsHandler = MultiplayerCore::event_handler(HandleRegisterMpexPackets); @@ -68,7 +66,7 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl if(player){ std::string const& userId = player->get_userId(); if (_mpexPlayerData.contains(userId)) { - getLogger().info("Recieved 'MpexPlayerData', player already exists"); + getLogger().info("Received 'MpexPlayerData', player already exists"); _mpexPlayerData[userId] = packet; } else { @@ -142,13 +140,19 @@ void HandleDisconnect(DisconnectedReason reason, GlobalNamespace::IConnectedPlay MultiplayerCore::Networking::MpNetworkingEvents::RegisterPackets -= _RegisterMpexPacketsHandler; MultiplayerCore::Networking::MpNetworkingEvents::UnRegisterPackets -= _UnRegisterMpexPacketsHandler; + + // Clear our manually created localMpexPlayerData instance + if(localMpexPlayerData){ + gc_free_specific(localMpexPlayerData); + localMpexPlayerData = nullptr; + } } void HandleConnecting(GlobalNamespace::IConnectedPlayer* localPlayer){ getLogger().debug("HandleConnecting, creating localMpexPlayerData and registering events"); if(!localMpexPlayerData){ - localMpexPlayerData = Players::MpexPlayerData::New_ctor(); + localMpexPlayerData = Players::MpexPlayerData::New_ctor<::il2cpp_utils::CreationType::Manual>(); localMpexPlayerData->Color = config.getPlayerColor(); } MultiplayerCore::Networking::MpNetworkingEvents::RegisterPackets += _RegisterMpexPacketsHandler; From 85e67fabf5e1c399a5a97f9f22cebde5e0c27b84 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Sun, 29 May 2022 22:42:42 +0200 Subject: [PATCH 53/56] Remove the ToSerializable() method, not needed --- MultiQuestensions/shared/Players/MpexPlayerData.hpp | 4 ---- .../src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/MultiQuestensions/shared/Players/MpexPlayerData.hpp b/MultiQuestensions/shared/Players/MpexPlayerData.hpp index fa0afad..edec2d8 100644 --- a/MultiQuestensions/shared/Players/MpexPlayerData.hpp +++ b/MultiQuestensions/shared/Players/MpexPlayerData.hpp @@ -15,8 +15,4 @@ DECLARE_CLASS_CUSTOM_DLL(MultiQuestensions::Players, MpexPlayerData, Multiplayer DECLARE_OVERRIDE_METHOD(void, Serialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Serialize", 1), LiteNetLib::Utils::NetDataWriter* writer); DECLARE_OVERRIDE_METHOD(void, Deserialize, il2cpp_utils::FindMethodUnsafe(classof(MultiplayerCore::Networking::Abstractions::MpPacket*), "Deserialize", 1), LiteNetLib::Utils::NetDataReader* reader); - - public: - operator LiteNetLib::Utils::INetSerializable*() { return reinterpret_cast(this); } - LiteNetLib::Utils::INetSerializable* ToSerializable() { return reinterpret_cast(this); } ) \ No newline at end of file diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 516ecb3..9ecfd64 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -99,7 +99,7 @@ void HandlePlayerConnected(IConnectedPlayer* player) { getLogger().debug("Sending MpexPlayerData"); if (localMpexPlayerData) { - MultiplayerCore::mpPacketSerializer->Send(localMpexPlayerData->ToSerializable()); + MultiplayerCore::mpPacketSerializer->Send(localMpexPlayerData); getLogger().debug("MpexPlayerData sent"); } SetPlayerPlaceColor(player, Config::DefaultPlayerColor, false); From 8eb8a67a2c6b19bc6f414b7a55d24d36b9359bf9 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Mon, 30 May 2022 19:45:28 +0200 Subject: [PATCH 54/56] Possibly fix nametag issues + optimizations --- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 27 ++++++------------- .../SessionManagerAndMpexPlayerHooks.cpp | 12 ++++++++- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index ca199d4..66a2d2d 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -38,11 +38,6 @@ using namespace System::Collections::Generic; namespace MultiQuestensions { #pragma region Fields - ILobbyStateDataModel* _lobbyStateDataModel; - MenuEnvironmentManager* _menuEnvironmentManager; - MultiplayerLobbyAvatarPlaceManager* _placeManager; - MultiplayerLobbyCenterStageManager* _stageManager; - std::vector avatarPlaces; float innerCircleRadius; @@ -61,7 +56,7 @@ namespace MultiQuestensions { MQEAvatarPlaceLighting* GetConnectedPlayerPlace(IConnectedPlayer* player) { //getLogger().debug("GetConnectedPlayerPlace, lighting"); - int sortIndex = _lobbyStateDataModel->get_localPlayer()->get_sortIndex(); + int sortIndex = MultiplayerCore::_multiplayerSessionManager->get_localPlayer()->get_sortIndex(); //getLogger().debug("GetConnectedPlayerPlace sortIndex %d, angleBetweenPlayersWithEvenAdjustment %f", sortIndex, angleBetweenPlayersWithEvenAdjustment); //static auto* sortIndexMethod = THROW_UNLESS(il2cpp_utils::FindMethodUnsafe(classof(IConnectedPlayer*), "get_sortIndex", 0)); //int playerSortIndex = il2cpp_utils::RunMethodThrow(player, sortIndexMethod); @@ -129,23 +124,17 @@ namespace MultiQuestensions { for (int i = 0; i < reinterpret_cast*>(MultiplayerCore::_multiplayerSessionManager->get_connectedPlayers())->get_Count(); i++) { auto player = MultiplayerCore::_multiplayerSessionManager->get_connectedPlayers()->get_Item(i); std::string userId = player->get_userId(); + // If user is us, we skip if (userId == static_cast(MultiplayerCore::_multiplayerSessionManager->get_localPlayer()->get_userId())) continue; - //getLogger().debug("SetDefaultPlayerPlaceColors, set player color for userId %s", userId.c_str()); if (_mpexPlayerData.contains(userId)) { - //getLogger().debug("SetDefaultPlayerPlaceColors, found MpexPlayerData setting color for player %s", userId.c_str()); SetPlayerPlaceColor(player, _mpexPlayerData.at(userId)->Color, true); } else { - //getLogger().debug("SetDefaultPlayerPlaceColors, did not find MpexPlayerData setting default color for player %s", userId.c_str()); SetPlayerPlaceColor(player, Config::DefaultPlayerColor, true); } } - - // for (auto& [key, extendedPlayer] : _mpexPlayerData) { - // SetPlayerPlaceColor(reinterpret_cast(extendedPlayer->get_self()), extendedPlayer->get_playerColor(), true); - // } } - void HandleLobbyEnvironmentLoaded() { + void HandleLobbyEnvironmentLoaded(ILobbyStateDataModel* _lobbyStateDataModel, MenuEnvironmentManager* _menuEnvironmentManager, MultiplayerLobbyAvatarPlaceManager* _placeManager, MultiplayerLobbyCenterStageManager* _stageManager) { initialized = false; getLogger().debug("HandleLobbyEnvironmentLoaded start"); auto nativeAvatarPlaces = Resources::FindObjectsOfTypeAll(); @@ -173,14 +162,14 @@ namespace MultiQuestensions { MAKE_HOOK_MATCH(MultiplayerLobbyController_ActivateMultiplayerLobby, &MultiplayerLobbyController::ActivateMultiplayerLobby, void, MultiplayerLobbyController* self) { getLogger().debug("MultiplayerLobbyController::ActivateMultiplayerLobby"); - _placeManager = Resources::FindObjectsOfTypeAll()[0]; - _menuEnvironmentManager = Resources::FindObjectsOfTypeAll()[0]; - _stageManager = Resources::FindObjectsOfTypeAll()[0]; - _lobbyStateDataModel = _placeManager->lobbyStateDataModel; + MultiplayerLobbyAvatarPlaceManager* _placeManager = self->multiplayerLobbyAvatarPlaceManager; + MenuEnvironmentManager* _menuEnvironmentManager = self->menuEnvironmentManager; + MultiplayerLobbyCenterStageManager* _stageManager = self->multiplayerLobbyCenterStageManager; + ILobbyStateDataModel* _lobbyStateDataModel = _placeManager->lobbyStateDataModel; MultiplayerLobbyController_ActivateMultiplayerLobby(self); - HandleLobbyEnvironmentLoaded(); + HandleLobbyEnvironmentLoaded(_lobbyStateDataModel, _menuEnvironmentManager, _placeManager, _stageManager); } MAKE_HOOK_MATCH(LightWithIdMonoBehaviour_RegisterLight, &LightWithIdMonoBehaviour::RegisterLight, void, LightWithIdMonoBehaviour* self) { diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 9ecfd64..2fd90b7 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -67,6 +67,8 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl std::string const& userId = player->get_userId(); if (_mpexPlayerData.contains(userId)) { getLogger().info("Received 'MpexPlayerData', player already exists"); + // Explicitly free previous MpexPlayerData + gc_free_specific( _mpexPlayerData[userId]); _mpexPlayerData[userId] = packet; } else { @@ -83,7 +85,9 @@ static void HandleMpexData(Players::MpexPlayerData* packet, IConnectedPlayer* pl } void HandleRegisterMpexPackets(MultiplayerCore::Networking::MpPacketSerializer* _mpPacketSerializer) { - _mpPacketSerializer->RegisterCallback(HandleMpexData); + // Explicitly allocate instance when packet is received, we will manually clear it + _mpPacketSerializer->RegisterCallback(HandleMpexData); + // _mpPacketSerializer->RegisterCallback(HandleMpexData); getLogger().debug("Callback HandleMpexData Registered"); } void HandleUnRegisterMpexPackets(MultiplayerCore::Networking::MpPacketSerializer* _mpPacketSerializer) { @@ -119,6 +123,8 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { if (_mpexPlayerData.contains(userId)) { getLogger().info("Reseting platform lights for Player '%s'", userId.c_str()); SetPlayerPlaceColor(player, UnityEngine::Color::get_black(), true); + // Explicitly free previous MpexPlayerData + gc_free_specific( _mpexPlayerData[userId]); _mpexPlayerData.erase(userId); } } @@ -132,6 +138,10 @@ void HandlePlayerDisconnected(IConnectedPlayer* player) { void HandleDisconnect(DisconnectedReason reason, GlobalNamespace::IConnectedPlayer* localPlayer) { getLogger().info("Disconnected from server reason: '%s'", MultiplayerCore::EnumUtils::GetEnumName(reason).c_str()); getLogger().info("Clearing MPEX player data"); + // TODO: Clear each instance manually + for (const auto & [ key, value ] : _mpexPlayerData) { + gc_free_specific(value); + } _mpexPlayerData.clear(); getLogger().info("MQE Removing connected/disconnected/disconnect events"); MultiplayerCore::Players::MpPlayerManager::playerConnectedEvent -= _PlayerConnectedHandler; From a2ae24ded2b092b486c283ff94b99fc949974430 Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 21 Mar 2023 22:35:41 +0100 Subject: [PATCH 55/56] Update MpCore includes --- .../include/Environments/MQEAvatarNameTag.hpp | 2 +- .../include/Environments/MQEAvatarPlaceLighting.hpp | 2 +- .../Hooks/SessionManagerAndExtendedPlayerHooks.hpp | 4 ++-- MultiQuestensions/shared/Players/MpexPlayerData.hpp | 2 +- .../shared/Players/MpexPlayerManager.hpp | 4 ++-- .../src/Environments/MQEAvaterNameTag.cpp | 6 +++--- .../src/Hooks/SessionManagerAndMpexPlayerHooks.cpp | 12 ++++++------ MultiQuestensions/src/UI/LobbySetupPanel.cpp | 2 +- MultiQuestensions/src/main.cpp | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp index 3d1f4be..85fbd34 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarNameTag.hpp @@ -1,7 +1,7 @@ #pragma once #include "custom-types/shared/macros.hpp" #include "Players/MpexPlayerData.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" +#include "multiplayer-core/shared/Players/MpPlayerData.hpp" #include "Players/MpexPlayerManager.hpp" #include "UnityEngine/MonoBehaviour.hpp" #include "HMUI/ImageView.hpp" diff --git a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp index 345ab2c..771ad02 100644 --- a/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp +++ b/MultiQuestensions/include/Environments/MQEAvatarPlaceLighting.hpp @@ -5,7 +5,7 @@ #include "UnityEngine/Color.hpp" #include "Players/MpexPlayerManager.hpp" -#include "MultiplayerCore/shared/Utils/event.hpp" +#include "multiplayer-core/shared/Utils/event.hpp" DECLARE_CLASS_CODEGEN(MultiQuestensions::Environments, MQEAvatarPlaceLighting, UnityEngine::MonoBehaviour, std::vector lights; diff --git a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp index 2588eae..128f43b 100644 --- a/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp +++ b/MultiQuestensions/include/Hooks/SessionManagerAndExtendedPlayerHooks.hpp @@ -2,8 +2,8 @@ #include "Players/MpexPlayerData.hpp" #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/DisconnectedReason.hpp" -#include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" -#include "MultiplayerCore/shared/Networking/MpNetworkingEvents.hpp" +#include "multiplayer-core/shared/Networking/MpPacketSerializer.hpp" +#include "multiplayer-core/shared/Networking/MpNetworkingEvents.hpp" extern MultiQuestensions::Players::MpexPlayerData* localMpexPlayerData; extern std::unordered_map _mpexPlayerData; diff --git a/MultiQuestensions/shared/Players/MpexPlayerData.hpp b/MultiQuestensions/shared/Players/MpexPlayerData.hpp index edec2d8..ffeb205 100644 --- a/MultiQuestensions/shared/Players/MpexPlayerData.hpp +++ b/MultiQuestensions/shared/Players/MpexPlayerData.hpp @@ -1,7 +1,7 @@ #pragma once #include "custom-types/shared/macros.hpp" #include "GlobalNamespace/IConnectedPlayer.hpp" -#include "MultiplayerCore/shared/Networking/Abstractions/MpPacket.hpp" +#include "multiplayer-core/shared/Networking/Abstractions/MpPacket.hpp" #include "UnityEngine/Color.hpp" DECLARE_CLASS_CUSTOM_DLL(MultiQuestensions::Players, MpexPlayerData, MultiplayerCore::Networking::Abstractions::MpPacket, "MultiplayerExtensions.Players", diff --git a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp index 558b33a..5f1287d 100644 --- a/MultiQuestensions/shared/Players/MpexPlayerManager.hpp +++ b/MultiQuestensions/shared/Players/MpexPlayerManager.hpp @@ -1,7 +1,7 @@ #pragma once #include "MpexPlayerData.hpp" -#include "MultiplayerCore/shared/Utils/event.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" +#include "multiplayer-core/shared/Utils/event.hpp" +#include "multiplayer-core/shared/Players/MpPlayerData.hpp" namespace MultiQuestensions::Players { diff --git a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp index 828bd30..dbba406 100644 --- a/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp +++ b/MultiQuestensions/src/Environments/MQEAvaterNameTag.cpp @@ -9,9 +9,9 @@ #include "GlobalNamespace/ConnectedPlayerName.hpp" #include "UnityEngine/Object.hpp" #include "Players/MpexPlayerManager.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" -#include "MultiplayerCore/shared/Utils/event.hpp" +#include "multiplayer-core/shared/Players/MpPlayerData.hpp" +#include "multiplayer-core/shared/Players/MpPlayerManager.hpp" +#include "multiplayer-core/shared/Utils/event.hpp" using namespace GlobalNamespace; using namespace UnityEngine::UI; diff --git a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp index 2fd90b7..bc8dd18 100644 --- a/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp +++ b/MultiQuestensions/src/Hooks/SessionManagerAndMpexPlayerHooks.cpp @@ -18,14 +18,14 @@ #include "questui/shared/BeatSaberUI.hpp" #include "questui/shared/CustomTypes/Components/MainThreadScheduler.hpp" -#include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" -#include "MultiplayerCore/shared/Networking/MpNetworkingEvents.hpp" +#include "multiplayer-core/shared/Networking/MpPacketSerializer.hpp" +#include "multiplayer-core/shared/Networking/MpNetworkingEvents.hpp" -#include "MultiplayerCore/shared/CodegenExtensions/EnumUtils.hpp" +#include "multiplayer-core/shared/Utils/EnumUtils.hpp" #include "Players/MpexPlayerManager.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerData.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" -#include "MultiplayerCore/shared/GlobalFields.hpp" +#include "multiplayer-core/shared/Players/MpPlayerData.hpp" +#include "multiplayer-core/shared/Players/MpPlayerManager.hpp" +#include "multiplayer-core/shared/GlobalFields.hpp" using namespace MultiQuestensions; using namespace MultiplayerCore::Networking; diff --git a/MultiQuestensions/src/UI/LobbySetupPanel.cpp b/MultiQuestensions/src/UI/LobbySetupPanel.cpp index 0962c87..67c71cb 100644 --- a/MultiQuestensions/src/UI/LobbySetupPanel.cpp +++ b/MultiQuestensions/src/UI/LobbySetupPanel.cpp @@ -11,7 +11,7 @@ #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" #include "Hooks/EnvironmentAndAvatarHooks.hpp" -#include "MultiplayerCore/shared/Networking/MpPacketSerializer.hpp" +#include "multiplayer-core/shared/Networking/MpPacketSerializer.hpp" using namespace UnityEngine::UI; using namespace MultiQuestensions; diff --git a/MultiQuestensions/src/main.cpp b/MultiQuestensions/src/main.cpp index 100707c..8541e9a 100644 --- a/MultiQuestensions/src/main.cpp +++ b/MultiQuestensions/src/main.cpp @@ -14,7 +14,7 @@ #include "custom-types/shared/register.hpp" #include "questui/shared/QuestUI.hpp" #include "questui/shared/BeatSaberUI.hpp" -#include "MultiplayerCore/shared/GlobalFields.hpp" +#include "multiplayer-core/shared/GlobalFields.hpp" //#include "GlobalNamespace/LobbySetupViewController.hpp" From 63e7a500b9a1688ce5989460ef75af13b6d6c37b Mon Sep 17 00:00:00 2001 From: EnderdracheLP Date: Tue, 21 Mar 2023 22:37:38 +0100 Subject: [PATCH 56/56] Experimental Multi Plattform Lights Custom Color --- .../src/Hooks/EnvironmentAndAvatarHooks.cpp | 92 ++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp index 66a2d2d..84e744e 100644 --- a/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp +++ b/MultiQuestensions/src/Hooks/EnvironmentAndAvatarHooks.cpp @@ -1,14 +1,15 @@ #include "main.hpp" #include "Hooks/Hooks.hpp" #include "GlobalFields.hpp" -#include "MultiplayerCore/shared/GlobalFields.hpp" +#include "multiplayer-core/shared/GlobalFields.hpp" #include "Hooks/EnvironmentAndAvatarHooks.hpp" #include "Hooks/SessionManagerAndExtendedPlayerHooks.hpp" #include "Environments/MQEAvatarPlaceLighting.hpp" #include "Environments/MQEAvatarNameTag.hpp" #include "Players/MpexPlayerManager.hpp" #include "Config.hpp" -#include "MultiplayerCore/shared/Players/MpPlayerManager.hpp" +#include "multiplayer-core/shared/Players/MpPlayerManager.hpp" +#include "multiplayer-core/shared/Utils/EnumUtils.hpp" #include "GlobalNamespace/MultiplayerLobbyController.hpp" #include "GlobalNamespace/LightWithIdMonoBehaviour.hpp" @@ -24,6 +25,15 @@ #include "GlobalNamespace/IConnectedPlayer.hpp" #include "GlobalNamespace/ConnectedPlayerManager_ConnectedPlayer.hpp" #include "GlobalNamespace/GameplayServerConfiguration.hpp" +#include "GlobalNamespace/MultiplayerGameplayAnimator.hpp" +#include "GlobalNamespace/MultiplayerController.hpp" +#include "GlobalNamespace/SimpleColorSO.hpp" +#include "GlobalNamespace/ConnectedPlayerHelpers.hpp" +#include "GlobalNamespace/LightsAnimator.hpp" +#include "GlobalNamespace/EaseType.hpp" + +#include "Tweening/Tween_1.hpp" +#include "Tweening/ColorTween.hpp" #include "System/Collections/Generic/List_1.hpp" @@ -257,11 +267,89 @@ namespace MultiQuestensions { HandleLobbyAvatarCreated(connectedPlayer); } +#pragma region Lighting hooks + + // Utilities for working with colors + ColorSO* getColorSO(UnityEngine::Color color) { + SimpleColorSO* colorSO = UnityEngine::ScriptableObject::CreateInstance(); + colorSO->SetColor(color); + return colorSO; + } + + MAKE_HOOK_MATCH(MultiplayerGameplayAnimator_HandleStateChanged, &MultiplayerGameplayAnimator::HandleStateChanged, void, MultiplayerGameplayAnimator* self, MultiplayerController::State state) { + getLogger().debug("MultiplayerGameplayAnimator::HandleStateChanged: Checking State %s", MultiplayerCore::EnumUtils::GetEnumName(state).c_str()); + getLogger().debug("MultiplayerGameplayAnimator::HandleStateChanged: Checking Player IsFailed %s", ConnectedPlayerHelpers::IsFailed(self->connectedPlayer) ? "true" : "false"); + + static bool skippedFirst = false; + + if (!ConnectedPlayerHelpers::IsFailed(self->connectedPlayer)) { + getLogger().debug("MultiplayerGameplayAnimator::HandleStateChanged: Player is not Failed"); + if (self && self->connectedPlayer && self->connectedPlayer->get_isMe()) { + if (state == MultiplayerController::State::Gameplay) + { + getLogger().debug("MultiplayerGameplayAnimator::HandleStateChanged: State is Gameplay and Player is not Failed (Me)"); + self->activeLightsColor = getColorSO(config.getPlayerColor()); + self->leadingLightsColor = getColorSO(config.getPlayerColor()); + // self->failedLightsColor = getColorSO(config.getPlayerColor()); + skippedFirst = false; + } + else if (state == MultiplayerController::State::Intro) + { + getLogger().debug("MultiplayerGameplayAnimator::HandleStateChanged: State is Intro and Player is not Failed (Me)"); + // if (skippedFirst) + // { + // TODO: Figure out how to animate the lights to the new color without the old value mixing itself in + for(LightsAnimator* lightsAnimator : self->allLightsAnimators) + { + // lightsAnimator->tween->set_delay(1.0f); + // lightsAnimator->tween->fromValue = {0, 0, 0, 0}; + // lightsAnimator->tween->toValue = config.getPlayerColor(); + lightsAnimator->AnimateToColor(config.getPlayerColor() * 1.1, 3, EaseType::Linear); + } + // } + // else skippedFirst = true; + + } + } + else if (self && self->connectedPlayer) { + StringW userId = self->connectedPlayer->get_userId(); + if (userId && _mpexPlayerData.contains(userId)) { + if (state == MultiplayerController::State::Gameplay) + { + getLogger().debug("MultiplayerGameplayAnimator::HandleStateChanged: State is Gameplay and Player is not Failed (Other Player)"); + self->activeLightsColor = getColorSO(_mpexPlayerData.at(userId)->Color); + self->leadingLightsColor = getColorSO(_mpexPlayerData.at(userId)->Color); + // self->failedLightsColor = getColorSO(_mpexPlayerData.at(userId)->Color); + skippedFirst = false; + } + else if (state == MultiplayerController::State::Intro) + { + getLogger().debug("MultiplayerGameplayAnimator::HandleStateChanged: State is Intro and Player is not Failed (Other Player)"); + // if (skippedFirst) + // { + // TODO: Figure out how to animate the lights to the new color without the old value mixing itself in + for(LightsAnimator* lightsAnimator : self->allLightsAnimators) + { + // lightsAnimator->tween->set_delay(1.0f); + // lightsAnimator->tween->fromValue = {0, 0, 0, 0}; + // lightsAnimator->tween->toValue = _mpexPlayerData.at(userId)->Color; + lightsAnimator->AnimateToColor(_mpexPlayerData.at(userId)->Color * 1.1, 3, EaseType::Linear); + } + // } + // else skippedFirst = true; + } + } + } + } + MultiplayerGameplayAnimator_HandleStateChanged(self, state); + } + #pragma endregion void Hooks::EnvironmentHooks() { INSTALL_HOOK(getLogger(), MultiplayerLobbyController_ActivateMultiplayerLobby); INSTALL_HOOK(getLogger(), LightWithIdMonoBehaviour_RegisterLight); INSTALL_HOOK(getLogger(), MultiplayerLobbyAvatarManager_AddPlayer); + INSTALL_HOOK(getLogger(), MultiplayerGameplayAnimator_HandleStateChanged); } } \ No newline at end of file