From 070fed3b7073047b8615c7a07137043c72219b6b Mon Sep 17 00:00:00 2001 From: Russ Treadwell Date: Mon, 14 Dec 2020 13:54:35 -0500 Subject: [PATCH] Add skipped methods from previous commits --- README.md | 8 +-- .../SteamBridge/Private/Core/SteamFriends.cpp | 39 ++++++++++++++- .../Private/Core/SteamGameServer.cpp | 12 ++++- .../Private/Core/SteamInventory.cpp | 50 +++++++++++++++++++ .../Private/Core/SteamUserStats.cpp | 25 ++++++++++ .../SteamBridge/Private/Core/SteamUtils.cpp | 28 +++++++++++ .../SteamBridge/Private/SteamBridgeUtils.cpp | 2 +- Source/SteamBridge/Public/Core/SteamFriends.h | 6 ++- .../SteamBridge/Public/Core/SteamGameServer.h | 18 +++++-- .../SteamBridge/Public/Core/SteamInventory.h | 43 ++++++++++++++-- .../SteamBridge/Public/Core/SteamUserStats.h | 49 ++++++++++++++++-- Source/SteamBridge/Public/Core/SteamUtils.h | 28 +++++++++-- Source/SteamBridge/Public/SteamBridgeUtils.h | 4 +- Source/SteamBridge/Public/SteamStructs.h | 18 +++++++ 14 files changed, 302 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 0c1f220..b69dc36 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ Interface | Completed | Notes | ISteamApps | :heavy_check_mark: | ISteamFriends | :heavy_check_mark: | [1] (1) | ISteamGameServer | :heavy_check_mark: | [1] (4) | -ISteamGameServerStats | :heavy_check_mark: | [1] (1) | +ISteamGameServerStats | :heavy_check_mark: | [1] (2) | ISteamHTMLSurface | :heavy_check_mark: | ISteamHTTP | :heavy_check_mark: | ISteamInput | :heavy_check_mark: | -ISteamInventory | :heavy_check_mark: | [1] (5) +ISteamInventory | :heavy_check_mark: | [1] (2) ISteamMatchmaking | :heavy_check_mark: | ISteamMatchmakingServers | :heavy_check_mark: | [1] (10) ISteamMusic | :heavy_check_mark: | @@ -27,8 +27,8 @@ ISteamRemoteStorage | :heavy_check_mark: | [1] (5) ISteamScreenshots | :heavy_check_mark: | ISteamUGC | :heavy_check_mark: | [1][3] (3/3) ISteamUser | :heavy_check_mark: | -ISteamUserStats | :heavy_check_mark: | [1] (4) -ISteamUtils | :heavy_check_mark: | [1] (5) +ISteamUserStats | :heavy_check_mark: | [1] (1) +ISteamUtils | :heavy_check_mark: | [1] (3) ISteamVideo | :heavy_check_mark: | SteamWeb | :x: | [2] | diff --git a/Source/SteamBridge/Private/Core/SteamFriends.cpp b/Source/SteamBridge/Private/Core/SteamFriends.cpp index 8861628..1edc2ca 100644 --- a/Source/SteamBridge/Private/Core/SteamFriends.cpp +++ b/Source/SteamBridge/Private/Core/SteamFriends.cpp @@ -74,6 +74,42 @@ FSteamAPICall USteamFriends::DownloadClanActivityCounts(TArray& SteamC return res; } +// #NOTE: This should work, but the reason of failure is k_ESteamAPICallFailureSteamGone so I'm assuming it's where this method isn't async +//TArray USteamFriends::EnumerateFollowingList() const +//{ +// int32 ResultCount = 0; +// FriendsEnumerateFollowingList_t Result; +// TArray SteamIDs; +// +// do +// { +// if (SteamAPICall_t ResultHandle = SteamFriends()->EnumerateFollowingList(ResultCount)) +// { +// if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, "LOL"); +// bool bTmpResult; +// if (SteamUtils()->GetAPICallResult(ResultHandle, &Result, sizeof(Result), Result.k_iCallback, &bTmpResult)) +// { +// if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, "LOL2"); +// ResultCount += Result.m_nResultsReturned; +// for (const auto& id : Result.m_rgSteamID) +// { +// if (id.IsValid()) +// { +// SteamIDs.Add(id.ConvertToUint64()); +// } +// } +// } +// +// ESteamAPICallFailure_ reason = (ESteamAPICallFailure_)((uint8)SteamUtils()->GetAPICallFailureReason(ResultHandle) - 1); +// +// if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, USteamBridgeUtils::GetEnumValueAsString("ESteamAPICallFailure_", reason)); +// +// } +// } while (ResultCount < Result.m_nTotalResultCount); +// +// return SteamIDs; +//} + int32 USteamFriends::GetClanChatMessage(FSteamID SteamIDClanChat, int32 MessageID, FString& Message, ESteamChatEntryType& ChatEntryType, FSteamID& SteamIDChatter) { EChatEntryType TmpEntryType; @@ -167,7 +203,7 @@ void USteamFriends::GetFriendsGroupMembersList(FSteamFriendsGroupID FriendsGroup } } -UTexture2D* USteamFriends::GetFriendAvatar(FSteamID SteamIDFriend, ESteamAvatarSize AvatarSize) const +UTexture2D* USteamFriends::GetFriendAvatar(FSteamID SteamIDFriend, ESteamAvatarSize AvatarSize, int32& ImageHandle) const { int32 Avatar = 0; switch (AvatarSize) @@ -183,6 +219,7 @@ UTexture2D* USteamFriends::GetFriendAvatar(FSteamID SteamIDFriend, ESteamAvatarS break; } + ImageHandle = Avatar; uint32 Width = 0, Height = 0; SteamUtils()->GetImageSize(Avatar, &Width, &Height); if (Width > 0 && Height > 0) diff --git a/Source/SteamBridge/Private/Core/SteamGameServer.cpp b/Source/SteamBridge/Private/Core/SteamGameServer.cpp index d129791..7482a36 100644 --- a/Source/SteamBridge/Private/Core/SteamGameServer.cpp +++ b/Source/SteamBridge/Private/Core/SteamGameServer.cpp @@ -28,13 +28,13 @@ USteamGameServer::~USteamGameServer() OnGSPolicyResponseCallback.Unregister(); } -ESteamBeginAuthSessionResult USteamGameServer::BeginAuthSession(TArray AuthTicket, FSteamID SteamID) +ESteamBeginAuthSessionResult USteamGameServer::BeginAuthSession(TArray AuthTicket, FSteamID SteamID) const { AuthTicket.SetNum(8192); return (ESteamBeginAuthSessionResult)SteamGameServer()->BeginAuthSession(AuthTicket.GetData(), 8192, SteamID); } -FHAuthTicket USteamGameServer::GetAuthSessionTicket(TArray &AuthTicket) +FHAuthTicket USteamGameServer::GetAuthSessionTicket(TArray &AuthTicket) const { uint32 length = 0; AuthTicket.SetNum(8192); @@ -43,6 +43,14 @@ FHAuthTicket USteamGameServer::GetAuthSessionTicket(TArray &AuthTicket) return result; } +FString USteamGameServer::GetPublicIP() const +{ + FString TmpIP; + USteamBridgeUtils::ConvertIPToString(SteamGameServer()->GetPublicIP().m_unIPv4); + + return TmpIP; +} + void USteamGameServer::OnAssociateWithClanResult(AssociateWithClanResult_t *pParam) { m_OnAssociateWithClanResult.Broadcast((ESteamResult)pParam->m_eResult); diff --git a/Source/SteamBridge/Private/Core/SteamInventory.cpp b/Source/SteamBridge/Private/Core/SteamInventory.cpp index a115835..d104ba1 100644 --- a/Source/SteamBridge/Private/Core/SteamInventory.cpp +++ b/Source/SteamBridge/Private/Core/SteamInventory.cpp @@ -112,6 +112,56 @@ bool USteamInventory::GetItemDefinitionIDs(TArray& Items) const return false; } +bool USteamInventory::GetItemDefinitionProperty(FSteamItemDef Definition, const FString& PropertyName, FString& Value) const +{ + uint32 Size = 0; + if (SteamInventory()->GetItemDefinitionProperty(Definition, TCHAR_TO_UTF8(*PropertyName), nullptr, &Size)) + { + TArray TmpStr; + TmpStr.SetNum(Size); + bool bResult = SteamInventory()->GetItemDefinitionProperty(Definition, TCHAR_TO_UTF8(*PropertyName), TmpStr.GetData(), &Size); + Value = UTF8_TO_TCHAR(TmpStr.GetData()); + return bResult; + } + return false; +} + +bool USteamInventory::GetItemsByID(FSteamInventoryResult& ResultHandle, const TArray& InstanceIDs) const +{ + const int32 Size = InstanceIDs.Num(); + TArray TmpIDs; + TmpIDs.SetNum(Size); + + for (int32 i = 0; i < Size; i++) + { + TmpIDs.Add(InstanceIDs[i]); + } + + return SteamInventory()->GetItemsByID((SteamInventoryResult_t*)&ResultHandle, TmpIDs.GetData(), Size); +} + +bool USteamInventory::GetItemsWithPrices(TArray& ItemData) const +{ + const int32 Size = SteamInventory()->GetNumItemsWithPrices(); + + TArray TmpItems; + TArray TmpCurrentPrices; + TArray TmpBasePrices; + TmpItems.SetNum(Size); + TmpCurrentPrices.SetNum(Size); + TmpBasePrices.SetNum(Size); + + if (bool bResult = SteamInventory()->GetItemsWithPrices(TmpItems.GetData(), TmpCurrentPrices.GetData(), TmpBasePrices.GetData(), Size)) + { + for (int32 i = 0; i < Size; i++) + { + ItemData.Add({TmpItems[i], (int64)TmpCurrentPrices[i], (int64)TmpBasePrices[i] }); + } + return bResult; + } + return false; +} + bool USteamInventory::GetResultItemProperty(FSteamInventoryResult ResultHandle, int32 ItemIndex, const FString& PropertyName, FString& Value) const { TArray TmpStr; diff --git a/Source/SteamBridge/Private/Core/SteamUserStats.cpp b/Source/SteamBridge/Private/Core/SteamUserStats.cpp index 3c54c53..9d84d7d 100644 --- a/Source/SteamBridge/Private/Core/SteamUserStats.cpp +++ b/Source/SteamBridge/Private/Core/SteamUserStats.cpp @@ -46,6 +46,15 @@ FSteamAPICall USteamUserStats::FindOrCreateLeaderboard(const FString& Leaderboar return SteamUserStats()->FindOrCreateLeaderboard(TCHAR_TO_UTF8(*LeaderboardName), (ELeaderboardSortMethod)LeaderboardSortMethod, (ELeaderboardDisplayType)LeaderboardDisplayType); } +bool USteamUserStats::GetDownloadedLeaderboardEntry(FSteamLeaderboardEntries SteamLeaderboardEntries, int32 index, FSteamLeaderboardEntry& LeaderboardEntry, TArray& Details, int32 DetailsMax) const +{ + Details.SetNum(DetailsMax); + LeaderboardEntry_t TmpEntry; + bool bResult = SteamUserStats()->GetDownloadedLeaderboardEntry(SteamLeaderboardEntries, index, &TmpEntry, Details.GetData(), DetailsMax); + LeaderboardEntry = TmpEntry; + return bResult; +} + int32 USteamUserStats::GetGlobalStatHistoryFloat(const FString& StatName, TArray& Data, int32 Size) const { TArray TmpData; @@ -57,6 +66,22 @@ int32 USteamUserStats::GetGlobalStatHistoryFloat(const FString& StatName, TArray return result; } +int32 USteamUserStats::GetMostAchievedAchievementInfo(FString& Name, float& Percent, bool& bAchieved) const +{ + TArray TmpName; + int32 result = SteamUserStats()->GetMostAchievedAchievementInfo(TmpName.GetData(), 1024, &Percent, &bAchieved); + Name = UTF8_TO_TCHAR(TmpName.GetData()); + return result; +} + +int32 USteamUserStats::GetNextMostAchievedAchievementInfo(int32 IteratorPrevious, FString& Name, float& Percent, bool& bAchieved) const +{ + TArray TmpName; + int32 result = SteamUserStats()->GetNextMostAchievedAchievementInfo(IteratorPrevious, TmpName.GetData(), 1024, &Percent, &bAchieved); + Name = UTF8_TO_TCHAR(TmpName.GetData()); + return result; +} + FSteamAPICall USteamUserStats::UploadLeaderboardScore(FSteamLeaderboard SteamLeaderboard, ESteamLeaderboardUploadScoreMethod LeaderboardUploadScoreMethod, int32 Score, const TArray& ScoreDetails) const { return SteamUserStats()->UploadLeaderboardScore(SteamLeaderboard, (ELeaderboardUploadScoreMethod)LeaderboardUploadScoreMethod, Score, ScoreDetails.GetData(), ScoreDetails.Num()); diff --git a/Source/SteamBridge/Private/Core/SteamUtils.cpp b/Source/SteamBridge/Private/Core/SteamUtils.cpp index b498f0c..afd0ab6 100644 --- a/Source/SteamBridge/Private/Core/SteamUtils.cpp +++ b/Source/SteamBridge/Private/Core/SteamUtils.cpp @@ -40,6 +40,34 @@ bool USteamUtils::GetEnteredGamepadTextInput(FString& Text) const return bResult; } +bool USteamUtils::GetImageRGBA(int32 Image, TArray& Buffer) const +{ + uint32 Width, Height; + if (SteamUtils()->GetImageSize(Image, &Width, &Height)) + { + const int32 ImageSize = Width * Height * 4; + TArray TmpBuffer; + TmpBuffer.SetNum(ImageSize); + bool bResult = SteamUtils()->GetImageRGBA(Image, TmpBuffer.GetData(), ImageSize); + + for (int32 i = 0; i < ImageSize; i++) + { + Buffer.Add(TmpBuffer[i]); + } + + return bResult; + } + return false; +} + +bool USteamUtils::GetImageSize(int32 Image, FIntPoint& Size) const +{ + uint32 Width, Height; + bool bResult = SteamUtils()->GetImageSize(Image, &Width, &Height); + Size = { (int32)Width, (int32)Height }; + return bResult; +} + bool USteamUtils::ShowGamepadTextInput(ESteamGamepadTextInputMode InputMode, ESteamGamepadTextInputLineMode LineInputMode, const FString& Description, const FString& ExistingText, int32 CharMax) const { return SteamUtils()->ShowGamepadTextInput((EGamepadTextInputMode)InputMode, (EGamepadTextInputLineMode)LineInputMode, TCHAR_TO_UTF8(*Description), CharMax, TCHAR_TO_UTF8(*ExistingText)); diff --git a/Source/SteamBridge/Private/SteamBridgeUtils.cpp b/Source/SteamBridge/Private/SteamBridgeUtils.cpp index 3a51c0a..7d031e2 100644 --- a/Source/SteamBridge/Private/SteamBridgeUtils.cpp +++ b/Source/SteamBridge/Private/SteamBridgeUtils.cpp @@ -19,7 +19,7 @@ FString USteamBridgeUtils::ConvertIPToString(uint32 IP) return FString::FromInt(IP >> 24) + "." + FString::FromInt((IP >> 16) % 256) + "." + FString::FromInt((IP >> 8) % 256) + "." + FString::FromInt(IP % 256); } -FString USteamBridgeUtils::GetSteamIDAsString(const FSteamID& SteamID) const +FString USteamBridgeUtils::GetSteamIDAsString(const FSteamID& SteamID) { return FString::Printf(TEXT("%llu"), SteamID.Value); } diff --git a/Source/SteamBridge/Public/Core/SteamFriends.h b/Source/SteamBridge/Public/Core/SteamFriends.h index 1bcc62a..e07198b 100644 --- a/Source/SteamBridge/Public/Core/SteamFriends.h +++ b/Source/SteamBridge/Public/Core/SteamFriends.h @@ -125,7 +125,8 @@ class STEAMBRIDGE_API USteamFriends final : public UObject UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|Friends") FSteamAPICall DownloadClanActivityCounts(TArray& SteamClanIDs, int32 ClansToRequest = 1) const; - // #TODO EnumerateFollowingList + /*UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "SteamBridgeCore|Friends") + TArray EnumerateFollowingList() const;*/ /** * Gets the Steam ID at the given index in a Steam group chat. @@ -509,10 +510,11 @@ class STEAMBRIDGE_API USteamFriends final : public UObject * * @param FSteamID SteamIDFriend * @param ESteamAvatarSize AvatarSize + * @param int32& ImageHandle * @return UTexture2D* */ UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|Friends") - UTexture2D* GetFriendAvatar(FSteamID SteamIDFriend, ESteamAvatarSize AvatarSize) const; + UTexture2D* GetFriendAvatar(FSteamID SteamIDFriend, ESteamAvatarSize AvatarSize, int32& ImageHandle) const; /** * Gets the current users persona (display) name. diff --git a/Source/SteamBridge/Public/Core/SteamGameServer.h b/Source/SteamBridge/Public/Core/SteamGameServer.h index bb58f87..9d55efd 100644 --- a/Source/SteamBridge/Public/Core/SteamGameServer.h +++ b/Source/SteamBridge/Public/Core/SteamGameServer.h @@ -55,7 +55,7 @@ class STEAMBRIDGE_API USteamGameServer final : public UObject * @return ESteamBeginAuthSessionResult */ UFUNCTION(BlueprintCallable, Category = "SteamBridgeCore|GameServer") - ESteamBeginAuthSessionResult BeginAuthSession(TArray AuthTicket, FSteamID SteamID); + ESteamBeginAuthSessionResult BeginAuthSession(TArray AuthTicket, FSteamID SteamID) const; /** * Checks if the game server is logged on. @@ -132,10 +132,20 @@ class STEAMBRIDGE_API USteamGameServer final : public UObject * @return FHAuthTicket - A handle to the auth ticket. When you're done interacting with the entity you must call CancelAuthTicket on the handle. */ UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|GameServer") - FHAuthTicket GetAuthSessionTicket(TArray& AuthTicket); + FHAuthTicket GetAuthSessionTicket(TArray& AuthTicket) const; // #TODO GetNextOutgoingPacket - // #TODO GetPublicIP + + + // #NOTE This method only returns IPv4 for now, will eventually return a struct of the IPs (to support IPv6) + /** + * Gets the public IP of the server according to Steam. + * This is useful when the server is behind NAT and you want to advertise its IP in a lobby for other clients to directly connect to. + * + * @return FString - Returns the IP address (IPv4) as an FString + */ + UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|GameServer") + FString GetPublicIP() const; /** * Gets the Steam ID of the game server. @@ -359,7 +369,7 @@ class STEAMBRIDGE_API USteamGameServer final : public UObject * @return ESteamUserHasLicenseForAppResult */ UFUNCTION(BlueprintCallable, Category = "SteamBridgeCore|GameServer") - ESteamUserHasLicenseForAppResult UserHasLicenseForApp(FSteamID SteamID, int32 AppID) { return (ESteamUserHasLicenseForAppResult)SteamGameServer()->UserHasLicenseForApp(SteamID, AppID); } + ESteamUserHasLicenseForAppResult UserHasLicenseForApp(FSteamID SteamID, int32 AppID) const { return (ESteamUserHasLicenseForAppResult)SteamGameServer()->UserHasLicenseForApp(SteamID, AppID); } /** * Checks if the master server has alerted us that we are out of date. diff --git a/Source/SteamBridge/Public/Core/SteamInventory.h b/Source/SteamBridge/Public/Core/SteamInventory.h index dc9f568..01de25d 100644 --- a/Source/SteamBridge/Public/Core/SteamInventory.h +++ b/Source/SteamBridge/Public/Core/SteamInventory.h @@ -183,7 +183,8 @@ class STEAMBRIDGE_API USteamInventory final : public UObject /** * Returns the set of all item definition IDs which are defined in the App Admin panel of the Steamworks website. * These item definitions may not necessarily be contiguous integers. - * This should be called in response to a SteamInventoryDefinitionUpdate_t callback. There is no reason to call this function if your game hardcodes the numeric definition IDs (eg, purple face mask = 20, blue weapon mod = 55) and does not allow for adding new item types without a client patch. + * This should be called in response to a SteamInventoryDefinitionUpdate_t callback. There is no reason to call this function if your game hardcodes the numeric definition IDs (eg, purple face mask = 20, blue weapon mod = 55) + * and does not allow for adding new item types without a client patch. * * @param TArray & Items - Returns the item definitions by copying them into this array. * @return bool - This call returns true upon success. It only returns false if item definitions have not been loaded from the server, or no item defintions exist for the current application. @@ -191,8 +192,35 @@ class STEAMBRIDGE_API USteamInventory final : public UObject UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "SteamBridgeCore|Inventory") bool GetItemDefinitionIDs(TArray& Items) const; - // #TODO GetItemDefinitionProperty - // #TODO GetItemsByID + /** + * Gets a string property from the specified item definition. + * Gets a property value for a specific item definition. + * Note that some properties (for example, "name") may be localized and will depend on the current Steam language settings (see ISteamApps::GetCurrentGameLanguage). Property names are always ASCII alphanumeric and underscores. + * Pass in NULL for pchPropertyName to get a comma-separated list of available property names. In this mode, punValueBufferSizeOut will contain the suggested buffer size. Otherwise it will be the number of bytes actually copied to pchValueBuffer. + * + * @param FSteamItemDef Definition - The item definition to get the properties for. + * @param const FString & PropertyName - The property name to get the value for. If you pass in NULL then pchValueBuffer will contain a comma-separated list of all the available names. + * @param FString & Value - Returns the value associated with pchPropertyName. + * @return bool - This returns true upon success; otherwise, false indicating that the item definitions have not been loaded from the server, or no item definitions exist for the current application, or the property name was not found in the item definition. + * The associated value is returned via pchValueBuffer, and the total number of bytes required to hold the value is available from punValueBufferSizeOut. It's recommended to call this function twice, the first time with pchValueBuffer + * set to NULL and punValueBufferSizeOut set to zero to get the size required for the buffer for the subsequent call. + */ + UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "SteamBridgeCore|Inventory") + bool GetItemDefinitionProperty(FSteamItemDef Definition, const FString& PropertyName, FString& Value) const; + + /** + * Gets the state of a subset of the current user's inventory. + * The subset is specified by an array of item instance IDs. + * The results from this call can be serialized using SerializeResult and passed to other players to "prove" that the current user owns specific items, without exposing the user's entire inventory. + * For example, you could call this with the IDs of the user's currently equipped items and serialize this to a buffer, and then transmit this buffer to other players upon joining a game. + * NOTE: You must call DestroyResult on the provided inventory result when you are done with it. + * + * @param FSteamInventoryResult & ResultHandle - Returns a new inventory result handle. + * @param const TArray & InstanceIDs - A list of the item instance ids to update the state of. + * @return bool - This function always returns true when called by a regular user, and always returns false when called from SteamGameServer. Returns a new result handle via pResultHandle. + */ + UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "SteamBridgeCore|Inventory") + bool GetItemsByID(FSteamInventoryResult& ResultHandle, const TArray& InstanceIDs) const; /** * After a successful call to RequestPrices, you can call this method to get the pricing for a specific item definition. @@ -206,7 +234,14 @@ class STEAMBRIDGE_API USteamInventory final : public UObject UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|Inventory") bool GetItemPrice(FSteamItemDef ItemDef, int64& CurrentPrice, int64& BasePrice) const { return SteamInventory()->GetItemPrice(ItemDef, (uint64*)&CurrentPrice, (uint64*)&BasePrice); } - // #TODO GetItemsWithPrices + /** + * After a successful call to RequestPrices, you can call this method to get all the pricing for applicable item definitions. Use the result of GetNumItemsWithPrices as the the size of the arrays that you pass in. + * + * @param TArray & ItemData - The array of item definition ids to populate + * @return bool - true upon success, indicating that pArrayItemDefs and pPrices have been successfully filled with the item definition ids and prices of items that are for sale. false if the parameters are invalid + */ + UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|Inventory") + bool GetItemsWithPrices(TArray& ItemData) const; /** * After a successful call to RequestPrices, this will return the number of item definitions with valid pricing. diff --git a/Source/SteamBridge/Public/Core/SteamUserStats.h b/Source/SteamBridge/Public/Core/SteamUserStats.h index 4d82e2f..fceae20 100644 --- a/Source/SteamBridge/Public/Core/SteamUserStats.h +++ b/Source/SteamBridge/Public/Core/SteamUserStats.h @@ -82,7 +82,7 @@ class STEAMBRIDGE_API USteamUserStats final : public UObject UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "SteamBridgeCore|UserStats") FSteamAPICall DownloadLeaderboardEntries(FSteamLeaderboard SteamLeaderboard, ESteamLeaderboardDataRequest LeaderboardDataRequest, int32 RangeStart, int32 RangeEnd) const; - // #TODO: FSteamAPICall DownloadLeaderboardEntriesForUsers(FSteamLeaderboard SteamLeaderboard, TArray& Users) const; + // #TODO: DownloadLeaderboardEntriesForUsers /** * Gets a leaderboard by name. @@ -195,7 +195,23 @@ class STEAMBRIDGE_API USteamUserStats final : public UObject UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|UserStats") FString GetAchievementName(int32 AchievementIndex = 0) const { return SteamUserStats()->GetAchievementName(AchievementIndex); } - // #TODO: bool GetDownloadedLeaderboardEntry(FSteamLeaderboardEntries SteamLeaderboardEntries, int32 index, FSteamLeaderboardEntry& LeaderboardEntry, int32& Details, int32 DetailsMax) const; + /** + * Retrieves the data for a single leaderboard entry. + * You should use a for loop from 0 to LeaderboardScoresDownloaded_t.m_cEntryCount to get all the downloaded entries. Once you've accessed all the entries, the data will be freed, and the SteamLeaderboardEntries_t handle will become invalid. + * Optionally details may be returned for the entry via the pDetails. If this is NULL then cDetailsMax MUST be 0. + * + * @param FSteamLeaderboardEntries SteamLeaderboardEntries - A leaderboard entries handle obtained from the most recently received LeaderboardScoresDownloaded_t call result. + * @param int32 index - The index of the leaderboard entry to receive, must be between 0 and LeaderboardScoresDownloaded_t.m_cEntryCount. + * @param FSteamLeaderboardEntry & LeaderboardEntry - Variable where the entry will be returned to. + * @param TArray & Details - A preallocated array where the details of this entry get returned into. + * @param int32 DetailsMax - The length of the pDetails array. + * @return bool - This function returns true upon success if all of the following conditions are met; otherwise, false. + * hSteamLeaderboardEntries must be a valid handle from the last received LeaderboardScoresDownloaded_t call result. + * index must be between 0 and LeaderboardScoresDownloaded_t.m_cEntryCount + * If the call is successful then the entry is returned via the parameter pLeaderboardEntry and if cDetailsMax is not 0 then pDetails is filled with the unlock details. + */ + UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|UserStats") + bool GetDownloadedLeaderboardEntry(FSteamLeaderboardEntries SteamLeaderboardEntries, int32 index, FSteamLeaderboardEntry& LeaderboardEntry, TArray& Details, int32 DetailsMax) const; /** * Gets the lifetime totals for an aggregated stat. @@ -296,9 +312,32 @@ class STEAMBRIDGE_API USteamUserStats final : public UObject UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|UserStats") ESteamLeaderboardSortMethod GetLeaderboardSortMethod(FSteamLeaderboard SteamLeaderboard) const { return (ESteamLeaderboardSortMethod)SteamUserStats()->GetLeaderboardSortMethod(SteamLeaderboard); } - // #NOTE: There was some weird error preventing implementation of these methods, will look into later - // #TODO: GetMostAchievedAchievementInfo - // #TODO: GetNextMostAchievedAchievementInfo + /** + * Gets the info on the most achieved achievement for the game. + * You must have called RequestGlobalAchievementPercentages and it needs to return successfully via its callback prior to calling this. + * + * @param FString & Name - String buffer to return the 'API Name' of the achievement into. + * @param float & Percent - Variable to return the percentage of people that have unlocked this achievement from 0 to 100. + * @param bool & bAchieved - Variable to return whether the current user has unlocked this achievement. + * @return int32 - Returns -1 if RequestGlobalAchievementPercentages has not been called or if there are no global achievement percentages for this app Id. + * If the call is successful it returns an iterator which should be used with GetNextMostAchievedAchievementInfo. + */ + UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|UserStats") + int32 GetMostAchievedAchievementInfo(FString& Name, float& Percent, bool& bAchieved) const; + + /** + * Gets the info on the next most achieved achievement for the game. + * You must have called RequestGlobalAchievementPercentages and it needs to return successfully via its callback prior to calling this. + * + * @param int32 IteratorPrevious - Iterator returned from the previous call to this function or from GetMostAchievedAchievementInfo + * @param FString & Name - String buffer to return the 'API Name' of the achievement into. + * @param float & Percent - Variable to return the percentage of people that have unlocked this achievement from 0 to 100. + * @param bool & bAchieved - Variable to return whether the current user has unlocked this achievement. + * @return int32 - Returns -1 if RequestGlobalAchievementPercentages has not been called or if there are no global achievement percentages for this app Id. + * If the call is successful it returns an iterator which should be used with subsequent calls to this function. + */ + UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|UserStats") + int32 GetNextMostAchievedAchievementInfo(int32 IteratorPrevious, FString& Name, float& Percent, bool& bAchieved) const; /** * Get the number of achievements defined in the App Admin panel of the Steamworks website. diff --git a/Source/SteamBridge/Public/Core/SteamUtils.h b/Source/SteamBridge/Public/Core/SteamUtils.h index 4cfb971..1be225c 100644 --- a/Source/SteamBridge/Public/Core/SteamUtils.h +++ b/Source/SteamBridge/Public/Core/SteamUtils.h @@ -110,8 +110,29 @@ class STEAMBRIDGE_API USteamUtils final : public UObject UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|Utils") int32 GetEnteredGamepadTextLength() const { return SteamUtils()->GetEnteredGamepadTextLength(); } - // #TODO: GetImageRGBA - // #TODO: GetImageSize + /** + * Gets the image bytes from an image handle. + * Prior to calling this you must get the size of the image by calling GetImageSize so that you can create your buffer with an appropriate size. You can then allocate your buffer with the width and height as: + * width * height * 4. The image is provided in RGBA format. This call can be somewhat expensive as it converts from the compressed type (JPG, PNG, TGA) and provides no internal caching of returned buffer, + * thus it is highly recommended to only call this once per image handle and cache the result. This function is only used for Steam Avatars and Achievement images and those are not expected to change mid game. + * + * @param int32 Image - The handle to the image that will be obtained. + * @param TArray & Buffer - The buffer that will be filled. + * @return bool - true upon success if the image handle is valid and the buffer was filled out, otherwise false. + */ + UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|Utils") + bool GetImageRGBA(int32 Image, TArray& Buffer) const; + + /** + * Gets the size of a Steam image handle. + * This must be called before calling GetImageRGBA to create an appropriately sized buffer that will be filled with the raw image data. + * + * @param int32 Image - The image handle to get the size for. + * @param FIntPoint & Size - Returns the width/height of the image. + * @return bool - true upon success if the image handle is valid and the sizes were filled out, otherwise false. + */ + UFUNCTION(BlueprintPure, Category = "SteamBridgeCore|Utils") + bool GetImageSize(int32 Image, FIntPoint& Size) const; /** * Returns the number of IPC calls made since the last time this function was called. @@ -201,7 +222,8 @@ class STEAMBRIDGE_API USteamUtils final : public UObject UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "SteamBridgeCore|Utils") bool InitFilterText() const { return SteamUtils()->InitFilterText(); } - // #TODO: FilterText (conflict with API and docs) + // #NOTE: There's a conflict with API and docs + // #TODO: FilterText /** * Checks if Steam & the Steam Overlay are running in Big Picture mode. diff --git a/Source/SteamBridge/Public/SteamBridgeUtils.h b/Source/SteamBridge/Public/SteamBridgeUtils.h index 660b766..d08b83c 100644 --- a/Source/SteamBridge/Public/SteamBridgeUtils.h +++ b/Source/SteamBridge/Public/SteamBridgeUtils.h @@ -20,8 +20,8 @@ class STEAMBRIDGE_API USteamBridgeUtils : public UObject static FString ConvertIPToString(uint32 IP); - UFUNCTION(BlueprintPure, Category = "Steam|USteamBridgeUtils") - FString GetSteamIDAsString(const FSteamID& SteamID) const; + UFUNCTION(BlueprintCallable, Category = "Steam|USteamBridgeUtils") + static FString GetSteamIDAsString(const FSteamID& SteamID); // Thanks to Rama for this method // GetEnumValueAsString("EEnumType", Value); diff --git a/Source/SteamBridge/Public/SteamStructs.h b/Source/SteamBridge/Public/SteamStructs.h index a12ea2d..09f9b30 100644 --- a/Source/SteamBridge/Public/SteamStructs.h +++ b/Source/SteamBridge/Public/SteamStructs.h @@ -512,3 +512,21 @@ struct STEAMBRIDGE_API FSteamUGCDetails FString(UTF8_TO_TCHAR(data.m_rgchTags)).ParseIntoArray(Tags, TEXT(","), true); } }; + +USTRUCT(BlueprintType) +struct STEAMBRIDGE_API FSteamItemPriceData +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite) + FSteamItemDef ItemDef; + + UPROPERTY(BlueprintReadWrite) + int64 CurrentPrice; + + UPROPERTY(BlueprintReadWrite) + int64 BasePrice; + + FSteamItemPriceData() {} + FSteamItemPriceData(FSteamItemDef def, int64 currentPrice, int64 basePrice) : ItemDef(def), CurrentPrice(currentPrice), BasePrice(basePrice) {} +};