Monolith/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamWorkshopLibrary.h

352 lines
16 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BlueprintDataDefinitions.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Online.h"
#include "OnlineSubsystem.h"
#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED
#include "steam/isteamugc.h"
#include "steam/isteamremotestorage.h"
#endif
#include "Interfaces/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)
// #TODO check back on this at some point
#pragma warning(disable:4265) // SteamAPI CCallback< specifically, this warning is off by default but 4.17 turned it on....
#endif
#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED
#pragma push_macro("ARRAY_COUNT")
#undef ARRAY_COUNT
#if USING_CODE_ANALYSIS
MSVC_PRAGMA(warning(push))
MSVC_PRAGMA(warning(disable : ALL_CODE_ANALYSIS_WARNINGS))
#endif // USING_CODE_ANALYSIS
#include <steam/steam_api.h>
#if USING_CODE_ANALYSIS
MSVC_PRAGMA(warning(pop))
#endif // USING_CODE_ANALYSIS
#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:
uint64 SteamWorkshopID;
FBPSteamWorkshopID()
{
}
FBPSteamWorkshopID(uint64 ID)
{
SteamWorkshopID = ID;
}
};
// General result codes - Copying steams version over
// Check these to future proof
UENUM(BlueprintType)
enum class FBPSteamResult : uint8
{
K_EResultInvalid = 0,
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()
{
ResultOfRequest = FBPSteamResult::k_EResultOK;
FileType = FBPWorkshopFileType::k_EWorkshopFileTypeMax;
CreatorAppID = 0;
ConsumerAppID = 0;
VotesUp = 0;
VotesDown = 0;
CalculatedScore = 0.f;
bBanned = false;
bAcceptedForUse = false;
bTagsTruncated = false;
}
#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED
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;
CreatorSteamID = FString::Printf(TEXT("%llu"), hUGCDetails.m_ulSteamIDOwner);
}
FBPSteamWorkshopItemDetails(const 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;
CreatorSteamID = FString::Printf(TEXT("%llu"), hUGCDetails.m_ulSteamIDOwner);
}
#endif
// 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;
// Steam ID of the user who created this content.
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop")
FString CreatorSteamID;
/*
PublishedFileId_t m_nPublishedFileId;
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);
};