mirror of
https://github.com/mordentral/AdvancedSessionsPlugin.git
synced 2025-10-23 08:24:18 +00:00
Merged SteamWorkshop - WIP Branch into default
Former-commit-id: f70e2fc40466acce136259128089729c5a1f7329
This commit is contained in:
@@ -51,6 +51,10 @@ private:
|
|||||||
// Internal callback when the session search completes, calls out to the public success/failure callbacks
|
// Internal callback when the session search completes, calls out to the public success/failure callbacks
|
||||||
void OnCompleted(bool bSuccess);
|
void OnCompleted(bool bSuccess);
|
||||||
|
|
||||||
|
bool bRunSecondSearch;
|
||||||
|
|
||||||
|
TArray<FBlueprintSessionResult> SessionSearchResults;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The player controller triggering things
|
// The player controller triggering things
|
||||||
TWeakObjectPtr<APlayerController> PlayerControllerWeakPtr;
|
TWeakObjectPtr<APlayerController> PlayerControllerWeakPtr;
|
||||||
@@ -63,6 +67,7 @@ private:
|
|||||||
|
|
||||||
// Object to track search results
|
// Object to track search results
|
||||||
TSharedPtr<FOnlineSessionSearch> SearchObject;
|
TSharedPtr<FOnlineSessionSearch> SearchObject;
|
||||||
|
TSharedPtr<FOnlineSessionSearch> SearchObjectDedicated;
|
||||||
|
|
||||||
// Whether or not to search LAN
|
// Whether or not to search LAN
|
||||||
bool bUseLAN;
|
bool bUseLAN;
|
||||||
|
@@ -0,0 +1,297 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "OnlineSubSystemHeader.h"
|
||||||
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||||
|
#include "Online.h"
|
||||||
|
#include "OnlineSubsystem.h"
|
||||||
|
#include "OnlineSessionInterface.h"
|
||||||
|
|
||||||
|
// @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 <steam/steam_api.h>
|
||||||
|
|
||||||
|
#pragma pop_macro("ARRAY_COUNT")
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @todo Steam: See above
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "AdvancedSteamWorkshopLibrary.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
//General Advanced Sessions Log
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(AdvancedSteamWorkshopLog, Log, All);
|
||||||
|
|
||||||
|
|
||||||
|
// Using a custom struct because uint32 isn't blueprint supported and I don't want to cast to int32
|
||||||
|
// due to the size of the workshop it could end up overflowing?
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FBPSteamWorkshopID
|
||||||
|
{
|
||||||
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
uint32 SteamWorkshopID;
|
||||||
|
|
||||||
|
FBPSteamWorkshopID()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FBPSteamWorkshopID(uint32 ID)
|
||||||
|
{
|
||||||
|
SteamWorkshopID = ID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// General result codes - Copying steams version over
|
||||||
|
// Check these to future proof
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class FBPSteamResult : uint8
|
||||||
|
{
|
||||||
|
k_EResultOK = 1, // success
|
||||||
|
k_EResultFail = 2, // generic failure
|
||||||
|
k_EResultNoConnection = 3, // no/failed network connection
|
||||||
|
// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed
|
||||||
|
k_EResultInvalidPassword = 5, // password/ticket is invalid
|
||||||
|
k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere
|
||||||
|
k_EResultInvalidProtocolVer = 7, // protocol version is incorrect
|
||||||
|
k_EResultInvalidParam = 8, // a parameter is incorrect
|
||||||
|
k_EResultFileNotFound = 9, // file was not found
|
||||||
|
k_EResultBusy = 10, // called method busy - action not taken
|
||||||
|
k_EResultInvalidState = 11, // called object was in an invalid state
|
||||||
|
k_EResultInvalidName = 12, // name is invalid
|
||||||
|
k_EResultInvalidEmail = 13, // email is invalid
|
||||||
|
k_EResultDuplicateName = 14, // name is not unique
|
||||||
|
k_EResultAccessDenied = 15, // access is denied
|
||||||
|
k_EResultTimeout = 16, // operation timed out
|
||||||
|
k_EResultBanned = 17, // VAC2 banned
|
||||||
|
k_EResultAccountNotFound = 18, // account not found
|
||||||
|
k_EResultInvalidSteamID = 19, // steamID is invalid
|
||||||
|
k_EResultServiceUnavailable = 20, // The requested service is currently unavailable
|
||||||
|
k_EResultNotLoggedOn = 21, // The user is not logged on
|
||||||
|
k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party)
|
||||||
|
k_EResultEncryptionFailure = 23, // Encryption or Decryption failed
|
||||||
|
k_EResultInsufficientPrivilege = 24, // Insufficient privilege
|
||||||
|
k_EResultLimitExceeded = 25, // Too much of a good thing
|
||||||
|
k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes)
|
||||||
|
k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired
|
||||||
|
k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again
|
||||||
|
k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time
|
||||||
|
k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user
|
||||||
|
k_EResultIPNotFound = 31, // IP address not found
|
||||||
|
k_EResultPersistFailed = 32, // failed to write change to the data store
|
||||||
|
k_EResultLockingFailed = 33, // failed to acquire access lock for this operation
|
||||||
|
k_EResultLogonSessionReplaced = 34,
|
||||||
|
k_EResultConnectFailed = 35,
|
||||||
|
k_EResultHandshakeFailed = 36,
|
||||||
|
k_EResultIOFailure = 37,
|
||||||
|
k_EResultRemoteDisconnect = 38,
|
||||||
|
k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested
|
||||||
|
k_EResultBlocked = 40, // a user didn't allow it
|
||||||
|
k_EResultIgnored = 41, // target is ignoring sender
|
||||||
|
k_EResultNoMatch = 42, // nothing matching the request found
|
||||||
|
k_EResultAccountDisabled = 43,
|
||||||
|
k_EResultServiceReadOnly = 44, // this service is not accepting content changes right now
|
||||||
|
k_EResultAccountNotFeatured = 45, // account doesn't have value, so this feature isn't available
|
||||||
|
k_EResultAdministratorOK = 46, // allowed to take this action, but only because requester is admin
|
||||||
|
k_EResultContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol.
|
||||||
|
k_EResultTryAnotherCM = 48, // The current CM can't service the user making a request, user should try another.
|
||||||
|
k_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed.
|
||||||
|
k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait
|
||||||
|
k_EResultSuspended = 51, // Long running operation (content download) suspended/paused
|
||||||
|
k_EResultCancelled = 52, // Operation canceled (typically by user: content download)
|
||||||
|
k_EResultDataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable
|
||||||
|
k_EResultDiskFull = 54, // Operation canceled - not enough disk space.
|
||||||
|
k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed
|
||||||
|
k_EResultPasswordUnset = 56, // Password could not be verified as it's unset server side
|
||||||
|
k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account
|
||||||
|
k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid
|
||||||
|
k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first
|
||||||
|
k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files
|
||||||
|
k_EResultIllegalPassword = 61, // The requested new password is not legal
|
||||||
|
k_EResultSameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer )
|
||||||
|
k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure
|
||||||
|
k_EResultCannotUseOldPassword = 64, // The requested new password is not legal
|
||||||
|
k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code invalid
|
||||||
|
k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent
|
||||||
|
k_EResultHardwareNotCapableOfIPT = 67, //
|
||||||
|
k_EResultIPTInitError = 68, //
|
||||||
|
k_EResultParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user
|
||||||
|
k_EResultFacebookQueryError = 70, // Facebook query returned an error
|
||||||
|
k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth code expired
|
||||||
|
k_EResultIPLoginRestrictionFailed = 72,
|
||||||
|
k_EResultAccountLockedDown = 73,
|
||||||
|
k_EResultAccountLogonDeniedVerifiedEmailRequired = 74,
|
||||||
|
k_EResultNoMatchingURL = 75,
|
||||||
|
k_EResultBadResponse = 76, // parse failure, missing field, etc.
|
||||||
|
k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password
|
||||||
|
k_EResultValueOutOfRange = 78, // the value entered is outside the acceptable range
|
||||||
|
k_EResultUnexpectedError = 79, // something happened that we didn't expect to ever happen
|
||||||
|
k_EResultDisabled = 80, // The requested service has been configured to be unavailable
|
||||||
|
k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid !
|
||||||
|
k_EResultRestrictedDevice = 82, // The device being used is not allowed to perform this action
|
||||||
|
k_EResultRegionLocked = 83, // The action could not be complete because it is region restricted
|
||||||
|
k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent
|
||||||
|
k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login
|
||||||
|
k_EResultItemDeleted = 86, // The thing we're trying to access has been deleted
|
||||||
|
k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker
|
||||||
|
k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch
|
||||||
|
k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match
|
||||||
|
k_EResultAccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners
|
||||||
|
k_EResultNotModified = 91, // data not modified
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check these to future proof
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class FBPWorkshopFileType : uint8
|
||||||
|
{
|
||||||
|
k_EWorkshopFileTypeCommunity = 0,
|
||||||
|
k_EWorkshopFileTypeMicrotransaction = 1,
|
||||||
|
k_EWorkshopFileTypeCollection = 2,
|
||||||
|
k_EWorkshopFileTypeArt = 3,
|
||||||
|
k_EWorkshopFileTypeVideo = 4,
|
||||||
|
k_EWorkshopFileTypeScreenshot = 5,
|
||||||
|
k_EWorkshopFileTypeGame = 6,
|
||||||
|
k_EWorkshopFileTypeSoftware = 7,
|
||||||
|
k_EWorkshopFileTypeConcept = 8,
|
||||||
|
k_EWorkshopFileTypeWebGuide = 9,
|
||||||
|
k_EWorkshopFileTypeIntegratedGuide = 10,
|
||||||
|
k_EWorkshopFileTypeMerch = 11,
|
||||||
|
k_EWorkshopFileTypeControllerBinding = 12,
|
||||||
|
k_EWorkshopFileTypeSteamworksAccessInvite = 13,
|
||||||
|
k_EWorkshopFileTypeSteamVideo = 14,
|
||||||
|
|
||||||
|
// Update k_EWorkshopFileTypeMax if you add values.
|
||||||
|
k_EWorkshopFileTypeMax = 15
|
||||||
|
};
|
||||||
|
|
||||||
|
// WorkshopItemDetails Struct
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FBPSteamWorkshopItemDetails
|
||||||
|
{
|
||||||
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
FBPSteamWorkshopItemDetails()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FBPSteamWorkshopItemDetails(SteamUGCDetails_t &hUGCDetails)
|
||||||
|
{
|
||||||
|
ResultOfRequest = (FBPSteamResult)hUGCDetails.m_eResult;
|
||||||
|
FileType = (FBPWorkshopFileType)hUGCDetails.m_eFileType;
|
||||||
|
CreatorAppID = (int32)hUGCDetails.m_nCreatorAppID;
|
||||||
|
ConsumerAppID = (int32)hUGCDetails.m_nConsumerAppID;
|
||||||
|
Title = FString(hUGCDetails.m_rgchTitle, k_cchPublishedDocumentTitleMax);
|
||||||
|
Description = FString(hUGCDetails.m_rgchDescription, k_cchPublishedDocumentDescriptionMax);
|
||||||
|
ItemUrl = FString(hUGCDetails.m_rgchURL, k_cchPublishedFileURLMax);
|
||||||
|
VotesUp = (int32)hUGCDetails.m_unVotesUp;
|
||||||
|
VotesDown = (int32)hUGCDetails.m_unVotesDown;
|
||||||
|
CalculatedScore = hUGCDetails.m_flScore;
|
||||||
|
bBanned = hUGCDetails.m_bBanned;
|
||||||
|
bAcceptedForUse = hUGCDetails.m_bAcceptedForUse;
|
||||||
|
bTagsTruncated = hUGCDetails.m_bTagsTruncated;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result of obtaining the details
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
FBPSteamResult ResultOfRequest;
|
||||||
|
|
||||||
|
// Type of file
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
FBPWorkshopFileType FileType;
|
||||||
|
|
||||||
|
// These two are listed as baked to an int, but is stored as a uint, think its safe to keep int
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
int32 CreatorAppID;
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
int32 ConsumerAppID;
|
||||||
|
|
||||||
|
// Title of item
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
FString Title;
|
||||||
|
|
||||||
|
// Description of item
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
FString Description;
|
||||||
|
|
||||||
|
//Url for a video of website
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
FString ItemUrl;
|
||||||
|
|
||||||
|
// Votes will be unlikely to go above signed limited
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
int32 VotesUp;
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
int32 VotesDown;
|
||||||
|
|
||||||
|
// Calculated score
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
float CalculatedScore;
|
||||||
|
|
||||||
|
// whether the file was banned
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
bool bBanned;
|
||||||
|
|
||||||
|
// developer has specifically flagged this item as accepted in the Workshop
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
bool bAcceptedForUse;
|
||||||
|
|
||||||
|
// whether the list of tags was too long to be returned in the provided buffer
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
bool bTagsTruncated;
|
||||||
|
|
||||||
|
/*
|
||||||
|
PublishedFileId_t m_nPublishedFileId;
|
||||||
|
uint64 m_ulSteamIDOwner; // Steam ID of the user who created this content.
|
||||||
|
uint32 m_rtimeCreated; // time when the published file was created
|
||||||
|
uint32 m_rtimeUpdated; // time when the published file was last updated
|
||||||
|
uint32 m_rtimeAddedToUserList; // time when the user added the published file to their list (not always applicable)
|
||||||
|
ERemoteStoragePublishedFileVisibility m_eVisibility; // visibility
|
||||||
|
char m_rgchTags[k_cchTagListMax]; // comma separated list of all tags associated with this file
|
||||||
|
// file/url information
|
||||||
|
UGCHandle_t m_hFile; // The handle of the primary file
|
||||||
|
UGCHandle_t m_hPreviewFile; // The handle of the preview file
|
||||||
|
char m_pchFileName[k_cchFilenameMax]; // The cloud filename of the primary file
|
||||||
|
int32 m_nFileSize; // Size of the primary file
|
||||||
|
int32 m_nPreviewFileSize; // Size of the preview file
|
||||||
|
uint32 m_unNumChildren; // if m_eFileType == k_EWorkshopFileTypeCollection, then this number will be the number of children contained within the collection
|
||||||
|
*/
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class UAdvancedSteamWorkshopLibrary : public UBlueprintFunctionLibrary
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
public:
|
||||||
|
|
||||||
|
//********* Steam Functions *************//
|
||||||
|
|
||||||
|
// Returns IDs for subscribed workshop items, TArray length dictates how many
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
static TArray<FBPSteamWorkshopID> GetSubscribedWorkshopItems(int32 & NumberOfItems);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
static void GetNumSubscribedWorkshopItems(int32 & NumberOfItems);
|
||||||
|
|
||||||
|
};
|
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// 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 <steam/steam_api.h>
|
||||||
|
|
||||||
|
#pragma pop_macro("ARRAY_COUNT")
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @todo Steam: See above
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "SteamWSRequestUGCDetailsCallbackProxy.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintWorkshopDetailsDelegate, const FBPSteamWorkshopItemDetails&, WorkShopDetails);
|
||||||
|
|
||||||
|
UCLASS(MinimalAPI)
|
||||||
|
class USteamWSRequestUGCDetailsCallbackProxy : public UOnlineBlueprintCallProxyBase
|
||||||
|
{
|
||||||
|
GENERATED_UCLASS_BODY()
|
||||||
|
|
||||||
|
// Called when there is a successful results return
|
||||||
|
UPROPERTY(BlueprintAssignable)
|
||||||
|
FBlueprintWorkshopDetailsDelegate OnSuccess;
|
||||||
|
|
||||||
|
// Called when there is an unsuccessful results return
|
||||||
|
UPROPERTY(BlueprintAssignable)
|
||||||
|
FBlueprintWorkshopDetailsDelegate OnFailure;
|
||||||
|
|
||||||
|
// Ends the current session
|
||||||
|
UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedSteamWorkshop")
|
||||||
|
static USteamWSRequestUGCDetailsCallbackProxy* GetWorkshopItemDetails(UObject* WorldContextObject, FBPSteamWorkshopID WorkShopID, int32 NumSecondsBeforeTimeout);
|
||||||
|
|
||||||
|
// UOnlineBlueprintCallProxyBase interface
|
||||||
|
virtual void Activate() override;
|
||||||
|
// End of UOnlineBlueprintCallProxyBase interface
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX
|
||||||
|
// Internal callback when the operation completes, calls out to the public success/failure callbacks
|
||||||
|
/* Steam UGC details */
|
||||||
|
//STEAM_CALLBACK(USteamWSRequestUGCDetailsCallbackProxy, OnUGCRequestUGCDetails, SteamUGCRequestUGCDetailsResult_t, OnUGCRequestUGCDetailsCallback);
|
||||||
|
void OnUGCRequestUGCDetails(SteamUGCRequestUGCDetailsResult_t *pResult, bool bIOFailure);
|
||||||
|
CCallResult<USteamWSRequestUGCDetailsCallbackProxy, SteamUGCRequestUGCDetailsResult_t> m_callResultUGCRequestDetails;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
FBPSteamWorkshopID WorkShopID;
|
||||||
|
|
||||||
|
int32 NumSecondsBeforeTimeout;
|
||||||
|
|
||||||
|
UObject* WorldContextObject;
|
||||||
|
};
|
@@ -115,6 +115,8 @@ UTexture2D * UAdvancedFriendsLibrary::GetSteamFriendAvatar(const FBPUniqueNetId
|
|||||||
SteamUtils()->GetImageSize(Picture, &Width, &Height);
|
SteamUtils()->GetImageSize(Picture, &Width, &Height);
|
||||||
|
|
||||||
// STOLEN FROM ANSWERHUB :p, then fixed because answerhub wasn't releasing the memory O.o
|
// STOLEN FROM ANSWERHUB :p, then fixed because answerhub wasn't releasing the memory O.o
|
||||||
|
// Also fixed image pixel format and switched to a memcpy instead of manual iteration.
|
||||||
|
// At some point I should probably reply to that answerhub post with these fixes to prevent people killing their games.....
|
||||||
|
|
||||||
if (Width > 0 && Height > 0)
|
if (Width > 0 && Height > 0)
|
||||||
{
|
{
|
||||||
|
@@ -12,6 +12,7 @@ UFindSessionsCallbackProxyAdvanced::UFindSessionsCallbackProxyAdvanced(const FOb
|
|||||||
, Delegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted))
|
, Delegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted))
|
||||||
, bUseLAN(false)
|
, bUseLAN(false)
|
||||||
{
|
{
|
||||||
|
bRunSecondSearch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UFindSessionsCallbackProxyAdvanced* UFindSessionsCallbackProxyAdvanced::FindSessionsAdvanced(UObject* WorldContextObject, class APlayerController* PlayerController, int MaxResults, bool bUseLAN, EBPServerPresenceSearchType ServerTypeToSearch, const TArray<FSessionsSearchSetting> &Filters, bool bEmptyServersOnly, bool bNonEmptyServersOnly, bool bSecureServersOnly, int MinSlotsAvailable)
|
UFindSessionsCallbackProxyAdvanced* UFindSessionsCallbackProxyAdvanced::FindSessionsAdvanced(UObject* WorldContextObject, class APlayerController* PlayerController, int MaxResults, bool bUseLAN, EBPServerPresenceSearchType ServerTypeToSearch, const TArray<FSessionsSearchSetting> &Filters, bool bEmptyServersOnly, bool bNonEmptyServersOnly, bool bSecureServersOnly, int MinSlotsAvailable)
|
||||||
@@ -40,6 +41,9 @@ void UFindSessionsCallbackProxyAdvanced::Activate()
|
|||||||
auto Sessions = Helper.OnlineSub->GetSessionInterface();
|
auto Sessions = Helper.OnlineSub->GetSessionInterface();
|
||||||
if (Sessions.IsValid())
|
if (Sessions.IsValid())
|
||||||
{
|
{
|
||||||
|
// Re-initialize here, otherwise I think there might be issues with people re-calling search for some reason before it is destroyed
|
||||||
|
bRunSecondSearch = false;
|
||||||
|
|
||||||
DelegateHandle = Sessions->AddOnFindSessionsCompleteDelegate_Handle(Delegate);
|
DelegateHandle = Sessions->AddOnFindSessionsCompleteDelegate_Handle(Delegate);
|
||||||
|
|
||||||
SearchObject = MakeShareable(new FOnlineSessionSearch);
|
SearchObject = MakeShareable(new FOnlineSessionSearch);
|
||||||
@@ -81,6 +85,18 @@ void UFindSessionsCallbackProxyAdvanced::Activate()
|
|||||||
if (MinSlotsAvailable != 0)
|
if (MinSlotsAvailable != 0)
|
||||||
tem.Set(SEARCH_MINSLOTSAVAILABLE, MinSlotsAvailable, EOnlineComparisonOp::GreaterThanEquals);
|
tem.Set(SEARCH_MINSLOTSAVAILABLE, MinSlotsAvailable, EOnlineComparisonOp::GreaterThanEquals);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Filter results
|
||||||
|
if (SearchSettings.Num() > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < SearchSettings.Num(); i++)
|
||||||
|
{
|
||||||
|
// Function that was added to make directly adding a FVariant possible
|
||||||
|
tem.HardSet(SearchSettings[i].PropertyKeyPair.Key, SearchSettings[i].PropertyKeyPair.Data, SearchSettings[i].ComparisonOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (ServerSearchType)
|
switch (ServerSearchType)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -99,21 +115,19 @@ void UFindSessionsCallbackProxyAdvanced::Activate()
|
|||||||
case EBPServerPresenceSearchType::AllServers:
|
case EBPServerPresenceSearchType::AllServers:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// tem.Set(SEARCH_DEDICATED_ONLY, false, EOnlineComparisonOp::Equals);
|
bRunSecondSearch = true;
|
||||||
// tem.Set(SEARCH_PRESENCE, false, EOnlineComparisonOp::Equals);
|
|
||||||
|
SearchObjectDedicated = MakeShareable(new FOnlineSessionSearch);
|
||||||
|
SearchObjectDedicated->MaxSearchResults = MaxResults;
|
||||||
|
SearchObjectDedicated->bIsLanQuery = bUseLAN;
|
||||||
|
|
||||||
|
FOnlineSearchSettingsEx DedicatedOnly = tem;
|
||||||
|
tem.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
|
||||||
|
|
||||||
|
DedicatedOnly.Set(SEARCH_DEDICATED_ONLY, true, EOnlineComparisonOp::Equals);
|
||||||
|
SearchObjectDedicated->QuerySettings = DedicatedOnly;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter results
|
|
||||||
if (SearchSettings.Num() > 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < SearchSettings.Num(); i++)
|
|
||||||
{
|
|
||||||
// Function that was added to make directly adding a FVariant possible
|
|
||||||
tem.HardSet(SearchSettings[i].PropertyKeyPair.Key, SearchSettings[i].PropertyKeyPair.Data, SearchSettings[i].ComparisonOp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the derived temp variable over to it's base class
|
// Copy the derived temp variable over to it's base class
|
||||||
@@ -131,8 +145,7 @@ void UFindSessionsCallbackProxyAdvanced::Activate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fail immediately
|
// Fail immediately
|
||||||
TArray<FBlueprintSessionResult> Results;
|
OnFailure.Broadcast(SessionSearchResults);
|
||||||
OnFailure.Broadcast(Results);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UFindSessionsCallbackProxyAdvanced::OnCompleted(bool bSuccess)
|
void UFindSessionsCallbackProxyAdvanced::OnCompleted(bool bSuccess)
|
||||||
@@ -140,7 +153,7 @@ void UFindSessionsCallbackProxyAdvanced::OnCompleted(bool bSuccess)
|
|||||||
FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("FindSessionsCallback"), GEngine->GetWorldFromContextObject(WorldContextObject));
|
FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("FindSessionsCallback"), GEngine->GetWorldFromContextObject(WorldContextObject));
|
||||||
Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get());
|
Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get());
|
||||||
|
|
||||||
if (Helper.IsValid())
|
if (!bRunSecondSearch && Helper.IsValid())
|
||||||
{
|
{
|
||||||
auto Sessions = Helper.OnlineSub->GetSessionInterface();
|
auto Sessions = Helper.OnlineSub->GetSessionInterface();
|
||||||
if (Sessions.IsValid())
|
if (Sessions.IsValid())
|
||||||
@@ -149,51 +162,43 @@ void UFindSessionsCallbackProxyAdvanced::OnCompleted(bool bSuccess)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<FBlueprintSessionResult> Results;
|
|
||||||
|
|
||||||
if (bSuccess && SearchObject.IsValid())
|
if (bSuccess && SearchObject.IsValid())
|
||||||
{
|
{
|
||||||
// Just log the results for now, will need to add a blueprint-compatible search result struct
|
// Just log the results for now, will need to add a blueprint-compatible search result struct
|
||||||
for (auto& Result : SearchObject->SearchResults)
|
for (auto& Result : SearchObject->SearchResults)
|
||||||
{
|
{
|
||||||
/* bool bAddResult = true;
|
|
||||||
|
|
||||||
// Filter results
|
|
||||||
if (SearchSettings.Num() > 0)
|
|
||||||
{
|
|
||||||
FOnlineSessionSetting * setting;
|
|
||||||
for (int i = 0; i < SearchSettings.Num(); i++)
|
|
||||||
{
|
|
||||||
setting = Result.Session.SessionSettings.Settings.Find(SearchSettings[i].PropertyKeyPair.Key);
|
|
||||||
|
|
||||||
// Couldn't find this key
|
|
||||||
if (!setting)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!CompareVariants(setting->Data, SearchSettings[i].PropertyKeyPair.Data, SearchSettings[i].ComparisonOp))
|
|
||||||
{
|
|
||||||
bAddResult = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//if (bAddResult)
|
|
||||||
//{
|
|
||||||
FString ResultText = FString::Printf(TEXT("Found a session. Ping is %d"), Result.PingInMs);
|
FString ResultText = FString::Printf(TEXT("Found a session. Ping is %d"), Result.PingInMs);
|
||||||
|
|
||||||
FFrame::KismetExecutionMessage(*ResultText, ELogVerbosity::Log);
|
FFrame::KismetExecutionMessage(*ResultText, ELogVerbosity::Log);
|
||||||
|
|
||||||
FBlueprintSessionResult BPResult;
|
FBlueprintSessionResult BPResult;
|
||||||
BPResult.OnlineResult = Result;
|
BPResult.OnlineResult = Result;
|
||||||
Results.Add(BPResult);
|
SessionSearchResults.Add(BPResult);
|
||||||
//}
|
}
|
||||||
|
if (!bRunSecondSearch)
|
||||||
|
{
|
||||||
|
OnSuccess.Broadcast(SessionSearchResults);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
OnSuccess.Broadcast(Results);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OnFailure.Broadcast(Results);
|
if (!bRunSecondSearch)
|
||||||
|
{
|
||||||
|
// Need to account for only one of the searches failing
|
||||||
|
if(SessionSearchResults.Num() > 0)
|
||||||
|
OnSuccess.Broadcast(SessionSearchResults);
|
||||||
|
else
|
||||||
|
OnFailure.Broadcast(SessionSearchResults);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bRunSecondSearch && ServerSearchType == EBPServerPresenceSearchType::AllServers)
|
||||||
|
{
|
||||||
|
bRunSecondSearch = false;
|
||||||
|
auto Sessions = Helper.OnlineSub->GetSessionInterface();
|
||||||
|
Sessions->FindSessions(*Helper.UserID, SearchObjectDedicated.ToSharedRef());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,69 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
#include "OnlineSubSystemHeader.h"
|
||||||
|
#include "SteamFuncs/AdvancedSteamWorkshopLibrary.h"
|
||||||
|
//General Log
|
||||||
|
DEFINE_LOG_CATEGORY(AdvancedSteamWorkshopLog);
|
||||||
|
|
||||||
|
|
||||||
|
void UAdvancedSteamWorkshopLibrary::GetNumSubscribedWorkshopItems(int32 & NumberOfItems)
|
||||||
|
{
|
||||||
|
NumberOfItems = 0;
|
||||||
|
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX
|
||||||
|
|
||||||
|
if (SteamAPI_Init())
|
||||||
|
{
|
||||||
|
NumberOfItems = SteamUGC()->GetNumSubscribedItems();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetNumSubscribedWorkshopItemCount : SteamAPI is not Inited!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetNumSubscribedWorkshopItemCount : Called on an incompatible platform"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FBPSteamWorkshopID> UAdvancedSteamWorkshopLibrary::GetSubscribedWorkshopItems(int32 & NumberOfItems)
|
||||||
|
{
|
||||||
|
TArray<FBPSteamWorkshopID> outArray;
|
||||||
|
NumberOfItems = 0;
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX
|
||||||
|
|
||||||
|
if (SteamAPI_Init())
|
||||||
|
{
|
||||||
|
uint32 NumItems = SteamUGC()->GetNumSubscribedItems();
|
||||||
|
|
||||||
|
if (NumItems == 0)
|
||||||
|
return outArray;
|
||||||
|
|
||||||
|
// Not using the actual variable above in case someone somehow goes past int32 limits
|
||||||
|
// Don't want to go negative on the iteration.
|
||||||
|
NumberOfItems = NumItems;
|
||||||
|
|
||||||
|
PublishedFileId_t *fileIds = new PublishedFileId_t[NumItems];
|
||||||
|
|
||||||
|
uint32 subItems = SteamUGC()->GetSubscribedItems(fileIds, NumItems);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < subItems; ++i)
|
||||||
|
{
|
||||||
|
outArray.Add(FBPSteamWorkshopID(fileIds[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete fileIds;
|
||||||
|
|
||||||
|
return outArray;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetSubscribedWorkshopItemCount : SteamAPI is not Inited!"));
|
||||||
|
return outArray;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetSubscribedWorkshopItemCount : Called on an incompatible platform"));
|
||||||
|
return outArray;
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "OnlineSubSystemHeader.h"
|
||||||
|
#include "SteamFuncs/SteamWSRequestUGCDetailsCallbackProxy.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// UEndSessionCallbackProxy
|
||||||
|
|
||||||
|
USteamWSRequestUGCDetailsCallbackProxy::USteamWSRequestUGCDetailsCallbackProxy(const FObjectInitializer& ObjectInitializer)
|
||||||
|
: Super(ObjectInitializer)
|
||||||
|
{
|
||||||
|
NumSecondsBeforeTimeout = 4.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
USteamWSRequestUGCDetailsCallbackProxy* USteamWSRequestUGCDetailsCallbackProxy::GetWorkshopItemDetails(UObject* WorldContextObject, FBPSteamWorkshopID WorkShopID, int32 NumSecondsBeforeTimeout)
|
||||||
|
{
|
||||||
|
USteamWSRequestUGCDetailsCallbackProxy* Proxy = NewObject<USteamWSRequestUGCDetailsCallbackProxy>();
|
||||||
|
|
||||||
|
Proxy->WorkShopID = WorkShopID;
|
||||||
|
Proxy->NumSecondsBeforeTimeout = NumSecondsBeforeTimeout;
|
||||||
|
return Proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USteamWSRequestUGCDetailsCallbackProxy::Activate()
|
||||||
|
{
|
||||||
|
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX
|
||||||
|
if (SteamAPI_Init())
|
||||||
|
{
|
||||||
|
SteamAPICall_t hSteamAPICall = SteamUGC()->RequestUGCDetails(WorkShopID.SteamWorkshopID, NumSecondsBeforeTimeout);
|
||||||
|
m_callResultUGCRequestDetails.Set(hSteamAPICall, this, &USteamWSRequestUGCDetailsCallbackProxy::OnUGCRequestUGCDetails);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OnFailure.Broadcast(FBPSteamWorkshopItemDetails());
|
||||||
|
}
|
||||||
|
|
||||||
|
void USteamWSRequestUGCDetailsCallbackProxy::OnUGCRequestUGCDetails(SteamUGCRequestUGCDetailsResult_t *pResult, bool bIOFailure)
|
||||||
|
{
|
||||||
|
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX
|
||||||
|
|
||||||
|
if (bIOFailure || !pResult)
|
||||||
|
{
|
||||||
|
OnFailure.Broadcast(FBPSteamWorkshopItemDetails());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnSuccess.Broadcast(FBPSteamWorkshopItemDetails(pResult->m_details));
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OnFailure.Broadcast(FBPSteamWorkshopItemDetails());
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user