diff --git a/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamFriendsLibrary.h b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamFriendsLibrary.h index 7accb05..a1a562e 100644 --- a/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamFriendsLibrary.h +++ b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamFriendsLibrary.h @@ -29,6 +29,29 @@ enum class SteamAvatarSize : uint8 SteamAvatar_Large = 3 }; +USTRUCT(BlueprintType, Category = "Online|SteamAPI|SteamGroups") +struct FBPSteamGroupInfo +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FBPUniqueNetId GroupID; // Uint64 representation + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FString GroupName; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FString GroupTag; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + int32 numOnline; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + int32 numInGame; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + int32 numChatting; + +}; + + UCLASS() class UAdvancedSteamFriendsLibrary : public UBlueprintFunctionLibrary @@ -57,4 +80,14 @@ public: // Creates a unique steam id directly from a string holding a uint64 value, useful for testing UFUNCTION(BlueprintPure, Category = "Online|AdvancedFriends|SteamAPI") static FBPUniqueNetId CreateSteamIDFromString(const FString SteamID64); + + /* Gets the current game played by a friend - AppID is int32 even though steam ids are uint32, can't be helped in blueprint currently + * The game name is retrieved from steamSDK AppList which isn't available to all game IDs without request, can use the AppID with the + * WebAPI GetAppList request as an alternative. + */ + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|SteamAPI", meta = (ExpandEnumAsExecs = "Result")) + static void GetSteamFriendGamePlayed(const FBPUniqueNetId UniqueNetId, EBlueprintResultSwitch &Result, FString & GameName, int32 & AppID); + + UFUNCTION(BlueprintCallable, Category = "Online|SteamAPI|SteamGroups") + static void GetSteamGroups(TArray & SteamGroups); }; diff --git a/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamRequestGroupOfficersCallbackProxy.h b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamRequestGroupOfficersCallbackProxy.h new file mode 100644 index 0000000..f3ba307 --- /dev/null +++ b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamRequestGroupOfficersCallbackProxy.h @@ -0,0 +1,83 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" + +// This is taken directly from UE4 - OnlineSubsystemSteamPrivatePCH.h as a fix for the array_count macro + +// @todo Steam: Steam headers trigger secure-C-runtime warnings in Visual C++. Rather than mess with _CRT_SECURE_NO_WARNINGS, we'll just +// disable the warnings locally. Remove when this is fixed in the SDK +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4996) +#endif + +#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX + +#pragma push_macro("ARRAY_COUNT") +#undef ARRAY_COUNT + +#include + +#pragma pop_macro("ARRAY_COUNT") + +#endif + +// @todo Steam: See above +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "SteamRequestGroupOfficersCallbackProxy.generated.h" + +USTRUCT(BlueprintType, Category = "Online|SteamAPI|SteamGroups") +struct FBPSteamGroupOfficer +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FBPUniqueNetId OfficerUniqueNetID; // Uint64 representation + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + bool bIsOwner; + +}; + + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintGroupOfficerDetailsDelegate, const TArray &, OfficerList); + +UCLASS(MinimalAPI) +class USteamRequestGroupOfficersCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful results return + UPROPERTY(BlueprintAssignable) + FBlueprintGroupOfficerDetailsDelegate OnSuccess; + + // Called when there is an unsuccessful results return + UPROPERTY(BlueprintAssignable) + FBlueprintGroupOfficerDetailsDelegate OnFailure; + + // Retruns a list of steam group officers + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|SteamAPI|SteamGroups") + static USteamRequestGroupOfficersCallbackProxy* GetSteamGroupOfficerList(UObject* WorldContextObject, FBPUniqueNetId GroupUniqueNetID); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + +#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX + void OnRequestGroupOfficerDetails( ClanOfficerListResponse_t *pResult, bool bIOFailure); + CCallResult m_callResultGroupOfficerRequestDetails; +#endif + +private: + + FBPUniqueNetId GroupUniqueID; + UObject* WorldContextObject; +}; diff --git a/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamFriendsLibrary.cpp b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamFriendsLibrary.cpp index c329a76..1260a3a 100644 --- a/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamFriendsLibrary.cpp +++ b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamFriendsLibrary.cpp @@ -17,6 +17,8 @@ #undef ARRAY_COUNT #include +#include +#include #include #pragma pop_macro("ARRAY_COUNT") @@ -81,6 +83,75 @@ DEFINE_LOG_CATEGORY(AdvancedSteamFriendsLog); return 0; }*/ +void UAdvancedSteamFriendsLibrary::GetSteamGroups(TArray & SteamGroups) +{ +#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX + + if (SteamAPI_Init()) + { + int numClans = SteamFriends()->GetClanCount(); + + for (int i = 0; i < numClans; i++) + { + CSteamID SteamGroupID = SteamFriends()->GetClanByIndex(i); + + if(!SteamGroupID.IsValid()) + continue; + + FBPSteamGroupInfo GroupInfo; + + TSharedPtr ValueID(new const FUniqueNetIdSteam(SteamGroupID)); + GroupInfo.GroupID.SetUniqueNetId(ValueID); + SteamFriends()->GetClanActivityCounts(SteamGroupID, &GroupInfo.numOnline, &GroupInfo.numInGame, &GroupInfo.numChatting); + GroupInfo.GroupName = FString(UTF8_TO_TCHAR(SteamFriends()->GetClanName(SteamGroupID))); + GroupInfo.GroupTag = FString(UTF8_TO_TCHAR(SteamFriends()->GetClanTag(SteamGroupID))); + + SteamGroups.Add(GroupInfo); + } + } +#endif +} + +void UAdvancedSteamFriendsLibrary::GetSteamFriendGamePlayed(const FBPUniqueNetId UniqueNetId, EBlueprintResultSwitch &Result, FString & GameName, int32 & AppID) +{ + +#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid()) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("GetSteamFriendGamePlayed Had a bad UniqueNetId!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + + FriendGameInfo_t GameInfo; + bool bIsInGame = SteamFriends()->GetFriendGamePlayed(id, &GameInfo); + + if (bIsInGame && GameInfo.m_gameID.IsValid()) + { + AppID = GameInfo.m_gameID.AppID(); + + char NameBuffer[512]; + int Len = SteamAppList()->GetAppName(GameInfo.m_gameID.AppID(), NameBuffer, 512); + + if (Len != -1) // Invalid + { + GameName = FString(UTF8_TO_TCHAR(NameBuffer)); + } + + Result = EBlueprintResultSwitch::OnSuccess; + return; + } + + } +#endif + + Result = EBlueprintResultSwitch::OnFailure; +} + int32 UAdvancedSteamFriendsLibrary::GetFriendSteamLevel(const FBPUniqueNetId UniqueNetId) { diff --git a/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamRequestGroupOfficersCallbackProxy.cpp b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamRequestGroupOfficersCallbackProxy.cpp new file mode 100644 index 0000000..0a462c0 --- /dev/null +++ b/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamRequestGroupOfficersCallbackProxy.cpp @@ -0,0 +1,82 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "SteamRequestGroupOfficersCallbackProxy.h" +#include "OnlineSubSystemHeader.h" + +////////////////////////////////////////////////////////////////////////// +// UEndSessionCallbackProxy + +USteamRequestGroupOfficersCallbackProxy::USteamRequestGroupOfficersCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + + +USteamRequestGroupOfficersCallbackProxy* USteamRequestGroupOfficersCallbackProxy::GetSteamGroupOfficerList(UObject* WorldContextObject, FBPUniqueNetId GroupUniqueNetID) +{ + USteamRequestGroupOfficersCallbackProxy* Proxy = NewObject(); + + Proxy->GroupUniqueID = GroupUniqueNetID; + return Proxy; +} + +void USteamRequestGroupOfficersCallbackProxy::Activate() +{ +#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)GroupUniqueID.UniqueNetId->GetBytes()); + SteamAPICall_t hSteamAPICall = SteamFriends()->RequestClanOfficerList(id); + m_callResultGroupOfficerRequestDetails.Set(hSteamAPICall, this, &USteamRequestGroupOfficersCallbackProxy::OnRequestGroupOfficerDetails); + return; + } +#endif + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); +} + +void USteamRequestGroupOfficersCallbackProxy::OnRequestGroupOfficerDetails(ClanOfficerListResponse_t *pResult, bool bIOFailure) +{ + TArray OfficerArray; + +#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX + + if (bIOFailure || !pResult || !pResult->m_bSuccess) + { + OnFailure.Broadcast(OfficerArray); + return; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)GroupUniqueID.UniqueNetId->GetBytes()); + + FBPSteamGroupOfficer Officer; + CSteamID ClanOwner = SteamFriends()->GetClanOwner(id); + + Officer.bIsOwner = true; + + TSharedPtr ValueID(new const FUniqueNetIdSteam(ClanOwner)); + Officer.OfficerUniqueNetID.SetUniqueNetId(ValueID); + OfficerArray.Add(Officer); + + for (int i = 0; i < pResult->m_cOfficers; i++) + { + CSteamID OfficerSteamID = SteamFriends()->GetClanOfficerByIndex(id, i); + + Officer.bIsOwner = false; + + TSharedPtr ValueID(new const FUniqueNetIdSteam(OfficerSteamID)); + Officer.OfficerUniqueNetID.SetUniqueNetId(ValueID); + + OfficerArray.Add(Officer); + } + + OnSuccess.Broadcast(OfficerArray); + return; + } +#endif + + OnFailure.Broadcast(OfficerArray); +} +