From dd23b91a113dfb1499d3c9cefb3238eb4c520583 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Thu, 3 Oct 2024 03:28:46 -0400 Subject: [PATCH 01/18] Clean up FindPlayerFromPlatformName --- AsaApi/Core/Public/Ark/ArkApiUtils.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index 6b6c150..d6c844e 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -157,21 +157,18 @@ namespace AsaApi */ FORCEINLINE AShooterPlayerController* FindPlayerFromPlatformName(const FString& steam_name) const { - AShooterPlayerController* result = nullptr; - const auto& player_controllers = GetWorld()->PlayerControllerListField(); - for (TWeakObjectPtr player_controller : player_controllers) + for (const auto& player_controllers = GetWorld()->PlayerControllerListField(); auto player_controller_weak : player_controllers) { - const FString current_name = player_controller->PlayerStateField()->PlayerNamePrivateField(); - if (current_name == steam_name) - { - auto* shooter_pc = static_cast(player_controller.Get()); + APlayerController* player_controller = player_controller_weak.Get(); - result = shooter_pc; - break; - } + if (!player_controller || !player_controller->PlayerStateField()) + continue; + + if (steam_name == player_controller->PlayerStateField()->PlayerNamePrivateField()) + return static_cast(player_controller); } - return result; + return nullptr; } /** From a0f035f74b275c4043dd24f53196fefee26cdf70 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Thu, 3 Oct 2024 03:30:51 -0400 Subject: [PATCH 02/18] Clean up FindControllerFromCharacter --- AsaApi/Core/Public/Ark/ArkApiUtils.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index d6c844e..b8ef35f 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -1,3 +1,4 @@ +// ReSharper disable CppClangTidyCppcoreguidelinesProTypeStaticCastDowncast #pragma once #include @@ -178,12 +179,10 @@ namespace AsaApi */ FORCEINLINE AShooterPlayerController* FindControllerFromCharacter(AShooterCharacter* character) const { - AShooterPlayerController* result = nullptr; + if (!character || character->IsDead()) + return nullptr; - if (character != nullptr && !character->IsDead()) - result = (AShooterPlayerController*)(character->GetOwnerController()); - - return result; + return static_cast(character->GetOwnerController()); } /** From 3665f09999a564fa93af750fa5e3de4a16be28e6 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Thu, 3 Oct 2024 04:11:37 -0400 Subject: [PATCH 03/18] Add FVector and FRotator literals --- AsaApi/Core/Private/UE/UE.cpp | 2 +- AsaApi/Core/Public/API/UE/Math/Rotator.h | 5 ++++ AsaApi/Core/Public/API/UE/Math/Vector.h | 36 +++++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/AsaApi/Core/Private/UE/UE.cpp b/AsaApi/Core/Private/UE/UE.cpp index d7b3e74..5f48fa6 100644 --- a/AsaApi/Core/Private/UE/UE.cpp +++ b/AsaApi/Core/Private/UE/UE.cpp @@ -9,4 +9,4 @@ ARK_API FProperty* UObject::FindProperty(FName name) return Property; } return nullptr; -} \ No newline at end of file +} diff --git a/AsaApi/Core/Public/API/UE/Math/Rotator.h b/AsaApi/Core/Public/API/UE/Math/Rotator.h index e663c28..1d7b79c 100644 --- a/AsaApi/Core/Public/API/UE/Math/Rotator.h +++ b/AsaApi/Core/Public/API/UE/Math/Rotator.h @@ -471,6 +471,11 @@ struct TRotator explicit TRotator(const TRotator& From) : TRotator((T)From.Pitch, (T)From.Yaw, (T)From.Roll) {} }; + +template +inline const TRotator TRotator::ZeroRotator = { 0,0,0 }; + + #if !defined(_MSC_VER) || defined(__clang__) // MSVC can't forward declare explicit specializations template<> const FRotator3f FRotator3f::ZeroRotator; template<> const FRotator3d FRotator3d::ZeroRotator; diff --git a/AsaApi/Core/Public/API/UE/Math/Vector.h b/AsaApi/Core/Public/API/UE/Math/Vector.h index 5fa5690..b182485 100644 --- a/AsaApi/Core/Public/API/UE/Math/Vector.h +++ b/AsaApi/Core/Public/API/UE/Math/Vector.h @@ -73,7 +73,7 @@ struct TVector }; /** A zero vector (0,0,0) */ - static const TVector ZeroVector; + static const TVector ZeroVector; /** One vector (1,1,1) */ static const TVector OneVector; @@ -1184,6 +1184,40 @@ struct TVector explicit TVector(const TVector& From) : TVector((T)From.X, (T)From.Y, (T)From.Z) {} }; + +template +inline const TVector TVector::ZeroVector = { 0,0,0 }; + +template +inline const TVector TVector::OneVector = { 1,1,1 }; + +template +inline const TVector TVector::UpVector = { 0,0,1 }; + +template +inline const TVector TVector::DownVector = { 0,0,-1 }; + +template +inline const TVector TVector::ForwardVector = { 1,0,0 }; + +template +inline const TVector TVector::BackwardVector = { -1,0,0 }; + +template +inline const TVector TVector::RightVector = { 0,1,0 }; + +template +inline const TVector TVector::LeftVector = { 0,-1,0 }; + +template +inline const TVector TVector::XAxisVector = { 1,0,0 }; + +template +inline const TVector TVector::YAxisVector = { 0,1,0 }; + +template +inline const TVector TVector::ZAxisVector = { 0,0,1 }; + /** * Structured archive slot serializer for FVector3f. * From 877a081efaeff967d0b7f5940692910a1211794d Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Thu, 3 Oct 2024 04:12:03 -0400 Subject: [PATCH 04/18] Clean Up SpawnDrop, Add Overload for FString --- AsaApi/Core/Public/Ark/ArkApiUtils.h | 62 ++++++++++++++++------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index b8ef35f..27499f0 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -219,14 +219,12 @@ namespace AsaApi */ static FORCEINLINE FString GetCharacterName(AShooterPlayerController* player_controller) { - if (player_controller != nullptr) - { - FString player_name(""); - player_controller->GetPlayerCharacterName(&player_name); - return player_name; - } + if (!player_controller) + return ""; - return FString(""); + FString player_name(""); + player_controller->GetPlayerCharacterName(&player_name); + return player_name; } /** @@ -235,7 +233,10 @@ namespace AsaApi */ static FORCEINLINE FString GetSteamName(AController* player_controller) { - return player_controller != nullptr ? player_controller->PlayerStateField()->PlayerNamePrivateField() : ""; + if (!player_controller || !player_controller->PlayerStateField()) + return ""; + + return player_controller->PlayerStateField()->PlayerNamePrivateField(); } /** @@ -259,38 +260,47 @@ namespace AsaApi * \param life_span Life span * \return Returns true if drop was spawned, false otherwise */ - FORCEINLINE bool SpawnDrop(const wchar_t* blueprint, FVector pos, int amount, float item_quality = 0.0f, - bool force_blueprint = false, float life_span = 0.0f) const + FORCEINLINE bool SpawnDrop(const FString& blueprint, const FVector& position, const int amount, const float item_quality = 0.0f, + const bool force_blueprint = false, const float life_span = 0.0f) const { - APlayerController* player = GetWorld()->GetFirstPlayerController(); + const auto player = GetWorld()->GetFirstPlayerController(); if (!player) return false; - FString bpFstr(blueprint); - - TSubclassOf archetype; - UVictoryCore::StringReferenceToClass(&archetype, &bpFstr); - - UPrimalItem* item = UPrimalItem::AddNewItem(archetype.uClass, nullptr, false, false, item_quality, false, amount, force_blueprint, 0, false, nullptr, 0, 0, 0, true); + TSubclassOf item_archetype; + // This is ugly, we should properly ensure that T is convertible to UObject + UVictoryCore::StringReferenceToClass(reinterpret_cast*>(&item_archetype), &blueprint); + UPrimalItem* item = UPrimalItem::AddNewItem(item_archetype.uClass, nullptr, false, false, item_quality, false, amount, force_blueprint, 0, false, nullptr, 0, false, false, true); if (!item) return false; FItemNetInfo* info = AllocateStruct(); - item->GetItemNetInfo(info, false); - TSubclassOf archetype_dropped; - archetype_dropped.uClass = archetype.uClass; + UPrimalInventoryComponent::StaticDropItem(player, info, item_archetype, &FRotator::ZeroRotator, true, &position, &FRotator::ZeroRotator, true, false, false, true, nullptr, &FVector::ZeroVector, nullptr, life_span); + FMemory::Free(info); + return true; + } - FVector zero_vector{ 0, 0, 0 }; - FRotator rot{ 0, 0, 0 }; + /** + * \brief Spawns an item drop + * \param blueprint Item simplified BP + * Example: '/Game/PrimalEarth/CoreBlueprints/Items/Armor/Riot/PrimalItemArmor_RiotPants.PrimalItemArmor_RiotPants_C' + * \param pos Spawn position + * \param amount Quantity + * \param item_quality Quality + * \param force_blueprint Is blueprint + * \param life_span Life span + * \return Returns true if drop was spawned, false otherwise + */ + FORCEINLINE bool SpawnDrop(const wchar_t* blueprint, FVector pos, int amount, float item_quality = 0.0f, + bool force_blueprint = false, float life_span = 0.0f) const + { + return SpawnDrop(FString(blueprint), pos, amount, item_quality, force_blueprint, life_span); + } - UPrimalInventoryComponent::StaticDropItem(player, info, archetype_dropped, &rot, true, &pos, &rot, true, false, false, true, nullptr, &zero_vector, nullptr, life_span); - FreeStruct(info); - return true; - } /** * \brief Spawns a dino near player or at specific coordinates From de79f2456e8c4f80a5401c90209cf45aa6f4897d Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Thu, 3 Oct 2024 17:17:58 -0400 Subject: [PATCH 05/18] Use alloca for FNetInfo to allocate stack space for it. --- AsaApi/Core/Public/API/ARK/Other.h | 3 +++ AsaApi/Core/Public/Ark/ArkApiUtils.h | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/Other.h b/AsaApi/Core/Public/API/ARK/Other.h index 5200f75..d3d1c31 100644 --- a/AsaApi/Core/Public/API/ARK/Other.h +++ b/AsaApi/Core/Public/API/ARK/Other.h @@ -1902,6 +1902,7 @@ struct FItemMultiplier struct FItemNetInfo { + void* data = alloca(GetStructSize()); // Fields TSubclassOf& ItemArchetypeField() { return *GetNativePointerField*>(this, "FItemNetInfo.ItemArchetype"); } @@ -1976,6 +1977,8 @@ struct FItemNetInfo bool NetSerialize(FArchive* Ar, UPackageMap* Map, bool* bOutSuccess) { return NativeCall(this, "FItemNetInfo.NetSerialize(FArchive&,UPackageMap*,bool&)", Ar, Map, bOutSuccess); } }; + + struct FItemSetup { // Fields diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index 27499f0..4ead1f4 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -275,11 +275,10 @@ namespace AsaApi if (!item) return false; - FItemNetInfo* info = AllocateStruct(); - item->GetItemNetInfo(info, false); + FItemNetInfo info{}; + item->GetItemNetInfo(&info, false); - UPrimalInventoryComponent::StaticDropItem(player, info, item_archetype, &FRotator::ZeroRotator, true, &position, &FRotator::ZeroRotator, true, false, false, true, nullptr, &FVector::ZeroVector, nullptr, life_span); - FMemory::Free(info); + UPrimalInventoryComponent::StaticDropItem(player, &info, item_archetype, &FRotator::ZeroRotator, true, &position, &FRotator::ZeroRotator, true, false, false, true, nullptr, &FVector::ZeroVector, nullptr, life_span); return true; } From 9c101b987a59813b6ea337ab1b961774b6e13a9f Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Fri, 11 Oct 2024 02:43:59 -0400 Subject: [PATCH 06/18] Further clean up ++ Introduce new method for padding structs (experimental) --- AsaApi/Core/Public/API/ARK/Other.h | 27 ++++- AsaApi/Core/Public/API/ARK/UE.h | 6 + AsaApi/Core/Public/Ark/ArkApiUtils.h | 161 +++++++++++++++++++-------- 3 files changed, 143 insertions(+), 51 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/Other.h b/AsaApi/Core/Public/API/ARK/Other.h index d3d1c31..61fe290 100644 --- a/AsaApi/Core/Public/API/ARK/Other.h +++ b/AsaApi/Core/Public/API/ARK/Other.h @@ -1900,11 +1900,34 @@ struct FItemMultiplier static UScriptStruct* StaticStruct() { return NativeCall(nullptr, "FItemMultiplier.StaticStruct()"); } }; +#define UE4_SizeOf(size) \ + constexpr static std::size_t size_of = size; \ + char storage[size_of] = { 0 }; + +#define UE4_CheckSize(Name) \ + { \ + const std::ptrdiff_t size_diff = size_of - GetStructSize(); \ + if(size_diff < 0) \ + { \ + Log::GetLog()->critical(#Name" will overrun ({} bytes smaller), please report this.", std::abs(size_diff)); \ + throw std::overflow_error(#Name" is not sufficiently sized."); \ + } \ + if (size_diff > 0) \ + { \ + Log::GetLog()->warn(#Name" exceeds real size ({} bytes larger), please report this.", std::abs(size_diff)); \ + } \ + } + + struct FItemNetInfo { - void* data = alloca(GetStructSize()); + UE4_SizeOf(528); + FItemNetInfo() + { + UE4_CheckSize(FItemNetInfo); + NativeCall(this, "FItemNetInfo.FItemNetInfo()"); + } // Fields - TSubclassOf& ItemArchetypeField() { return *GetNativePointerField*>(this, "FItemNetInfo.ItemArchetype"); } FItemNetID& ItemIDField() { return *GetNativePointerField(this, "FItemNetInfo.ItemID"); } unsigned int& ItemQuantityField() { return *GetNativePointerField(this, "FItemNetInfo.ItemQuantity"); } diff --git a/AsaApi/Core/Public/API/ARK/UE.h b/AsaApi/Core/Public/API/ARK/UE.h index d78d32e..270c999 100644 --- a/AsaApi/Core/Public/API/ARK/UE.h +++ b/AsaApi/Core/Public/API/ARK/UE.h @@ -1507,6 +1507,12 @@ int GetStructSize() // Credits to Substitute#0001 for the idea int size = 0; UScriptStruct* staticStruct = T::StaticStruct(); + + size = staticStruct ? staticStruct->PropertiesSizeField() : 0; + + printf("The size of this struct is %d bytes.", size); + return size; + if (staticStruct) { return staticStruct->PropertiesSizeField(); diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index 4ead1f4..d6cc952 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -249,11 +249,12 @@ namespace AsaApi return FindPlayerFromEOSID_Internal(eos_id); } + /** * \brief Spawns an item drop * \param blueprint Item simplified BP * Example: '/Game/PrimalEarth/CoreBlueprints/Items/Armor/Riot/PrimalItemArmor_RiotPants.PrimalItemArmor_RiotPants_C' - * \param pos Spawn position + * \param position Spawn position * \param amount Quantity * \param item_quality Quality * \param force_blueprint Is blueprint @@ -275,10 +276,12 @@ namespace AsaApi if (!item) return false; - FItemNetInfo info{}; + FItemNetInfo info; + item->GetItemNetInfo(&info, false); UPrimalInventoryComponent::StaticDropItem(player, &info, item_archetype, &FRotator::ZeroRotator, true, &position, &FRotator::ZeroRotator, true, false, false, true, nullptr, &FVector::ZeroVector, nullptr, life_span); + return true; } @@ -364,36 +367,92 @@ namespace AsaApi return nullptr; } + /** + * \brief Returns true if character is riding a dino, false otherwise + * \param player_controller Player + */ + static FORCEINLINE bool IsRidingDino(AShooterPlayerController& player_controller) + { + return !!GetRidingDino(player_controller); + } + /** * \brief Returns true if character is riding a dino, false otherwise * \param player_controller Player */ static FORCEINLINE bool IsRidingDino(AShooterPlayerController* player_controller) { - return player_controller != nullptr && player_controller->GetPlayerCharacter() != nullptr - && player_controller->GetPlayerCharacter()->GetRidingDino() != nullptr; + if (!player_controller) + return false; + return IsRidingDino(*player_controller); } /** * \brief Returns the dino the character is riding - * \param player_controller Player + * \param player_controller AShooterPlayerController& + * \return APrimalDinoCharacter* + */ + static FORCEINLINE APrimalDinoCharacter* GetRidingDino(AShooterPlayerController& player_controller) + { + const auto& player_character = player_controller.GetPlayerCharacter(); + return player_character ? player_character->GetRidingDino() : nullptr; + } + + /** + * \brief Returns the dino the character is riding + * \param player_controller AShooterPlayerController* * \return APrimalDinoCharacter* */ static FORCEINLINE APrimalDinoCharacter* GetRidingDino(AShooterPlayerController* player_controller) { - return player_controller != nullptr && player_controller->GetPlayerCharacter() != nullptr - ? player_controller->GetPlayerCharacter()->GetRidingDino() - : nullptr; + return player_controller ? GetRidingDino(*player_controller) : nullptr; } /** * \brief Returns the position of a player - * \param player_controller Player + * \param player_controller APlayerController& + * \return FVector + */ + static FORCEINLINE FVector GetPosition(APlayerController& player_controller) + { + const auto& player_pawn = player_controller.PawnField(); + if (!player_pawn) + return FVector::ZeroVector; + + return player_pawn->RootComponentField()->RelativeLocationField(); + } + + /** + * \brief Returns the position of a player + * \param player_controller APlayerController* * \return FVector */ static FORCEINLINE FVector GetPosition(APlayerController* player_controller) { - return player_controller != nullptr && player_controller->PawnField() != nullptr ? player_controller->PawnField()->RootComponentField()->RelativeLocationField() : FVector{0, 0, 0}; + if (!player_controller) + return FVector::ZeroVector; + return GetPosition(*player_controller); + } + + static FORCEINLINE bool TeleportToPos(AShooterPlayerController& player_controller, const FVector& position) + { + if (IsPlayerDead(player_controller)) + return false; + player_controller.SetPlayerPos(position.X, position.Y, position.Z); + return true; + } + + /** + * \brief Teleports player to the given position + * \param player_controller Player + * \param pos New position + */ + static FORCEINLINE bool TeleportToPos(AShooterPlayerController* player_controller, const FVector& pos) + { + if (!player_controller) + return false; + + return TeleportToPos(*player_controller, pos); } /** @@ -403,53 +462,49 @@ namespace AsaApi * \param check_for_dino If set true prevents players teleporting with dino's or teleporting to a player on a dino * \param max_dist Is the max distance the characters can be away from each other -1 is disabled */ - static FORCEINLINE std::optional TeleportToPlayer(AShooterPlayerController* me, AShooterPlayerController* him, - bool check_for_dino, float max_dist) + static FORCEINLINE std::optional TeleportToPlayer(AShooterPlayerController& source, AShooterPlayerController& destination, bool check_for_dino = false, float max_dist = -1) { - FVector him_position = GetPosition(him); - if (!(me != nullptr && him != nullptr && me->GetPlayerCharacter() != nullptr && him-> - GetPlayerCharacter() - != nullptr - && !me->GetPlayerCharacter()->IsDead() && !him->GetPlayerCharacter()->IsDead()) - ) - { - return "One of players is dead"; - } + if (IsPlayerDead(source)) + return "Source Player is dead."; - if (check_for_dino && (IsRidingDino(me) || IsRidingDino(him))) - { - return "One of players is riding a dino"; - } + if (IsPlayerDead(destination)) + return "Destination Player is dead."; - if (max_dist != -1 && FVector::Distance(GetPosition(me), him_position) > max_dist) - { - return "Person is too far away"; - } + if (check_for_dino && IsRidingDino(source)) + return "Source Player is riding a dino."; - if (him_position.IsNearlyZero()) - { - return "Player location is invalid"; - } + if (check_for_dino && IsRidingDino(destination)) + return "Destination Player is riding a dino."; - me->SetPlayerPos((float)him_position.X, (float)him_position.Y, (float)him_position.Z); + const FVector source_position = GetPosition(source); + const FVector destination_position = GetPosition(destination); + if (destination_position.IsNearlyZero()) + return "Destination Location is invalid."; + + if (max_dist != -1 && FVector::Distance(source_position, destination_position) > max_dist) + return "Distance between Players is too great."; + + TeleportToPos(source, destination_position); return {}; } /** - * \brief Teleports player to the given position - * \param player_controller Player - * \param pos New position + * \brief Teleport one player to another + * \param me Player + * \param him Other Player + * \param check_for_dino If set true prevents players teleporting with dino's or teleporting to a player on a dino + * \param max_dist Is the max distance the characters can be away from each other -1 is disabled */ - static FORCEINLINE bool TeleportToPos(AShooterPlayerController* player_controller, const FVector& pos) + static FORCEINLINE std::optional TeleportToPlayer(AShooterPlayerController* source, AShooterPlayerController* destination, bool check_for_dino, float max_dist) { - if (player_controller != nullptr && !IsPlayerDead(player_controller)) - { - player_controller->SetPlayerPos((float)pos.X, (float)pos.Y, (float)pos.Z); - return true; - } - return false; + if (!source) + return "Source Player Controller is null."; + + if (!destination) + return "Destination Player Controller is null."; + return TeleportToPlayer(*source, *destination, check_for_dino, max_dist); } /** @@ -510,14 +565,22 @@ namespace AsaApi /** * \brief Returns true if player is dead, false otherwise */ - static FORCEINLINE bool IsPlayerDead(AShooterPlayerController* player) + static FORCEINLINE bool IsPlayerDead(AShooterPlayerController& player) { - if (player == nullptr || player->GetPlayerCharacter() == nullptr) - { + const auto player_character = player.GetPlayerCharacter(); + if (!player_character) return true; - } + return player_character->IsDead(); + } - return player->GetPlayerCharacter()->IsDead(); + /** + * \brief Returns true if player is dead, false otherwise + */ + static FORCEINLINE bool IsPlayerDead(AShooterPlayerController* player) + { + if (!player) + return true; + return IsPlayerDead(*player); } static FORCEINLINE uint64 GetPlayerID(APrimalCharacter* character) From e29cf6db496a148fb73aee889639cff63e283db5 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Fri, 11 Oct 2024 04:17:09 -0400 Subject: [PATCH 07/18] Update GetMinimapData --- AsaApi/Core/Public/API/ARK/GameMode.h | 7 ++ AsaApi/Core/Public/Ark/ArkApiUtils.h | 95 ++++++++++++++++----------- 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/GameMode.h b/AsaApi/Core/Public/API/ARK/GameMode.h index 4eb9ca5..ad5366f 100644 --- a/AsaApi/Core/Public/API/ARK/GameMode.h +++ b/AsaApi/Core/Public/API/ARK/GameMode.h @@ -1225,6 +1225,13 @@ struct UPrimalGlobals : UObject struct FMapData { + UE4_SizeOf(128); + + FMapData() + { + UE4_CheckSize(FMapData); + NativeCall(this, "FMapData.FMapData()"); + } // Fields FString& MapNameField() { return *GetNativePointerField(this, "FMapData.MapName"); } diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index d6cc952..ef6f21c 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -543,15 +543,24 @@ namespace AsaApi return item_count; } + /** + * \brief Returns IP address of player + */ + static FORCEINLINE FString GetIPAddress(AShooterPlayerController& player) + { + FString address {}; + player.GetPlayerNetworkAddress(&address); + return address; + } + /** * \brief Returns IP address of player */ static FORCEINLINE FString GetIPAddress(AShooterPlayerController* player) { - FString addr; - if (player) - player->GetPlayerNetworkAddress(&addr); - return addr; + if (!player) + return ""; // Should we replace this with a sane legal value, such as 255.255.255.255? + return GetIPAddress(*player); } /** @@ -753,50 +762,56 @@ namespace AsaApi return out_actors; } + FORCEINLINE UMinimapData& GetMinimapData() const + { + constexpr auto default_path = "Blueprint'/Game/ASA/Minimap/Core/MinimapData_Base.MinimapData_Base'"; + APrimalWorldSettings& world_settings = *static_cast(GetWorld()->GetWorldSettings(false, true)); + + if(world_settings.CurrentMinimapDataField().uClass) + return *static_cast(world_settings.CurrentMinimapDataField().uClass->GetDefaultObject(true)); + + return *static_cast(UVictoryCore::BPLoadClass(default_path)->GetDefaultObject(true)); + } + + FORCEINLINE FMapData& GetMapDataFromMiniMap(UMinimapData& minimap_data, const FVector& reference_point = FVector::ZeroVector) const + { + if (minimap_data.MinimapDataField().Num() == 1) + return *minimap_data.MinimapDataField().GetData(); + + for (auto& data : minimap_data.MinimapDataField()) + { + if (PointIntersectsRectangle(reference_point, data.PlayableMinField(), data.PlayableMaxField())) + return data; + } + + throw std::invalid_argument("Unable To Find MapData."); + } + /** * \brief Converts FVector into coords that are displayed when you view the ingame map */ - FORCEINLINE MapCoords FVectorToCoords(FVector actor_position) + FORCEINLINE MapCoords FVectorToCoords(const FVector& position) const { - MapCoords coords; - AWorldSettings* world_settings = GetWorld()->GetWorldSettings(false, true); - APrimalWorldSettings* p_world_settings = static_cast(world_settings); + constexpr auto max = 100.f; + constexpr auto min = 0.f; - UMinimapData* minimap_data = nullptr; - if (p_world_settings->CurrentMinimapDataField().uClass) - minimap_data = static_cast(p_world_settings->CurrentMinimapDataField().uClass->GetDefaultObject(true)); - else - minimap_data = static_cast(UVictoryCore::BPLoadClass("Blueprint'/Game/ASA/Minimap/Core/MinimapData_Base.MinimapData_Base'")->GetDefaultObject(true)); + auto& minimap = GetMinimapData(); + auto& map_data = GetMapDataFromMiniMap(minimap, position); - FMapData* map_data = nullptr; - if (minimap_data->MinimapDataField().Num() == 1) - map_data = minimap_data->MinimapDataField().GetData(); - else - { - const int FMapDataSize = GetStructSize(); - for (int i = 0; i < minimap_data->MinimapDataField().Num(); i++) - { - FMapData* data = minimap_data->MinimapDataField().GetData() + (i * FMapDataSize); - - if (actor_position.X < data->PlayableMaxField().X - && actor_position.Y < data->PlayableMaxField().Y - && actor_position.X > data->PlayableMinField().X - && actor_position.Y > data->PlayableMinField().Y - && actor_position.Z < data->PlayableMaxField().Z - && actor_position.Z > data->PlayableMinField().Z) - { - map_data = data; - break; - } - } - } + const auto& map_min = map_data.OriginMinField(); + const auto& map_max = map_data.OriginMaxField(); + const auto& projected = (map_max - position) / (map_max - map_min); - double xAlpha = (actor_position.X - map_data->OriginMaxField().X) / (map_data->OriginMinField().X - map_data->OriginMaxField().X); - double yAlpha = (actor_position.Y - map_data->OriginMaxField().Y) / (map_data->OriginMinField().Y - map_data->OriginMaxField().Y); + return { FMath::Lerp(max, min, projected.X), FMath::Lerp(max, min, projected.Y) }; + + } - coords.x = (float)FMath::Lerp(100.0, 0.0, xAlpha); - coords.y = (float)FMath::Lerp(100.0, 0.0, yAlpha); - return coords; + // N.B., we should use dot projection here as not all rects are axis aligned. + FORCEINLINE bool PointIntersectsRectangle(const FVector& position, const FVector& start, const FVector& end) const + { + return + start.X < position.X && position.X < end.X && + start.Y < position.Y && position.Y < end.Y; } /** From efead9129404b34cbb4cb98bbe7cd80302c09e08 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Fri, 11 Oct 2024 04:58:30 -0400 Subject: [PATCH 08/18] More clean up --- AsaApi/Core/Public/API/ARK/Other.h | 1 + AsaApi/Core/Public/Ark/ArkApiUtils.h | 145 +++++++++++++++++++-------- 2 files changed, 103 insertions(+), 43 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/Other.h b/AsaApi/Core/Public/API/ARK/Other.h index 61fe290..6401fa7 100644 --- a/AsaApi/Core/Public/API/ARK/Other.h +++ b/AsaApi/Core/Public/API/ARK/Other.h @@ -1915,6 +1915,7 @@ struct FItemMultiplier if (size_diff > 0) \ { \ Log::GetLog()->warn(#Name" exceeds real size ({} bytes larger), please report this.", std::abs(size_diff)); \ + throw std::underflow_error(#Name" is not sufficiently sized."); \ } \ } diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index ef6f21c..4ded099 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -10,7 +10,7 @@ namespace AsaApi { - enum class ServerStatus { Loading, Ready }; + enum class ServerStatus { Loading = 0, Ready = 1 }; struct MapCoords { @@ -140,17 +140,23 @@ namespace AsaApi /** * \brief Returns EOS ID from player controller */ - static FORCEINLINE FString GetEOSIDFromController(AController* controller) + static FORCEINLINE FString GetEOSIDFromController(AController& controller) { FString eos_id = ""; - - AShooterPlayerController* playerController = static_cast(controller); - if (playerController != nullptr) - playerController->GetUniqueNetIdAsString(&eos_id); - + static_cast(controller).GetUniqueNetIdAsString(&eos_id); return eos_id; } + /** + * \brief Returns EOS ID from player controller + */ + static FORCEINLINE FString GetEOSIDFromController(AController* controller) + { + if (!controller) + return ""; + return GetEOSIDFromController(*controller); + } + /** * \brief Finds player from the given platform name (can be steam, Playstation, Xbox, etc...) * \param steam_name Platform name @@ -177,12 +183,24 @@ namespace AsaApi * \param character Player character * \return Pointer to AShooterPlayerController */ - FORCEINLINE AShooterPlayerController* FindControllerFromCharacter(AShooterCharacter* character) const + FORCEINLINE AShooterPlayerController* FindControllerFromCharacter(AShooterCharacter& character) const { - if (!character || character->IsDead()) + if (character.IsDead()) return nullptr; + return static_cast(character.GetOwnerController()); + + } - return static_cast(character->GetOwnerController()); + /** + * \brief Finds player controller from the given player character + * \param character Player character + * \return Pointer to AShooterPlayerController + */ + FORCEINLINE AShooterPlayerController* FindControllerFromCharacter(AShooterCharacter* character) const + { + if (!character) + return nullptr; + return FindControllerFromCharacter(*character); } /** @@ -213,6 +231,17 @@ namespace AsaApi return found_players; } + /** + * \brief Returns the character name of player + * \param player_controller Player + */ + static FORCEINLINE FString GetCharacterName(AShooterPlayerController& player_controller) + { + FString player_name(""); + player_controller.GetPlayerCharacterName(&player_name); + return player_name; + } + /** * \brief Returns the character name of player * \param player_controller Player @@ -221,10 +250,18 @@ namespace AsaApi { if (!player_controller) return ""; + return GetCharacterName(*player_controller); + } - FString player_name(""); - player_controller->GetPlayerCharacterName(&player_name); - return player_name; + /** + * \brief Returns the steam name of player + * \param player_controller Player + */ + static FORCEINLINE FString GetSteamName(AController& player_controller) + { + if (const auto& player_state = player_controller.PlayerStateField()) + return player_state->PlayerNamePrivateField(); + return ""; } /** @@ -233,10 +270,9 @@ namespace AsaApi */ static FORCEINLINE FString GetSteamName(AController* player_controller) { - if (!player_controller || !player_controller->PlayerStateField()) + if (!player_controller) return ""; - - return player_controller->PlayerStateField()->PlayerNamePrivateField(); + return GetSteamName(*player_controller); } /** @@ -261,8 +297,7 @@ namespace AsaApi * \param life_span Life span * \return Returns true if drop was spawned, false otherwise */ - FORCEINLINE bool SpawnDrop(const FString& blueprint, const FVector& position, const int amount, const float item_quality = 0.0f, - const bool force_blueprint = false, const float life_span = 0.0f) const + FORCEINLINE bool SpawnDrop(const FString& blueprint, const FVector& position, const int amount, const float item_quality = 0.0f, const bool force_blueprint = false, const float life_span = 0.0f) const { const auto player = GetWorld()->GetFirstPlayerController(); if (!player) @@ -270,7 +305,7 @@ namespace AsaApi TSubclassOf item_archetype; // This is ugly, we should properly ensure that T is convertible to UObject - UVictoryCore::StringReferenceToClass(reinterpret_cast*>(&item_archetype), &blueprint); + UVictoryCore::StringReferenceToClass(std::bit_cast*>(&item_archetype), &blueprint); UPrimalItem* item = UPrimalItem::AddNewItem(item_archetype.uClass, nullptr, false, false, item_quality, false, amount, force_blueprint, 0, false, nullptr, 0, false, false, true); if (!item) @@ -296,8 +331,7 @@ namespace AsaApi * \param life_span Life span * \return Returns true if drop was spawned, false otherwise */ - FORCEINLINE bool SpawnDrop(const wchar_t* blueprint, FVector pos, int amount, float item_quality = 0.0f, - bool force_blueprint = false, float life_span = 0.0f) const + FORCEINLINE bool SpawnDrop(const wchar_t* blueprint, FVector pos, int amount, float item_quality = 0.0f, bool force_blueprint = false, float life_span = 0.0f) const { return SpawnDrop(FString(blueprint), pos, amount, item_quality, force_blueprint, life_span); } @@ -600,10 +634,16 @@ namespace AsaApi : 0; } + static FORCEINLINE uint64 GetPlayerID(AController& controller) + { + return static_cast(controller).LinkedPlayerIDField(); + } + static FORCEINLINE uint64 GetPlayerID(AController* controller) { - auto* player = static_cast(controller); - return player != nullptr ? player->LinkedPlayerIDField() : 0; + if (!controller) + return 0; + return GetPlayerID(*controller); } FORCEINLINE const FString GetEOSIDForPlayerID(int player_id) @@ -638,37 +678,46 @@ namespace AsaApi return eos_id; } + static FORCEINLINE FString GetBlueprint(UObjectBase& object) + { + const auto class_field = object.ClassPrivateField(); + if (!class_field) + return ""; + return GetClassBlueprint(class_field).Replace(L"Default__", L"", ESearchCase::CaseSensitive); + } + /** * \brief Returns blueprint path from any UObject */ static FORCEINLINE FString GetBlueprint(UObjectBase* object) { - if (object != nullptr && object->ClassPrivateField() != nullptr) - { - FString path_name = GetClassBlueprint(object->ClassPrivateField()); - return path_name.Replace(L"Default__", L"", ESearchCase::CaseSensitive); - } - - return FString(""); + if (!object) + return ""; + return GetBlueprint(*object); } /** * \brief Returns blueprint path from any UClass */ - static FORCEINLINE FString GetClassBlueprint(UClass* the_class) + static FORCEINLINE FString GetClassBlueprint(UClass& the_class) { - if (the_class != nullptr) - { - FString path; - auto the_object = UVictoryCore::GetClassDefaultObject(the_class); - the_object->GetPathName(nullptr, &path); - if (path.EndsWith("_C")) - return "Blueprint'" + path.LeftChop(2) + "'"; - else - return "Blueprint'" + path + "'"; - } + FString path; + UVictoryCore::GetClassDefaultObject(&the_class)->GetPathName(nullptr, &path); - return FString(""); + if (path.EndsWith("_C")) + path = path.LeftChop(2); + + return "Blueprint'" + path + "'"; + } + + /** + * \brief Returns blueprint path from any UClass + */ + static FORCEINLINE FString GetClassBlueprint(UClass* the_class) + { + if (!the_class) + return ""; + return GetClassBlueprint(*the_class); } /** @@ -866,7 +915,7 @@ namespace AsaApi * \param _this Player controller * \param Command Command to run */ - void RunHiddenCommand(AShooterPlayerController* _this, FString* Command) + void RunHiddenCommand(AShooterPlayerController* _this, const FString* Command) const { FString result; HideCommand = true; @@ -874,6 +923,16 @@ namespace AsaApi HideCommand = false; } + /** + * \brief Runs a command that is not logged anywhere + * \param _this Player controller + * \param Command Command to run + */ + void RunHiddenCommand(AShooterPlayerController* _this, const FString& Command) const + { + RunHiddenCommand(_this, &Command); + } + /** * \brief Gets the current messaging manager for the plugin, without casting * \return MessagingManager From b6675d2c44c1aeb4cc64d34cb443c4e1710d166a Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Fri, 11 Oct 2024 21:52:55 -0400 Subject: [PATCH 09/18] Clean up Extensions Definitions --- .../Public/API/ARK/ExtensionsDefinition.h | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h b/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h index 3068c68..4fdf2df 100644 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h +++ b/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h @@ -1,45 +1,41 @@ +// ReSharper disable CppInconsistentNaming #pragma once -#include "../../IApiUtils.h" +#define STRINGIFY(a) #a +#define Name_Persist(name) _Pragma( STRINGIFY( comment(linker, "/Export:AsaApi_" ## name ## "=" __FUNCDNAME__) )) -// Actor extensions +DLLEXPORT FORCEINLINE FString GetSteamName(AController& player_controller) +{ + Name_Persist("IApiUtils_GetSteamName_0"); + if (const auto& player_state = player_controller.PlayerStateField()) + return player_state->PlayerNamePrivateField(); + return ""; +} +// Actor extensions FORCEINLINE FVector ActorExtensions::GetActorForwardVector() { - AActor* _this = static_cast(this); - USceneComponent* RootComponent = _this->RootComponentField().Get(); - if (RootComponent) - { - return RootComponent->ComponentToWorldField().GetUnitAxis(EAxis::X); - } - - //return FVector::ZeroVector; - return FVector(0, 0, 0); + if (USceneComponent* root_component = std::bit_cast(this)->RootComponentField().Get()) + return root_component->ComponentToWorldField().GetUnitAxis(EAxis::X); + return FVector::ZeroVector; } -FORCEINLINE bool ActorExtensions::IsA(UClass* SomeBase) +FORCEINLINE bool ActorExtensions::IsA(const UClass* some_base) { - return static_cast(this)->ClassPrivateField()->IsChildOf(SomeBase); + return std::bit_cast(this)->ClassPrivateField()->IsChildOf(some_base); } FORCEINLINE FVector ActorExtensions::GetLocation() { - AActor* _this = static_cast(this); - auto* root = _this->RootComponentField().Get(); - if (root) - { - UE::Math::TTransform transform = root->ComponentToWorldField(); - return transform.GetLocation(); - } - return FVector(); + if (const auto& root = std::bit_cast(this)->RootComponentField()) + return root->ComponentToWorldField().GetLocation(); + return FVector::ZeroVector; } // Player Controller Extensions FORCEINLINE FString PlayerControllerExtensions::GetEOSId() { - AShooterPlayerController* _this = static_cast(this); - FString eos_id = ""; - _this->GetUniqueNetIdAsString(&eos_id); + FString eos_id = *std::bit_cast(this)->GetUniqueNetIdAsString(&eos_id); return eos_id; } \ No newline at end of file From 7f68f8f3da79e5664f296f71153288d6bde71af6 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Fri, 11 Oct 2024 21:53:35 -0400 Subject: [PATCH 10/18] Clean up Extensions Definitions --- AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h b/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h index 4fdf2df..b058397 100644 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h +++ b/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h @@ -1,17 +1,6 @@ // ReSharper disable CppInconsistentNaming #pragma once -#define STRINGIFY(a) #a -#define Name_Persist(name) _Pragma( STRINGIFY( comment(linker, "/Export:AsaApi_" ## name ## "=" __FUNCDNAME__) )) - -DLLEXPORT FORCEINLINE FString GetSteamName(AController& player_controller) -{ - Name_Persist("IApiUtils_GetSteamName_0"); - if (const auto& player_state = player_controller.PlayerStateField()) - return player_state->PlayerNamePrivateField(); - return ""; -} - // Actor extensions FORCEINLINE FVector ActorExtensions::GetActorForwardVector() { From 319a9edd8632b230b86440d1736dd856181473b7 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Fri, 11 Oct 2024 22:00:00 -0400 Subject: [PATCH 11/18] Clean up Extensions Definitions --- AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h b/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h index 236ef5b..7c3a22d 100644 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h +++ b/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h @@ -14,10 +14,10 @@ struct ActorExtensions /** * \brief Returns if the actor is from SomeBase or a subclass of SomeBase. - * \param SomeBase The base class to check against. + * \param some_base The base class to check against. * \return true if the actor is from SomeBase or a subclass of SomeBase. */ - bool IsA(UClass* SomeBase); + bool IsA(const UClass* some_base); /** * \brief Returns the actor's location in world space. From c5132ca543f38d73077b809e505f8e7cef60affd Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Fri, 11 Oct 2024 22:00:35 -0400 Subject: [PATCH 12/18] Clean up Extensions Definitions --- AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h b/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h index 7c3a22d..59bdf70 100644 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h +++ b/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h @@ -1,6 +1,5 @@ +// ReSharper disable CppInconsistentNaming #pragma once - -#include "UE.h" #include #include From 8a440269c6f7e63ce5ed3154e056e9d2e5bc8394 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Sat, 12 Oct 2024 16:17:32 -0400 Subject: [PATCH 13/18] More changes / clean up --- AsaApi/Core/Public/API/ARK/Actor.h | 29 +++++++++++++++++-- .../Public/API/ARK/ExtensionsDeclaration.h | 9 ------ .../Public/API/ARK/ExtensionsDefinition.h | 10 +------ AsaApi/Core/Public/Ark/ArkApiUtils.h | 23 +++++++++++++-- .../Public/Ark/AsaApiUtilsMessagingManager.h | 20 +++++++++---- AsaApi/Core/Public/Ark/MessagingManager.h | 16 +++++----- 6 files changed, 70 insertions(+), 37 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/Actor.h b/AsaApi/Core/Public/API/ARK/Actor.h index ed23460..66487d3 100644 --- a/AsaApi/Core/Public/API/ARK/Actor.h +++ b/AsaApi/Core/Public/API/ARK/Actor.h @@ -2584,7 +2584,7 @@ struct APrimalController : AController }; -struct APlayerController : APrimalController, PlayerControllerExtensions +struct APlayerController : APrimalController { // Fields @@ -3056,8 +3056,33 @@ struct ABasePlayerController : APrimalPlayerController struct AShooterPlayerController : ABasePlayerController { - // Fields +public: + // Start AsaApi Extensions + FString GetPlayerCharacterName() + { + FString player_name = *GetPlayerCharacterName(&player_name); + return player_name; + } + + FString GetUniqueNetIdAsString() + { + FString unique_id = *GetUniqueNetIdAsString(&unique_id); + return unique_id; + } + + void ClientServerChatDirectMessage(const FString& MessageText, FLinearColor MessageColor, bool bIsBold, const FString& SenderId) + { + ClientServerChatDirectMessage(&MessageText, MessageColor, bIsBold, &SenderId); + } + void ClientServerNotification(const FString& MessageText, FLinearColor MessageColor, float DisplayScale, float DisplayTime, UTexture2D* MessageIcon, USoundBase* SoundToPlay, int Priority) + { + ClientServerNotification(&MessageText, MessageColor, DisplayScale, DisplayTime, MessageIcon, SoundToPlay, Priority); + } + + // End AsaApi Extensions + + // Fields UPaintingStreamingComponent*& PaintingStreamingComponentField() { return *GetNativePointerField(this, "AShooterPlayerController.PaintingStreamingComponent"); } FieldArray HeldItemSlotField() { return { this, "AShooterPlayerController.HeldItemSlot" }; } FieldArray UsedItemSlotField() { return { this, "AShooterPlayerController.UsedItemSlot" }; } diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h b/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h index 59bdf70..4b0734c 100644 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h +++ b/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h @@ -23,13 +23,4 @@ struct ActorExtensions * \return The actor's location in world space. */ FVector GetLocation(); -}; - -struct PlayerControllerExtensions -{ - /** - * \brief Returns the player's EOS id (platform unique identifier) - * \return The player's EOS id (platform unique identifier) - */ - FString GetEOSId(); }; \ No newline at end of file diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h b/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h index b058397..77713a8 100644 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h +++ b/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h @@ -4,7 +4,7 @@ // Actor extensions FORCEINLINE FVector ActorExtensions::GetActorForwardVector() { - if (USceneComponent* root_component = std::bit_cast(this)->RootComponentField().Get()) + if (USceneComponent* root_component = std::bit_cast(this)->RootComponentField()) return root_component->ComponentToWorldField().GetUnitAxis(EAxis::X); return FVector::ZeroVector; } @@ -19,12 +19,4 @@ FORCEINLINE FVector ActorExtensions::GetLocation() if (const auto& root = std::bit_cast(this)->RootComponentField()) return root->ComponentToWorldField().GetLocation(); return FVector::ZeroVector; -} - -// Player Controller Extensions - -FORCEINLINE FString PlayerControllerExtensions::GetEOSId() -{ - FString eos_id = *std::bit_cast(this)->GetUniqueNetIdAsString(&eos_id); - return eos_id; } \ No newline at end of file diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index 4ded099..58460ba 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -6,8 +6,26 @@ #include #include <../Private/Ark/Globals.h> #include "MessagingManager.h" +#include "API/ARK/ExtensionsDefinition.h" #include "API/Helpers/Helpers.h" +namespace AsaApi::IApiUtils_Next +{ + FORCEINLINE FString GetSteamName(AController& player_controller) + { + if (const auto& player_state = player_controller.PlayerStateField()) + return player_state->PlayerNamePrivateField(); + return ""; + } + + FORCEINLINE FString GetSteamName(AController* player_controller) + { + if (!player_controller) + return ""; + return GetSteamName(*player_controller); + } +} + namespace AsaApi { enum class ServerStatus { Loading = 0, Ready = 1 }; @@ -231,15 +249,14 @@ namespace AsaApi return found_players; } + /** * \brief Returns the character name of player * \param player_controller Player */ static FORCEINLINE FString GetCharacterName(AShooterPlayerController& player_controller) { - FString player_name(""); - player_controller.GetPlayerCharacterName(&player_name); - return player_name; + return player_controller.GetPlayerCharacterName(); } /** diff --git a/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h b/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h index 3d731ba..5bc9f1b 100644 --- a/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h +++ b/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h @@ -18,7 +18,9 @@ class AsaApiUtilsMessagingManager : public MessagingManager FORCEINLINE FString SendNotificationPrettyToPlayer(APlayerController* PC, const FString& Text, const FLinearColor& BackgroundColor, const FLinearColor& TextColor, const double TextScale, const double Duration, const Position TextJustification, const Position ScreenPosition, const bool bAddToChat) { - return SendNotificationPrettyToPlayer(PC->GetEOSId(), Text, BackgroundColor, TextColor, TextScale, Duration, TextJustification, ScreenPosition, bAddToChat); + if (!PC->IsA(AShooterPlayerController::StaticClass())) + return ""; + return SendNotificationPrettyToPlayer(std::bit_cast(PC)->GetUniqueNetIdAsString(), Text, BackgroundColor, TextColor, TextScale, Duration, TextJustification, ScreenPosition, bAddToChat); } // this function lets you send a notification to a player using the pretty widgets from the api utils mod, will all the possible params, to specific player @@ -31,12 +33,18 @@ class AsaApiUtilsMessagingManager : public MessagingManager } // this function lets you send a notification to a player using the pretty widgets from the api utils mod, will all the possible params, to all players - FORCEINLINE FString SendNotificationPrettyToPlayers(TArray PCs, const FString& Text, const FLinearColor& BackgroundColor, const FLinearColor& TextColor, + FORCEINLINE FString SendNotificationPrettyToPlayers(TArray player_controllers, const FString& Text, const FLinearColor& BackgroundColor, const FLinearColor& TextColor, const double TextScale, const double Duration, const Position TextJustification, const Position ScreenPosition, const bool bAddToChat) { TArray ids; - for (APlayerController* PC : PCs) - ids.Add(PC->GetEOSId()); + + for (APlayerController* player_controller : player_controllers) + { + if (!player_controller->IsA(AShooterPlayerController::StaticClass())) + continue;; + ids.Add(std::bit_cast(player_controller)->GetUniqueNetIdAsString()); + } + return SendNotificationPrettyToPlayers(ids, Text, BackgroundColor, TextColor, TextScale, Duration, TextJustification, ScreenPosition, bAddToChat); } @@ -51,7 +59,7 @@ class AsaApiUtilsMessagingManager : public MessagingManager void SendServerMessage_Impl(AShooterPlayerController* player_controller, FLinearColor msg_color, const FString& msg) override { TArray ids; - ids.Add(player_controller->GetEOSId()); + ids.Add(player_controller->GetUniqueNetIdAsString()); SendNotificationPrettyToPlayers(ids, msg, FLinearColor(0, 0, 0, 0), msg_color, 1.0, 0.0, Position::Center, Position::Center, true); } @@ -60,7 +68,7 @@ class AsaApiUtilsMessagingManager : public MessagingManager float display_time, UTexture2D* icon, const FString& msg) override { TArray ids; - ids.Add(player_controller->GetEOSId()); + ids.Add(player_controller->GetUniqueNetIdAsString()); SendNotificationPrettyToPlayers(ids, msg, FLinearColor(0, 0, 0, 0), color, display_scale, display_time, Position::Center, Position::Center, false); } }; diff --git a/AsaApi/Core/Public/Ark/MessagingManager.h b/AsaApi/Core/Public/Ark/MessagingManager.h index 3602e4f..0572450 100644 --- a/AsaApi/Core/Public/Ark/MessagingManager.h +++ b/AsaApi/Core/Public/Ark/MessagingManager.h @@ -12,6 +12,7 @@ class ARK_API MessagingManager { public: + virtual ~MessagingManager() = default; /** * \brief Sends server message to the specific player. Using fmt::format. * \tparam T Either a a char or wchar_t @@ -147,8 +148,8 @@ class ARK_API MessagingManager } /** - * \brief Returns wether this messaging manager is able to work in the current session. - * \brief The default one does not depend in any mod or external service so it always returns true. + * \brief Returns weather this messaging manager is able to work in the current session. + * \brief The default one does not depend on any mod or external service, so it always returns true. * \brief Subclasses should redefine this function if they depend on any external service. * \brief If it returns an error, it will be removed and the plugin will fall back to the default API messaging manager. * \return Empty optional if no error, or optional filled with error string. @@ -172,10 +173,9 @@ class ARK_API MessagingManager protected /*overridable functions*/: // these are to be redefined by the child classes // default implementations - virtual void SendServerMessage_Impl(AShooterPlayerController* player_controller, FLinearColor msg_color, const FString& msg) + virtual void SendServerMessage_Impl(AShooterPlayerController* player_controller, FLinearColor color, const FString& message) { - static const FString senderid = "Server"; - player_controller->ClientServerChatDirectMessage(&msg, msg_color, false, &senderid); + player_controller->ClientServerChatDirectMessage(message, color, false, "Server"); } virtual void SendChatMessage_Impl(AShooterPlayerController* player_controller, const FString& sender_name, const FString& msg) @@ -183,14 +183,14 @@ protected /*overridable functions*/: // these are to be redefined by the child c FPrimalChatMessage chat_message; chat_message.SenderName = sender_name; chat_message.Message = msg; - chat_message.UserId = player_controller->GetEOSId(); + chat_message.UserId = player_controller->GetUniqueNetIdAsString(); player_controller->ClientChatMessage(chat_message); } virtual void SendNotification_Impl(AShooterPlayerController* player_controller, FLinearColor color, float display_scale, - float display_time, UTexture2D* icon, const FString& msg) + float display_time, UTexture2D* icon, const FString& message) { - player_controller->ClientServerNotification(&msg, color, display_scale, display_time, icon, nullptr, 1); + player_controller->ClientServerNotification(message, color, display_scale, display_time, icon, nullptr, 1); } protected /*variables*/: From 03f009b819daf83fe1ba8a29b810423ca49a44f8 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Sat, 12 Oct 2024 16:30:09 -0400 Subject: [PATCH 14/18] Remove extension classes, annotate AsaApi additions in classes --- AsaApi/AsaApi.vcxproj | 2 -- AsaApi/Core/Private/UE/UE.cpp | 6 +++++ AsaApi/Core/Public/API/ARK/Actor.h | 18 ++++++++++++- .../Public/API/ARK/ExtensionsDeclaration.h | 26 ------------------- .../Public/API/ARK/ExtensionsDefinition.h | 22 ---------------- AsaApi/Core/Public/API/ARK/UE.h | 5 +++- 6 files changed, 27 insertions(+), 52 deletions(-) delete mode 100644 AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h delete mode 100644 AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h diff --git a/AsaApi/AsaApi.vcxproj b/AsaApi/AsaApi.vcxproj index 9d3ff60..6ddd901 100644 --- a/AsaApi/AsaApi.vcxproj +++ b/AsaApi/AsaApi.vcxproj @@ -396,8 +396,6 @@ copy "$(SolutionDir)$(PlatformName)\$(ConfigurationName)\$(ProjectName).pdb" "F: - - diff --git a/AsaApi/Core/Private/UE/UE.cpp b/AsaApi/Core/Private/UE/UE.cpp index 5f48fa6..bc19797 100644 --- a/AsaApi/Core/Private/UE/UE.cpp +++ b/AsaApi/Core/Private/UE/UE.cpp @@ -1,3 +1,4 @@ +// ReSharper disable CppInconsistentNaming #include "API/ARK/Ark.h" #include "API/ARK/UE.h" @@ -10,3 +11,8 @@ ARK_API FProperty* UObject::FindProperty(FName name) } return nullptr; } + +bool UObjectBaseUtility::IsA(const UClass* base) +{ + return this->ClassPrivateField()->IsChildOf(base); +} diff --git a/AsaApi/Core/Public/API/ARK/Actor.h b/AsaApi/Core/Public/API/ARK/Actor.h index 66487d3..ed528e0 100644 --- a/AsaApi/Core/Public/API/ARK/Actor.h +++ b/AsaApi/Core/Public/API/ARK/Actor.h @@ -1377,8 +1377,24 @@ struct UInstancedStaticMeshComponent : UStaticMeshComponent void ReceiveComponentDamage(float DamageAmount, const FDamageEvent* DamageEvent, AController* EventInstigator, AActor* DamageCauser) { NativeCall(this, "UInstancedStaticMeshComponent.ReceiveComponentDamage(float,FDamageEvent&,AController*,AActor*)", DamageAmount, DamageEvent, EventInstigator, DamageCauser); } }; -struct AActor : UPrimalActor, ActorExtensions +struct AActor : UPrimalActor { + // Start AsaApi Extensions + FORCEINLINE FVector GetActorForwardVector() + { + if (USceneComponent* root_component = RootComponentField()) + return root_component->ComponentToWorldField().GetUnitAxis(EAxis::X); + return FVector::ZeroVector; + } + + FORCEINLINE FVector GetLocation() + { + if (const auto& root = RootComponentField()) + return root->ComponentToWorldField().GetLocation(); + return FVector::ZeroVector; + } + // End AsaApi Extensions + // Fields FActorTickFunction& PrimaryActorTickField() { return *GetNativePointerField(this, "AActor.PrimaryActorTick"); } diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h b/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h deleted file mode 100644 index 4b0734c..0000000 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDeclaration.h +++ /dev/null @@ -1,26 +0,0 @@ -// ReSharper disable CppInconsistentNaming -#pragma once -#include -#include - -struct ActorExtensions -{ - /** - * \brief Returns the forward direction vector (length 1.0) from the actor's point of view. - * \return The forward direction vector (length 1.0) from the actor's point of view. - */ - FVector GetActorForwardVector(); - - /** - * \brief Returns if the actor is from SomeBase or a subclass of SomeBase. - * \param some_base The base class to check against. - * \return true if the actor is from SomeBase or a subclass of SomeBase. - */ - bool IsA(const UClass* some_base); - - /** - * \brief Returns the actor's location in world space. - * \return The actor's location in world space. - */ - FVector GetLocation(); -}; \ No newline at end of file diff --git a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h b/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h deleted file mode 100644 index 77713a8..0000000 --- a/AsaApi/Core/Public/API/ARK/ExtensionsDefinition.h +++ /dev/null @@ -1,22 +0,0 @@ -// ReSharper disable CppInconsistentNaming -#pragma once - -// Actor extensions -FORCEINLINE FVector ActorExtensions::GetActorForwardVector() -{ - if (USceneComponent* root_component = std::bit_cast(this)->RootComponentField()) - return root_component->ComponentToWorldField().GetUnitAxis(EAxis::X); - return FVector::ZeroVector; -} - -FORCEINLINE bool ActorExtensions::IsA(const UClass* some_base) -{ - return std::bit_cast(this)->ClassPrivateField()->IsChildOf(some_base); -} - -FORCEINLINE FVector ActorExtensions::GetLocation() -{ - if (const auto& root = std::bit_cast(this)->RootComponentField()) - return root->ComponentToWorldField().GetLocation(); - return FVector::ZeroVector; -} \ No newline at end of file diff --git a/AsaApi/Core/Public/API/ARK/UE.h b/AsaApi/Core/Public/API/ARK/UE.h index 270c999..80711e2 100644 --- a/AsaApi/Core/Public/API/ARK/UE.h +++ b/AsaApi/Core/Public/API/ARK/UE.h @@ -1,5 +1,5 @@ #pragma once - +// ReSharper disable CppInconsistentNaming #ifdef ARK_EXPORTS #define ARK_API __declspec(dllexport) #else @@ -251,6 +251,9 @@ struct UObjectBase struct UObjectBaseUtility : UObjectBase { + // Start AsaApi Extensions + bool IsA(const UClass* base); + // End AsaApi Extensions // Fields From 06a66a24ba7587465d9c706dc3bbe5e4333c9785 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Sat, 12 Oct 2024 16:32:20 -0400 Subject: [PATCH 15/18] Clean up includes for removed extensions --- AsaApi/Core/Public/API/ARK/Ark.h | 2 -- AsaApi/Core/Public/Ark/ArkApiUtils.h | 1 - 2 files changed, 3 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/Ark.h b/AsaApi/Core/Public/API/ARK/Ark.h index 4cb84c4..0508753 100644 --- a/AsaApi/Core/Public/API/ARK/Ark.h +++ b/AsaApi/Core/Public/API/ARK/Ark.h @@ -25,7 +25,6 @@ #include "../UE/Math/ColorList.h" #include "UE.h" -#include "ExtensionsDeclaration.h" //#include "Tribe.h" #include "Actor.h" #include "Other.h" @@ -40,4 +39,3 @@ #include "../../ICommands.h" #include "IHooks.h" #include "Tools.h" -#include "ExtensionsDefinition.h" diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index 58460ba..97c395e 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -6,7 +6,6 @@ #include #include <../Private/Ark/Globals.h> #include "MessagingManager.h" -#include "API/ARK/ExtensionsDefinition.h" #include "API/Helpers/Helpers.h" namespace AsaApi::IApiUtils_Next From 76f51b8e86d1f08d0835021c44b2e0a6f2de2b85 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Sat, 12 Oct 2024 16:48:35 -0400 Subject: [PATCH 16/18] Add template version of IsA --- AsaApi/Core/Public/API/ARK/UE.h | 5 +++++ AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/UE.h b/AsaApi/Core/Public/API/ARK/UE.h index 80711e2..7f4e4a7 100644 --- a/AsaApi/Core/Public/API/ARK/UE.h +++ b/AsaApi/Core/Public/API/ARK/UE.h @@ -253,6 +253,11 @@ struct UObjectBaseUtility : UObjectBase { // Start AsaApi Extensions bool IsA(const UClass* base); + template + bool IsA() + { + return IsA(T::StaticClass()); + } // End AsaApi Extensions // Fields diff --git a/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h b/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h index 5bc9f1b..83ff719 100644 --- a/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h +++ b/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h @@ -18,7 +18,7 @@ class AsaApiUtilsMessagingManager : public MessagingManager FORCEINLINE FString SendNotificationPrettyToPlayer(APlayerController* PC, const FString& Text, const FLinearColor& BackgroundColor, const FLinearColor& TextColor, const double TextScale, const double Duration, const Position TextJustification, const Position ScreenPosition, const bool bAddToChat) { - if (!PC->IsA(AShooterPlayerController::StaticClass())) + if (!PC->IsA()) return ""; return SendNotificationPrettyToPlayer(std::bit_cast(PC)->GetUniqueNetIdAsString(), Text, BackgroundColor, TextColor, TextScale, Duration, TextJustification, ScreenPosition, bAddToChat); } @@ -40,8 +40,8 @@ class AsaApiUtilsMessagingManager : public MessagingManager for (APlayerController* player_controller : player_controllers) { - if (!player_controller->IsA(AShooterPlayerController::StaticClass())) - continue;; + if (!player_controller->IsA()) + continue; ids.Add(std::bit_cast(player_controller)->GetUniqueNetIdAsString()); } From d159127f2d4d27510c52420a92ccdfa85b75f237 Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Sat, 19 Oct 2024 22:51:31 -0400 Subject: [PATCH 17/18] Further clean up --- .../Public/Ark/AsaApiUtilsMessagingManager.h | 17 +++----- AsaApi/Core/Public/Ark/MessagingManager.h | 42 ++++++++++++------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h b/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h index 83ff719..870e02d 100644 --- a/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h +++ b/AsaApi/Core/Public/Ark/AsaApiUtilsMessagingManager.h @@ -27,9 +27,7 @@ class AsaApiUtilsMessagingManager : public MessagingManager FORCEINLINE FString SendNotificationPrettyToPlayer(const FString& EOSid, const FString& Text, const FLinearColor& BackgroundColor, const FLinearColor& TextColor, const double TextScale, const double Duration, const Position TextJustification, const Position ScreenPosition, const bool bAddToChat) { - TArray ids; - ids.Add(EOSid); - return SendNotificationPrettyToPlayers(ids, Text, BackgroundColor, TextColor, TextScale, Duration, TextJustification, ScreenPosition, bAddToChat); + return SendNotificationPrettyToPlayers({ EOSid }, Text, BackgroundColor, TextColor, TextScale, Duration, TextJustification, ScreenPosition, bAddToChat); } // this function lets you send a notification to a player using the pretty widgets from the api utils mod, will all the possible params, to all players @@ -56,20 +54,15 @@ class AsaApiUtilsMessagingManager : public MessagingManager } protected: // changes the server messages to use pretty widgets from the api utils mod - void SendServerMessage_Impl(AShooterPlayerController* player_controller, FLinearColor msg_color, const FString& msg) override + void SendServerMessage_Impl(AShooterPlayerController* player_controller, const FLinearColor message, const FString& msg) override { - TArray ids; - ids.Add(player_controller->GetUniqueNetIdAsString()); - SendNotificationPrettyToPlayers(ids, msg, FLinearColor(0, 0, 0, 0), msg_color, 1.0, 0.0, Position::Center, Position::Center, true); + SendNotificationPrettyToPlayers({ player_controller->GetUniqueNetIdAsString() }, msg, FLinearColor(0, 0, 0, 0), message, 1.0, 0.0, Position::Center, Position::Center, true); } // changes notifications to use pretty widgets from the api utils mod, this version mostly mimics old ASE notifications - void SendNotification_Impl(AShooterPlayerController* player_controller, FLinearColor color, float display_scale, - float display_time, UTexture2D* icon, const FString& msg) override + void SendNotification_Impl(AShooterPlayerController* player_controller, const FLinearColor color, const float display_scale, const float display_time, UTexture2D* icon, const FString& msg) override { - TArray ids; - ids.Add(player_controller->GetUniqueNetIdAsString()); - SendNotificationPrettyToPlayers(ids, msg, FLinearColor(0, 0, 0, 0), color, display_scale, display_time, Position::Center, Position::Center, false); + SendNotificationPrettyToPlayers({ player_controller->GetUniqueNetIdAsString() }, msg, FLinearColor(0, 0, 0, 0), color, display_scale, display_time, Position::Center, Position::Center, false); } }; diff --git a/AsaApi/Core/Public/Ark/MessagingManager.h b/AsaApi/Core/Public/Ark/MessagingManager.h index 0572450..18945dc 100644 --- a/AsaApi/Core/Public/Ark/MessagingManager.h +++ b/AsaApi/Core/Public/Ark/MessagingManager.h @@ -2,6 +2,8 @@ #include "API/ARK/Ark.h" + + /** * \brief Messaging manager. Allows to send server messages, notifications and chat messages. * \brief Usage: @@ -13,23 +15,36 @@ class ARK_API MessagingManager { public: virtual ~MessagingManager() = default; + /** * \brief Sends server message to the specific player. Using fmt::format. * \tparam T Either a a char or wchar_t * \tparam Args Optional arguments types * \param player_controller Player - * \param msg_color Message color - * \param msg Message + * \param color Message color + * \param message Message * \param args Optional arguments */ template - FORCEINLINE void SendServerMessage(AShooterPlayerController* player_controller, FLinearColor msg_color, const T* msg, Args&&... args) + FORCEINLINE void SendServerMessage(AShooterPlayerController& player_controller, FLinearColor color, const T* message, Args&&... args) + { + SendServerMessage_Impl(&player_controller, color, FString::Format(message, std::forward(args)...)); + } + /** + * \brief Sends server message to the specific player. Using fmt::format. + * \tparam T Either a a char or wchar_t + * \tparam Args Optional arguments types + * \param player_controller Player + * \param color Message color + * \param message Message + * \param args Optional arguments + */ + template + FORCEINLINE void SendServerMessage(AShooterPlayerController* player_controller, FLinearColor color, const T* message, Args&&... args) { if (!player_controller) return; - - FString message = FString::Format(msg, std::forward(args)...); - SendServerMessage_Impl(player_controller, msg_color, message); + SendServerMessage_Impl(player_controller, color, FString::Format(message, std::forward(args)...)); } /** @@ -105,18 +120,13 @@ class ARK_API MessagingManager * \param args Optional arguments */ template - FORCEINLINE void SendNotificationToAll(FLinearColor color, float display_scale, - float display_time, UTexture2D* icon, const T* msg, Args&&... args) + FORCEINLINE void SendNotificationToAll(const FLinearColor color, const float display_scale, const float display_time, UTexture2D* icon, const T* msg, Args&&... args) { - FString text(FString::Format(msg, std::forward(args)...)); + const FString text(FString::Format(msg, std::forward(args)...)); - const auto& player_controllers = WorldContext->PlayerControllerListField(); - for (TWeakObjectPtr player_controller : player_controllers) - { - AShooterPlayerController* shooter_pc = static_cast(player_controller.Get()); - if (shooter_pc) - SendNotification_Impl(shooter_pc, color, display_scale, display_time, icon, text); - } + for (const auto& controllers = WorldContext->PlayerControllerListField(); auto player_controller : controllers) + if (const auto shooter_controller = static_cast(player_controller.Get())) + SendNotification_Impl(shooter_controller, color, display_scale, display_time, icon, text); } /** From 6ad54b5e9f13c3c410b78f89f675b9a44dc573dd Mon Sep 17 00:00:00 2001 From: "Riley S." Date: Sat, 19 Oct 2024 23:08:54 -0400 Subject: [PATCH 18/18] Console Command Cleanup --- AsaApi/Core/Public/API/ARK/Actor.h | 22 +++++++++++++++++++++- AsaApi/Core/Public/Ark/ArkApiUtils.h | 5 +---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/AsaApi/Core/Public/API/ARK/Actor.h b/AsaApi/Core/Public/API/ARK/Actor.h index ed528e0..0b86834 100644 --- a/AsaApi/Core/Public/API/ARK/Actor.h +++ b/AsaApi/Core/Public/API/ARK/Actor.h @@ -1973,7 +1973,15 @@ struct AInfo : AActor }; struct UPlayer : UObject { - TObjectPtr& PlayerControllerField() { return *GetNativePointerField*>(this, "UPlayer.PlayerController"); } + // Start AsaApi Extensions + FString ConsoleCommand(const FString& Command, bool bWriteToLog) + { + FString result = *ConsoleCommand(&result, &Command, bWriteToLog); + return result; + } + // End AsaApi Extensions + + TObjectPtr& PlayerControllerField() { return *GetNativePointerField*>(this, "UPlayer.PlayerController"); } // int CurrentNetSpeed; // int ConfiguredInternetSpeed; // int ConfiguredLanSpeed; @@ -3096,6 +3104,18 @@ struct AShooterPlayerController : ABasePlayerController ClientServerNotification(&MessageText, MessageColor, DisplayScale, DisplayTime, MessageIcon, SoundToPlay, Priority); } + FString ConsoleCommand(const FString& Command, bool bWriteToLog) + { + FString result = *ConsoleCommand(&result, &Command, bWriteToLog); + return result; + } + + void RunHiddenCommand(const FString& Command) + { + this->PlayerField().Get()->ConsoleCommand(Command, false); + } + + // End AsaApi Extensions // Fields diff --git a/AsaApi/Core/Public/Ark/ArkApiUtils.h b/AsaApi/Core/Public/Ark/ArkApiUtils.h index 97c395e..85fd277 100644 --- a/AsaApi/Core/Public/Ark/ArkApiUtils.h +++ b/AsaApi/Core/Public/Ark/ArkApiUtils.h @@ -933,10 +933,7 @@ namespace AsaApi */ void RunHiddenCommand(AShooterPlayerController* _this, const FString* Command) const { - FString result; - HideCommand = true; - _this->ConsoleCommand(&result, Command, false); - HideCommand = false; + _this->RunHiddenCommand(*Command); } /**