diff --git a/Config/Localization/Modio.ini b/Config/Localization/Modio.ini new file mode 100644 index 00000000..66591cae --- /dev/null +++ b/Config/Localization/Modio.ini @@ -0,0 +1,52 @@ +[CommonSettings] +SourcePath=Plugins/Modio/Content/UI/Localization +DestinationPath=Plugins/Modio/Content/UI/Localization +ManifestName=Modio.manifest +ArchiveName=Modio.archive +PortableObjectName=Modio.po +ResourceName=Modio.locres +NativeCulture=en +CulturesToGenerate=en + +;Gather text from source code +[GatherTextStep0] +CommandletClass=GatherTextFromSource +SearchDirectoryPaths=Plugins/Modio/Source/ModioUI +FileNameFilters=*.cpp +FileNameFilters=*.h +FileNameFilters=*.c +FileNameFilters=*.inl +FileNameFilters=*.mm +FileNameFilters=*.ini +FileNameFilters=*.csv +ShouldGatherFromEditorOnlyData=false + +[GatherTextStep1] +CommandletClass=GatherTextFromAssets +IncludePathFilters=Plugins/Modio/Content/* +ExcludePathFilters=Plugins/Modio/Content/UI/Localization/* +PackageFileNameFilters=*.uasset +PackageFileNameFilters=*.umap + + +;Write Manifest +[GatherTextStep2] +CommandletClass=GenerateGatherManifest + +;Write Archives +[GatherTextStep3] +CommandletClass=GenerateGatherArchive + +;Import localized PO files +[GatherTextStep4] +CommandletClass=InternationalizationExport +bImportLoc=true + +;Write Localized Text Resource +[GatherTextStep5] +CommandletClass=GenerateTextLocalizationResource + +;Export PO files +[GatherTextStep6] +CommandletClass=InternationalizationExport +bExportLoc=true \ No newline at end of file diff --git a/Doc/documentation.html b/Doc/documentation.html index f7d716d9..4872faeb 100644 --- a/Doc/documentation.html +++ b/Doc/documentation.html @@ -802,6 +802,8 @@

mod.io UE4 Plugin Documentation

  • Checking for errors
  • Inspecting ErrorCodes more deeply
  • Parameter Validation Errors
  • +
  • Submitting a new mod
  • +
  • Submitting a file for a mod
  • @@ -847,6 +849,7 @@

    mod.io UE4 Plugin Documentation

  • ClearUserDataAsync
  • AuthenticateUserExternalAsync
  • AuthenticateUserEmailAsync
  • +
  • ArchiveModAsync
  • Is Mod Management Busy
  • Get Last Validation Error
  • ForceUninstallModAsync
  • @@ -897,6 +900,7 @@

    mod.io UE4 Plugin Documentation

  • ModioModDependency
  • ModioOptionalModProgressInfo
  • ModioModProgressInfo
  • +
  • ModioUnsigned64
  • ModioReportParams
  • ModioTerms
  • ModioLink
  • @@ -937,6 +941,16 @@

    mod.io UE4 Plugin Documentation

  • Get Project Environment
  • Get Project Api Key
  • ToString (Filesize)
  • +
  • ModioUnsigned64 - ModioUnsigned64
  • +
  • ModioUnsigned64 != ModioUnsigned64
  • +
  • Make from Components
  • +
  • ModioUnsigned64 < ModioUnsigned64
  • +
  • ModioUnsigned64 > ModioUnsigned64
  • +
  • ModioUnsigned64 == ModioUnsigned64
  • +
  • ModioUnsigned64 / float
  • +
  • ModioUnsigned64 / ModioUnsigned64
  • +
  • Break to Components
  • +
  • ModioUnsigned64 + ModioUnsigned64
  • SubmitNewModFileForModFromMemory
  • LoadModFileToMemory
  • @@ -955,6 +969,7 @@

    mod.io UE4 Plugin Documentation

  • EModioLogoSize
  • EModioPortal
  • EModioEnvironment
  • +
  • EModioErrorCondition
  • EModioSortDirection
  • EModioSortFieldType
  • EModioImageState
  • @@ -1129,7 +1144,7 @@

    Thread-safety guarantees

    Non-blocking, asynchronous interface

    -

    The plugin communicates with the mod.io servers, the filesystem on the device you’re using, and platform-provided services for authentication. All of these may not return results immediately, so many functions provided by the ModioSubsystem are non-blocking and asynchronous.

    +

    The plugin communicates with the mod.io servers, the filesystem on the device you’re using, and platform-provided services for authentication. All of these may not return results immediately, so many functions provided by the ModioSubsystem are non-blocking and asynchronous. For example, the initialization function returns immediately. However, your game should consider the ModioSybsystem as initialized only when the init callback executes.

    @@ -1213,18 +1228,16 @@

    Mod Data Directory

    - + - - - + + + - - - - + +
    WindowsLinuxOSX

    Windows

    Linux

    OSX

    ${FolderID_Public}/mod.io

    TBD

    TBD

    ${USER_HOME}/mod.io

    ${USER_HOME}/Library/Application Support/mod.io

    @@ -1304,6 +1317,9 @@

    Plugin quick-start: Ini
  • The error-handling in this sample has been omitted. See Plugin quick-start: Error Handling for more information on error handling.

  • +
  • +

    To fully initialize the SDK, you must receive confirmation from the callback. Consider that most functions return after invocation, nonetheless, their effects are only visible in their callback function

    +
  • @@ -1547,6 +1563,52 @@

    SSO/External authentication

    authenticate user external +
    +

    Note that the SDK will automatically URL encode parameters (such as the auth token) when making the request.

    +
    +
    +
    Steam Authentication Example
    +
    +

    In order to use the Steam authentication functionality, you must add your games Encrypted App Ticket Key from Steamworks. On your games profile on mod.io, go to Edit > Options and add the key. You can then call AuthenticateUserExternalAsync and provide the users Encrypted App Ticket as the Auth Token. Note that the Auth Token must be Base64 encoded when passed

    +
    +
    +

    Below is a sample Blueprint method that will get the users current Encrypted App Ticket that you can use in your Authentication request. Add this to a BlueprintLibrary in your games codebase.

    +
    +
    +C++ Example +
    +
    +
    +
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnGetTicket, int32, LocalUserNum, FString, TokenData);
    +UFUNCTION(BlueprintCallable)
    +static void GetSteamAuthTicket(int32 LocalUserNum, FOnGetTicket Callback)
    +{
    +    //Get the steam subsystem
    +    FOnlineSubsystemSteam* SteamSubsystem = static_cast<FOnlineSubsystemSteam*>(IOnlineSubsystem::Get());
    +    //Add a handler to the subsystem for when the ticket has been retrieved
    +    SteamSubsystem->GetEncryptedAppTicketInterface()->OnEncryptedAppTicketResultDelegate.AddLambda(
    +        [LocalUserNum, OnComplete = Callback](bool bEncryptedDataAvailable, int32 ResultCode) {
    +
    +            TArray<uint8> TokenData;
    +            if (bEncryptedDataAvailable)
    +            {
    +                //If the ticket was retrieved successfully, get its data
    +                SteamSubsystem->GetEncryptedAppTicketInterface()->GetEncryptedAppTicket(TokenData);
    +            }
    +            //Call the user callback with the base64-encoded ticket, ready for submission via AuthenticateUserExternalAsync
    +            OnComplete.ExecuteIfBound(LocalUserNum, FBase64::Encode(TokenData));
    +        });
    +    //Begin the actual async request for the ticket, which will invoke the above lambda when it completes
    +    SteamSubsystem->GetEncryptedAppTicketInterface()->RequestEncryptedAppTicket(nullptr, 0);
    +}
    +
    +
    +
    +

    Note that if you are on 4.27 or above, Epic provides a helper method in OnlineIdentityInterface::GetLinkedAccountAuthToken that will get the current account’s auth token without having to take a direct dependency on FOnlineSubsystemSteam. Ensure that the token is Base64 encoded when being passed to AuthenticateUserExternalAsync.

    +
    +
    +
    +

    Token Lifetime & Re-Authentication

    @@ -2000,6 +2062,91 @@

    Parameter Validation Errors


    +
    +

    Submitting a new mod

    +
    +

    In order to submit a mod, you have to first create a mod handle using GetModCreationHandle and use that handle when calling SubmitNewModAsync

    +
    +
    +Blueprint Example +
    +
    +
    +submit new mod +
    +
    +
    +
    +
    +C++ Example +
    +
    +
    +
    void UModioManager::SubmitNewMod()
    +{
    +	if (GEngine->GetEngineSubsystem<UModioSubsystem>())
    +	{
    +		FModioModCreationHandle Handle = GEngine->GetEngineSubsystem<UModioSubsystem>()->GetModCreationHandle();
    +
    +		FModioCreateModParams Params;
    +		Params.Name = TEXT("My Awesome Mod");
    +		Params.Description = TEXT("This is an amazing mod");
    +		Params.PathToLogoFile = TEXT("C:\\temp\\image.png");
    +
    +		GEngine->GetEngineSubsystem<UModioSubsystem>()->SubmitNewModAsync(Handle, Params, FOnSubmitNewModDelegateFast::CreateUObject(this, &UModioManager::OnSubmitNewModCallback));
    +	}
    +}
    +
    +void UModioManager::OnSubmitNewModCallback(FModioErrorCode ErrorCode, TOptional<FModioModID> ModId)
    +{
    +	if (ErrorCode == false)
    +	{
    +		// Mod was submitted successfully. Use ModId to submit some files to it.
    +	}
    +}
    +
    +
    +
    +
    +
    +
    +

    Submitting a file for a mod

    +
    +

    Once you have successfully submitted a mod, you can then submit a file for that mod using SubmitNewModFileForMod. When you submit a file, you pass a ModioCreateModFileParams containing the directory of the files that you want to submit. The plugin will then compress this folder into a zip file and upload it as the active version of the mod. Note that there is no callback for this method; you’ll get notified of the completed upload by the Mod Management callbacks.

    +
    +
    +Blueprint Example +
    +
    +

    As an example, after the callback for submitting a mod has completed, you can get the Mod Id to use for file submission.

    +
    +
    +
    +submit new mod file +
    +
    +
    +
    +
    +C++ Example +
    +
    +
    +
    void UModioManager::SubmitNewModFile(FModioModID ModId)
    +{
    +	if (GEngine->GetEngineSubsystem<UModioSubsystem>())
    +	{
    +		FModioCreateModFileParams Params;
    +		Params.PathToModRootDirectory = TEXT("C:\\temp\\mod_folder");
    +
    +		GEngine->GetEngineSubsystem<UModioSubsystem>()->SubmitNewModFileForMod(ModId, Params);
    +	}
    +}
    +
    +
    +
    +
    +
    @@ -3627,7 +3774,7 @@

    EnableModManagement

    -
    void K2_EnableModManagement(FOnModManagementDelegate Callback)
    +
    FModioErrorCode K2_EnableModManagement(FOnModManagementDelegate Callback)
    @@ -3648,6 +3795,10 @@
    Parameters

    Callback

    This callback handler will be invoked with a ModManagementEvent for each mod operation performed by the SDK

    + +

    Return Value

    + +
    @@ -3868,6 +4019,83 @@
    Error Values

    +

    ArchiveModAsync

    +
    +
    +nd img K2 ArchiveModAsync +
    +
    +
    +
    +
    void K2_ArchiveModAsync(FModioModID Mod, FOnErrorOnlyDelegate Callback)
    +
    +
    +
    +

    Archives a mod. This mod will no longer be able to be viewed or retrieved via the SDK, but it will still exist should you choose to restore it at a later date. Archiving is restricted to team managers and administrators only. Note that restoration and permanent deletion of a mod is possible only via web interface.

    +
    +
    Requirements
    +
    + +
    +
    Parameters
    + ++++ + + + + + + + + + + + + + + +

    Target

    Modio Subsystem Object Reference

    Mod

    The mod to be archived.

    Callback

    +
    Error Values
    + ++++ + + + + + + + + + + + + + + + + + + +

    ApiError::InsufficientPermission

    The authenticated user does not have permission to archive this mod.This action is restricted to team managers and administrators only.

    GenericError::SDKNotInitialized

    SDK not initialized

    NetworkError

    Couldn’t connect to mod.io servers

    EntityNotFoundError

    Specified mod does not exist or was deleted

    +
    +
    +

    Is Mod Management Busy

    @@ -3882,7 +4110,7 @@

    Is Mod Management Busy

    Checks if the automatic management process is currently installing or removing mods

    -
    Parameters
    +
    Parameters
    @@ -3920,7 +4148,7 @@

    Get Last Validation Error

    If the last request to the mod.io servers returned a validation failure, this function returns extended information describing the fields that failed validation.

    -
    Requirements
    +
    Requirements
    • @@ -3928,7 +4156,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -3966,7 +4194,7 @@

    ForceUninstallModAsync

    Forcibly uninstalls a mod from the system. This is intended for use when a host application requires more room for a mod that the user wants to install, and as such will return an error if the current user is subscribed to the mod. To remove a mod the current user is subscribed to, use UnsubscribeFromModAsync.

    -
    Parameters
    +
    Parameters
    @@ -3987,7 +4215,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -4025,7 +4253,7 @@

    Disable Mod Management

    Disables automatic installation or uninstallation of mods based on the user’s subscriptions. Allows currently processing installation to complete; will cancel any pending operations when called.

    -
    Parameters
    +
    Parameters
    @@ -4825,22 +5053,22 @@

    Variables

    - + - + - + - + @@ -4854,6 +5082,13 @@

    Variables


    +

    ModioUnsigned64

    +
    +

    Trivial Blueprint-compatible wrapper around an unsigned 64-bit integer

    +
    +
    +
    +

    ModioReportParams


    @@ -5017,7 +5252,7 @@

    Set Portal

    Changes the portal for the provided set of initialization options

    -

    Parameters

    +

    Parameters

    int64

    FModioUnsigned64

    TotalDownloadSize

    Total size of the downloaded file

    int64

    FModioUnsigned64

    CurrentlyDownloadedBytes

    Current amount downloaded in bytes

    int64

    FModioUnsigned64

    TotalExtractedSizeOnDisk

    Total size on disk when fully extracted

    int64

    FModioUnsigned64

    CurrentlyExtractedBytes

    Amount of data currently extracted

    @@ -5059,7 +5294,7 @@

    Make Initialize Options

    Make initialization options, should only be used in conjunction with InitializeAsync

    -

    Parameters

    +

    Parameters

    @@ -5105,7 +5340,7 @@

    Make Game Id

    Create a game id from a integer, should only be used in conjunction with InitializeAsync

    -

    Parameters

    +

    Parameters

    @@ -5139,7 +5374,7 @@

    Make Auth Params

    Creates an AuthenticationParams object

    -

    Parameters

    +

    Parameters

    @@ -5185,7 +5420,7 @@

    Make Api Key

    Create a ApiKey id from a string, should only be used in conjunction with InitializeAsync

    -

    Parameters

    +

    Parameters

    @@ -5216,7 +5451,7 @@

    Get Value

    int32 GetValue(FModioErrorCode Error)
    -

    Parameters

    +

    Parameters

    @@ -5251,7 +5486,7 @@

    Get Message

    FString GetMessage(FModioErrorCode Error)
    -

    Parameters

    +

    Parameters

    @@ -5286,7 +5521,7 @@

    List User Subscription Async

    Runs a filter over the user’s subscription list

    -

    Parameters

    +

    Parameters

    @@ -5401,7 +5636,7 @@

    Get Logo Size

    FVector2D GetLogoSize(UTexture* Logo, EModioLogoSize LogoSize)
    -

    Parameters

    +

    Parameters

    @@ -5440,7 +5675,7 @@

    Get Gallery Size

    FVector2D GetGallerySize(UTexture* GalleryImage, EModioGallerySize GallerySize)
    -

    Parameters

    +

    Parameters

    @@ -5479,7 +5714,7 @@

    Get Avatar Size

    FVector2D GetAvatarSize(UTexture* Avatar, EModioAvatarSize AvatarSize)
    -

    Parameters

    +

    Parameters

    @@ -5518,7 +5753,7 @@

    Get Path

    FString GetPath(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -5553,7 +5788,7 @@

    Get Mod State

    EModioModState GetModState(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -5588,7 +5823,7 @@

    Get Mod Profile

    FModioModInfo GetModProfile(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -5623,7 +5858,7 @@

    Get ID

    FModioModID GetID(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -5661,7 +5896,7 @@

    Get Percent (integer64/integer64)

    Dividend/Divisor and return the floating point result with no checks *

    -

    Parameters

    +

    Parameters

    @@ -5696,7 +5931,7 @@

    Is Valid Security Code Format

    bool IsValidSecurityCodeFormat(FString String)
    -

    Parameters

    +

    Parameters

    @@ -5731,7 +5966,7 @@

    Is Valid Email Address Format

    bool IsValidEmailAddressFormat(FString String)
    -

    Parameters

    +

    Parameters

    @@ -5822,7 +6057,7 @@

    ToString (Filesize)

    FText Filesize_ToString(int64 FileSize, int32 MaxDecimals, TEnumAsByte<EFileSizeUnit> Unit)
    -

    Parameters

    +

    Parameters

    @@ -5854,6 +6089,146 @@

    Returns


    +

    ModioUnsigned64 - ModioUnsigned64

    +
    +
    +nd img Subtract +
    +
    +
    +
    +
    FModioUnsigned64 Subtract(FModioUnsigned64 LHS, FModioUnsigned64 RHS)
    +
    +
    +
    +
    +
    +

    ModioUnsigned64 != ModioUnsigned64

    +
    +
    +nd img NotEqualTo +
    +
    +
    +
    +
    bool NotEqualTo(FModioUnsigned64 LHS, FModioUnsigned64 RHS)
    +
    +
    +
    +
    +
    +

    Make from Components

    +
    +
    +nd img MakeFromComponents +
    +
    +
    +
    +
    FModioUnsigned64 MakeFromComponents(int32 High, int32 Low)
    +
    +
    +
    +
    +
    +

    ModioUnsigned64 < ModioUnsigned64

    +
    +
    +nd img LessThan +
    +
    +
    +
    +
    bool LessThan(FModioUnsigned64 LHS, FModioUnsigned64 RHS)
    +
    +
    +
    +
    +
    +

    ModioUnsigned64 > ModioUnsigned64

    +
    +
    +nd img GreaterThan +
    +
    +
    +
    +
    bool GreaterThan(FModioUnsigned64 LHS, FModioUnsigned64 RHS)
    +
    +
    +
    +
    +
    +

    ModioUnsigned64 == ModioUnsigned64

    +
    +
    +nd img EqualTo +
    +
    +
    +
    +
    bool EqualTo(FModioUnsigned64 LHS, FModioUnsigned64 RHS)
    +
    +
    +
    +
    +
    +

    ModioUnsigned64 / float

    +
    +
    +nd img DivideFloat +
    +
    +
    +
    +
    float DivideFloat(FModioUnsigned64 LHS, float RHS)
    +
    +
    +
    +
    +
    +

    ModioUnsigned64 / ModioUnsigned64

    +
    +
    +nd img Divide +
    +
    +
    +
    +
    FModioUnsigned64 Divide(FModioUnsigned64 LHS, FModioUnsigned64 RHS)
    +
    +
    +
    +
    +
    +

    Break to Components

    +
    +
    +nd img BreakToComponents +
    +
    +
    +
    +
    void BreakToComponents(FModioUnsigned64 In, int32 High, int32 Low)
    +
    +
    +
    +
    +
    +

    ModioUnsigned64 + ModioUnsigned64

    +
    +
    +nd img Add +
    +
    +
    +
    +
    FModioUnsigned64 Add(FModioUnsigned64 LHS, FModioUnsigned64 RHS)
    +
    +
    +
    +
    +

    SubmitNewModFileForModFromMemory

    @@ -5868,7 +6243,7 @@

    SubmitNewModFileForModFromMemory

    Queues the upload of a new mod file release for the specified mod, using the submitted parameters. This upload method accepts a a block of memory TArray<uint8> rather than a file path. The upload’s progress can be tracked in the same way as downloads; when completed, a Mod Management Event will be triggered with the result code for the upload.

    -

    Requirements

    +

    Requirements

    • @@ -5879,7 +6254,7 @@

      Requirements

    -

    Parameters

    +

    Parameters

    @@ -5917,7 +6292,7 @@

    LoadModFileToMemory

    Loads an installed mod file into memory.

    -

    Requirements

    +

    Requirements

    • @@ -5928,7 +6303,7 @@

      Requirements

    -

    Parameters

    +

    Parameters

    @@ -6399,11 +6774,64 @@

    Values


    +

    EModioErrorCondition

    +

    Values

    +
    ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    NoError

    NetworkError

    When this condition is true, the error code represents a connection or HTTP error between the client and the mod.io server.

    ConfigurationError

    When this condition is true, the error code indicates the SDK’s configuration is not valid - the game ID or API key are incorrect or the game has been deleted.

    InvalidArgsError

    When this condition is true, the error code indicates the arguments passed to the function have failed validation or were otherwise invalid.

    FilesystemError

    When this condition is true, the error code indicates a permission or IO error when accessing local filesystem data.

    InternalError

    When this condition is true, the error code represents an internal SDK error - please inform mod.io of the error code value.

    EntityNotFoundError

    When this condition is true, the error code indicates that a specified game, mod, media file or mod file was not found.

    UserTermsOfUseError

    When this condition is true, the error code indicates that the user has not yet accepted the mod.io Terms of Use.

    SubmitReportError

    When this condition is true, the error code indicates that a report for the specified content could not be submitted.

    UserNotAuthenticatedError

    When this condition is true, the error code indicates that a user is not authenticated.

    +
    +
    +

    EModioSortDirection

    Enum indicating which direction sorting should be applied

    -

    Values

    +

    Values

    @@ -6427,7 +6855,7 @@

    EModioSortFieldTy

    Enum indicating which field should be used to sort the results

    -

    Values

    +

    Values

    @@ -6458,13 +6886,17 @@

    Values

    + + + +

    DateUpdated

    use date mod was marked live

    DownloadsTotal

    use date mod was last updated


    EModioImageState

    -

    Values

    +

    Values

    @@ -6496,7 +6928,7 @@

    EModioModState

    Enum representing the current state of a mod

    -

    Values

    +

    Values

    @@ -6533,7 +6965,7 @@

    Values

    EModioRating

    -

    Values

    +

    Values

    @@ -6558,7 +6990,7 @@

    Values

    EModioReportType

    -

    Values

    +

    Values

    @@ -6603,7 +7035,7 @@

    Values

    EFileSizeUnit

    -

    Values

    +

    Values

    @@ -6638,7 +7070,7 @@

    Values

    diff --git a/Doc/getting-started.adoc b/Doc/getting-started.adoc index 4894f1f8..0bc254df 100644 --- a/Doc/getting-started.adoc +++ b/Doc/getting-started.adoc @@ -73,7 +73,7 @@ NOTE: The plugin event loop, any internal event handlers, and all callbacks you ==== Non-blocking, asynchronous interface -The plugin communicates with the mod.io servers, the filesystem on the device you're using, and platform-provided services for authentication. All of these may not return results immediately, so many functions provided by the ModioSubsystem are non-blocking and asynchronous. +The plugin communicates with the mod.io servers, the filesystem on the device you're using, and platform-provided services for authentication. All of these may not return results immediately, so many functions provided by the ModioSubsystem are non-blocking and asynchronous. For example, the initialization function returns immediately. However, your game should consider the ModioSybsystem as initialized only when the init callback executes. NOTE: All async methods in the public API end with the suffix `Async`. @@ -110,9 +110,8 @@ The plugin stores mods in a game-specific directory in the following directory b [stripes=odd,frame=none,cols="1,^1,^1"] |=== -|Windows | Linux | OSX - -|`${FolderID_Public}/mod.io` | TBD |TBD +| Windows | Linux | OSX +|`${FolderID_Public}/mod.io` | `${USER_HOME}/mod.io` | `${USER_HOME}/Library/Application Support/mod.io` |=== However, this value can be overridden in one of two ways: @@ -156,6 +155,7 @@ image::img/initasync_getoptions.png[] .Notes * The error-handling in this sample has been omitted. See <> for more information on error handling. +* To fully initialize the SDK, you must receive confirmation from the callback. Consider that most functions return after invocation, nonetheless, their effects are only visible in their callback function ==== @@ -348,6 +348,45 @@ Here's what steps 1 and 2 might look like in Blueprint: image::img/authenticate_user_external.png[] +Note that the SDK will automatically URL encode parameters (such as the auth token) when making the request. + +===== Steam Authentication Example + +In order to use the Steam authentication functionality, you must add your games https://partner.steamgames.com/apps/sdkauth[Encrypted App Ticket Key] from Steamworks. On your games profile on mod.io, go to Edit > Options and add the key. You can then call <> and provide the users Encrypted App Ticket as the Auth Token. Note that the Auth Token must be Base64 encoded when passed + +Below is a sample Blueprint method that will get the users current Encrypted App Ticket that you can use in your Authentication request. Add this to a BlueprintLibrary in your games codebase. + +.C++ Example +[%collapsible] +==== +[source] +---- +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnGetTicket, int32, LocalUserNum, FString, TokenData); +UFUNCTION(BlueprintCallable) +static void GetSteamAuthTicket(int32 LocalUserNum, FOnGetTicket Callback) +{ + //Get the steam subsystem + FOnlineSubsystemSteam* SteamSubsystem = static_cast(IOnlineSubsystem::Get()); + //Add a handler to the subsystem for when the ticket has been retrieved + SteamSubsystem->GetEncryptedAppTicketInterface()->OnEncryptedAppTicketResultDelegate.AddLambda( + [LocalUserNum, OnComplete = Callback](bool bEncryptedDataAvailable, int32 ResultCode) { + + TArray TokenData; + if (bEncryptedDataAvailable) + { + //If the ticket was retrieved successfully, get its data + SteamSubsystem->GetEncryptedAppTicketInterface()->GetEncryptedAppTicket(TokenData); + } + //Call the user callback with the base64-encoded ticket, ready for submission via AuthenticateUserExternalAsync + OnComplete.ExecuteIfBound(LocalUserNum, FBase64::Encode(TokenData)); + }); + //Begin the actual async request for the ticket, which will invoke the above lambda when it completes + SteamSubsystem->GetEncryptedAppTicketInterface()->RequestEncryptedAppTicket(nullptr, 0); +} +---- +Note that if you are on 4.27 or above, Epic provides a helper method in OnlineIdentityInterface::GetLinkedAccountAuthToken that will get the current account's auth token without having to take a direct dependency on FOnlineSubsystemSteam. Ensure that the token is Base64 encoded when being passed to <>. +==== + ==== Token Lifetime & Re-Authentication By default, tokens issued via email token exchange have a lifetime of 1 year. You can verify that a user has been successfully authenticated by using <>. A success and non-null result indicates that a user has been authenticated. @@ -713,3 +752,85 @@ image::img/get_last_validation_error.png[] ''' +==== Submitting a new mod + +In order to submit a mod, you have to first create a mod handle using <> and use that handle when calling <> + +.Blueprint Example +[%collapsible] +==== + +image::img/submit_new_mod.png[] + +==== + +.C++ Example +[%collapsible] +==== + +[source] +---- + +void UModioManager::SubmitNewMod() +{ + if (GEngine->GetEngineSubsystem()) + { + FModioModCreationHandle Handle = GEngine->GetEngineSubsystem()->GetModCreationHandle(); + + FModioCreateModParams Params; + Params.Name = TEXT("My Awesome Mod"); + Params.Description = TEXT("This is an amazing mod"); + Params.PathToLogoFile = TEXT("C:\\temp\\image.png"); + + GEngine->GetEngineSubsystem()->SubmitNewModAsync(Handle, Params, FOnSubmitNewModDelegateFast::CreateUObject(this, &UModioManager::OnSubmitNewModCallback)); + } +} + +void UModioManager::OnSubmitNewModCallback(FModioErrorCode ErrorCode, TOptional ModId) +{ + if (ErrorCode == false) + { + // Mod was submitted successfully. Use ModId to submit some files to it. + } +} + +---- + +==== + + +==== Submitting a file for a mod + +Once you have successfully submitted a mod, you can then submit a file for that mod using <>. When you submit a file, you pass a <> containing the directory of the files that you want to submit. The plugin will then compress this folder into a zip file and upload it as the active version of the mod. Note that there is no callback for this method; you'll get notified of the completed upload by the Mod Management callbacks. + +.Blueprint Example +[%collapsible] +==== + +As an example, after the callback for submitting a mod has completed, you can get the Mod Id to use for file submission. + +image::img/submit_new_mod_file.png[] + +==== + +.C++ Example +[%collapsible] +==== + +[source] +---- + +void UModioManager::SubmitNewModFile(FModioModID ModId) +{ + if (GEngine->GetEngineSubsystem()) + { + FModioCreateModFileParams Params; + Params.PathToModRootDirectory = TEXT("C:\\temp\\mod_folder"); + + GEngine->GetEngineSubsystem()->SubmitNewModFileForMod(ModId, Params); + } +} + +---- + +==== diff --git a/Doc/img/nd_img_Add.png b/Doc/img/nd_img_Add.png new file mode 100644 index 00000000..08114dd0 Binary files /dev/null and b/Doc/img/nd_img_Add.png differ diff --git a/Doc/img/nd_img_BreakToComponents.png b/Doc/img/nd_img_BreakToComponents.png new file mode 100644 index 00000000..1eeb3d6a Binary files /dev/null and b/Doc/img/nd_img_BreakToComponents.png differ diff --git a/Doc/img/nd_img_Divide.png b/Doc/img/nd_img_Divide.png new file mode 100644 index 00000000..4f5ca66a Binary files /dev/null and b/Doc/img/nd_img_Divide.png differ diff --git a/Doc/img/nd_img_EqualTo.png b/Doc/img/nd_img_EqualTo.png new file mode 100644 index 00000000..473f6f15 Binary files /dev/null and b/Doc/img/nd_img_EqualTo.png differ diff --git a/Doc/img/nd_img_GreaterThan.png b/Doc/img/nd_img_GreaterThan.png new file mode 100644 index 00000000..ffffcbb7 Binary files /dev/null and b/Doc/img/nd_img_GreaterThan.png differ diff --git a/Doc/img/nd_img_K2_ArchiveModAsync.png b/Doc/img/nd_img_K2_ArchiveModAsync.png new file mode 100644 index 00000000..c588e88a Binary files /dev/null and b/Doc/img/nd_img_K2_ArchiveModAsync.png differ diff --git a/Doc/img/nd_img_K2_EnableModManagement.png b/Doc/img/nd_img_K2_EnableModManagement.png index 04e92d52..bc03eedf 100644 Binary files a/Doc/img/nd_img_K2_EnableModManagement.png and b/Doc/img/nd_img_K2_EnableModManagement.png differ diff --git a/Doc/img/nd_img_LessThan.png b/Doc/img/nd_img_LessThan.png new file mode 100644 index 00000000..d29da95d Binary files /dev/null and b/Doc/img/nd_img_LessThan.png differ diff --git a/Doc/img/nd_img_MakeFromComponents.png b/Doc/img/nd_img_MakeFromComponents.png new file mode 100644 index 00000000..f5fffb67 Binary files /dev/null and b/Doc/img/nd_img_MakeFromComponents.png differ diff --git a/Doc/img/nd_img_NotEqualTo.png b/Doc/img/nd_img_NotEqualTo.png new file mode 100644 index 00000000..8581f2b7 Binary files /dev/null and b/Doc/img/nd_img_NotEqualTo.png differ diff --git a/Doc/img/nd_img_Subtract.png b/Doc/img/nd_img_Subtract.png new file mode 100644 index 00000000..c210b80f Binary files /dev/null and b/Doc/img/nd_img_Subtract.png differ diff --git a/README.adoc b/README.adoc index 2f778064..5df4a362 100644 --- a/README.adoc +++ b/README.adoc @@ -65,7 +65,7 @@ The settings have the following parameters: == Further reading -To begin using the Plugin, either from Blueprint or from C++, please read our link:doc/getting-started.adoc[Getting Started Guide] for a detailed explanation of initialization and usage. +To begin using the Plugin, either from Blueprint or from C++, please read our link:Doc/getting-started.adoc[Getting Started Guide] for a detailed explanation of initialization and usage. * link:Doc/getting-started.adoc#plugin-quick-start-initialization-and-teardown[SDK initialization and event loop] * link:Doc/getting-started.adoc#plugin-quick-start-user-authentication[Authentication] diff --git a/Source/Modio/Modio.Build.cs b/Source/Modio/Modio.Build.cs index 04b05f9d..42e186a0 100644 --- a/Source/Modio/Modio.Build.cs +++ b/Source/Modio/Modio.Build.cs @@ -217,7 +217,7 @@ private void AddCommonHeaderPaths(string GeneratedHeaderPath) PublicIncludePaths.AddRange(new string[] { Path.Combine(GeneratedHeaderPath, "Public") }); - + ConditionalAddModuleDirectory(new DirectoryReference(Path.Combine(GeneratedHeaderPath, "Public"))); // Add common private includes from the Native SDK PrivateIncludePaths.AddRange(new string[] { diff --git a/Source/Modio/Private/Internal/Convert/CreateModFileParams.h b/Source/Modio/Private/Internal/Convert/CreateModFileParams.h index 951004b2..cd888000 100644 --- a/Source/Modio/Private/Internal/Convert/CreateModFileParams.h +++ b/Source/Modio/Private/Internal/Convert/CreateModFileParams.h @@ -25,5 +25,10 @@ FORCEINLINE Modio::CreateModFileParams ToModio(const FModioCreateModFileParams& Out.Changelog = ToModioOptional(In.Changelog); Out.bSetAsActive = ToModioOptional(In.bSetAsActiveRelease); Out.MetadataBlob = ToModioOptional(In.MetadataBlob); + if (In.ModfilePlatforms.IsSet()) + { + Out.Platforms = ToModio(In.ModfilePlatforms.GetValue()); + } + return Out; } \ No newline at end of file diff --git a/Source/Modio/Private/Internal/Convert/FilterParams.h b/Source/Modio/Private/Internal/Convert/FilterParams.h index 9d90157a..01b8d0f7 100644 --- a/Source/Modio/Private/Internal/Convert/FilterParams.h +++ b/Source/Modio/Private/Internal/Convert/FilterParams.h @@ -44,6 +44,8 @@ FORCEINLINE Modio::FilterParams::SortFieldType ToModio(EModioSortFieldType Envir return Modio::FilterParams::SortFieldType::DateMarkedLive; case EModioSortFieldType::DateUpdated: return Modio::FilterParams::SortFieldType::DateUpdated; + case EModioSortFieldType::DownloadsTotal: + return Modio::FilterParams::SortFieldType::DownloadsTotal; } return Modio::FilterParams::SortFieldType::ID; diff --git a/Source/Modio/Private/Internal/Convert/ModCollectionEntry.h b/Source/Modio/Private/Internal/Convert/ModCollectionEntry.h index 1347f6ef..505376c3 100644 --- a/Source/Modio/Private/Internal/Convert/ModCollectionEntry.h +++ b/Source/Modio/Private/Internal/Convert/ModCollectionEntry.h @@ -47,6 +47,15 @@ FModioModCollectionEntry ToUnreal(const Modio::ModCollectionEntry& In) Out.ModID = ToUnreal(In.GetID()); Out.ModPath = ToUnreal(In.GetPath()); Out.ModProfile = ToUnreal(In.GetModProfile()); + Out.SizeOnDisk = FModioUnsigned64(0); + if (In.GetSizeOnDisk()) + { + if (*In.GetSizeOnDisk()) + { + Out.SizeOnDisk = ToUnreal(*In.GetSizeOnDisk()); + } + } + return Out; } diff --git a/Source/Modio/Private/Internal/Convert/ModInfo.h b/Source/Modio/Private/Internal/Convert/ModInfo.h index 4c9556b2..53245ff8 100644 --- a/Source/Modio/Private/Internal/Convert/ModInfo.h +++ b/Source/Modio/Private/Internal/Convert/ModInfo.h @@ -47,6 +47,8 @@ FORCEINLINE FModioModInfo ToUnreal(const Modio::ModInfo& In) Out.ProfileDateUpdated = ToUnrealDateTime(In.ProfileDateUpdated); Out.ProfileDateLive = ToUnrealDateTime(In.ProfileDateLive); Out.ProfileMaturityOption = ToUnreal(In.ProfileMaturityOption); + Out.bVisible = In.bVisible; + Out.MetadataBlob = FString(In.MetadataBlob.c_str()); // Converting verbatim rather than via TCHAR as ToUnreal does if (In.FileInfo.has_value()) diff --git a/Source/Modio/Private/Internal/Convert/ModProgressInfo.h b/Source/Modio/Private/Internal/Convert/ModProgressInfo.h index 3edcbfaa..17534119 100644 --- a/Source/Modio/Private/Internal/Convert/ModProgressInfo.h +++ b/Source/Modio/Private/Internal/Convert/ModProgressInfo.h @@ -1,11 +1,11 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io UE4 Plugin. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #pragma once @@ -18,6 +18,7 @@ FORCEINLINE FModioModProgressInfo ToUnreal(const Modio::ModProgressInfo& In) FModioModProgressInfo Out; Out.TotalDownloadSize = ToUnreal(In.TotalDownloadSize); Out.CurrentlyDownloadedBytes = ToUnreal(In.CurrentlyDownloadedBytes); + Out.CurrentlyExtractedBytes = ToUnreal(In.CurrentlyExtractedBytes); Out.TotalExtractedSizeOnDisk = ToUnreal(In.TotalExtractedSizeOnDisk); Out.ID = ToUnreal(In.ID); return Out; diff --git a/Source/Modio/Private/Internal/ModioConvert.cpp b/Source/Modio/Private/Internal/ModioConvert.cpp index d223cab8..4ea11b70 100644 --- a/Source/Modio/Private/Internal/ModioConvert.cpp +++ b/Source/Modio/Private/Internal/ModioConvert.cpp @@ -1,4 +1,5 @@ #include "Internal/ModioConvert.h" +#include "Types/ModioUnsigned64.h" std::string ToModio(const FString& String) { @@ -47,19 +48,21 @@ FString ToUnreal(const std::string& String) return UTF8_TO_TCHAR(String.c_str()); } - - FString ToUnreal(const Modio::filesystem::path& Path) { return UTF8_TO_TCHAR(Path.generic_u8string().c_str()); } +FModioUnsigned64 ToUnreal(const Modio::FileSize& In) +{ + return FModioUnsigned64(In); +} + FDateTime ToUnrealDateTime(std::int64_t UnixTimestamp) { return FDateTime::FromUnixTimestamp(UnixTimestamp); } - Modio::ApiKey ToModio(const FModioApiKey& In) { return Modio::ApiKey(TCHAR_TO_UTF8(*In.ToString())); @@ -93,7 +96,6 @@ Modio::UserID ToModio(const FModioUserID& In) return Modio::UserID(In.UserID); } - Modio::LogLevel ToModio(EModioLogLevel UnrealLogLevel) { switch (UnrealLogLevel) @@ -174,6 +176,37 @@ Modio::Environment ToModio(EModioEnvironment Environment) return Modio::Environment::Test; } +Modio::ModfilePlatform ToModio(EModioModfilePlatform Platform) +{ + switch (Platform) + { + case EModioModfilePlatform::Android: + return Modio::ModfilePlatform::Android; + case EModioModfilePlatform::iOS: + return Modio::ModfilePlatform::iOS; + case EModioModfilePlatform::Linux: + return Modio::ModfilePlatform::Linux; + case EModioModfilePlatform::Mac: + return Modio::ModfilePlatform::Mac; + case EModioModfilePlatform::Oculus: + return Modio::ModfilePlatform::Oculus; + case EModioModfilePlatform::PS4: + return Modio::ModfilePlatform::PS4; + case EModioModfilePlatform::PS5: + return Modio::ModfilePlatform::PS5; + case EModioModfilePlatform::Switch: + return Modio::ModfilePlatform::Switch; + case EModioModfilePlatform::Windows: + return Modio::ModfilePlatform::Windows; + case EModioModfilePlatform::XboxOne: + return Modio::ModfilePlatform::XboxOne; + case EModioModfilePlatform::XboxSeriesX: + return Modio::ModfilePlatform::XboxSeriesX; + } + checkf(false, TEXT("Unhandled value in ToModio(EModioModfilePlatform Platform)")); + return Modio::ModfilePlatform::Windows; +} + Modio::Portal ToModio(EModioPortal Portal) { switch (Portal) diff --git a/Source/Modio/Private/Internal/ModioConvert.h b/Source/Modio/Private/Internal/ModioConvert.h index 559c8185..28084188 100644 --- a/Source/Modio/Private/Internal/ModioConvert.h +++ b/Source/Modio/Private/Internal/ModioConvert.h @@ -21,8 +21,6 @@ #include #include - - int64 ToUnreal(std::int64_t Value); double ToUnreal(double Value); bool ToUnreal(bool Value); @@ -38,6 +36,7 @@ struct FModioMetadata ToUnreal(const Modio::Metadata& In); struct FModioModTag ToUnreal(const Modio::ModTag& In); struct FModioModInfo ToUnreal(const Modio::ModInfo& In); struct FModioModDependency ToUnreal(const Modio::ModDependency& In); +struct FModioUnsigned64 ToUnreal(const Modio::FileSize& In); std::string ToModio(const FString& String); std::vector ToModio(const TArray& StringArray); @@ -54,6 +53,7 @@ Modio::AvatarSize ToModio(EModioAvatarSize AvatarSize); Modio::GallerySize ToModio(EModioGallerySize GallerySize); Modio::LogoSize ToModio(EModioLogoSize LogoSize); Modio::Environment ToModio(EModioEnvironment Environment); +Modio::ModfilePlatform ToModio(EModioModfilePlatform Platform); Modio::Portal ToModio(EModioPortal Portal); Modio::Language ToModio(EModioLanguage Language); @@ -70,7 +70,6 @@ typename TEnableIf>::Va return static_cast(Flags.RawValue()); } - template TArray ToUnreal(std::vector&& OriginalArray) { @@ -111,5 +110,4 @@ std::vector ToModio(const TArray& OriginalArray) return Out; } - #pragma endregion diff --git a/Source/Modio/Private/Libraries/ModioCommonTypesLibrary.cpp b/Source/Modio/Private/Libraries/ModioCommonTypesLibrary.cpp index 214f338f..3a424e6e 100644 --- a/Source/Modio/Private/Libraries/ModioCommonTypesLibrary.cpp +++ b/Source/Modio/Private/Libraries/ModioCommonTypesLibrary.cpp @@ -1,11 +1,11 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io UE4 Plugin. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #include "Libraries/ModioCommonTypesLibrary.h" @@ -21,11 +21,10 @@ FString UModioCommonTypesLibrary::Conv_GameIDToString(FModioGameID GameId) return GameId.ToString(); } -FModioAuthenticationParams UModioCommonTypesLibrary::MakeAuthParams(const FString AuthToken, - const FString EmailAddress, - const bool bHasAcceptedTOS) +FModioAuthenticationParams UModioCommonTypesLibrary::MakeAuthParams(const FString AuthToken, const FString EmailAddress, + const bool bHasAcceptedTOS) { - return FModioAuthenticationParams { AuthToken, EmailAddress, bHasAcceptedTOS }; + return FModioAuthenticationParams {AuthToken, EmailAddress, bHasAcceptedTOS}; } FModioApiKey UModioCommonTypesLibrary::MakeApiKey(const FString ApiKey) @@ -73,7 +72,9 @@ FString UModioCommonTypesLibrary::Conv_UserIDToString(FModioUserID UserID) return UserID.ToString(); } -FModioInitializeOptions UModioCommonTypesLibrary::MakeInitializeOptions(int64 GameId, const FString& APIKey, EModioEnvironment GameEnvironment, EModioPortal PortalInUse) +FModioInitializeOptions UModioCommonTypesLibrary::MakeInitializeOptions(int64 GameId, const FString& APIKey, + EModioEnvironment GameEnvironment, + EModioPortal PortalInUse) { FModioInitializeOptions Options; Options.GameId = FModioGameID(GameId); @@ -99,3 +100,12 @@ FModioInitializeOptions UModioCommonTypesLibrary::SetSessionIdentifier(const FMo return DuplicateOptions; } +bool UModioCommonTypesLibrary::EqualTo(const FModioModID& A, const FModioModID& B) +{ + return A == B; +} + +bool UModioCommonTypesLibrary::NotEqualTo(const FModioModID& A, const FModioModID& B) +{ + return A != B; +} \ No newline at end of file diff --git a/Source/Modio/Private/ModioSubsystem.cpp b/Source/Modio/Private/ModioSubsystem.cpp index 2874ad5e..ba1f35b2 100644 --- a/Source/Modio/Private/ModioSubsystem.cpp +++ b/Source/Modio/Private/ModioSubsystem.cpp @@ -47,9 +47,10 @@ void UModioSubsystem::Initialize(FSubsystemCollectionBase& Collection) { Super::Initialize(Collection); - if (const UModioSettings* Settings = GetDefault()) + if (const UModioSettings* Settings = GetMutableDefault()) { SetLogLevel(Settings->LogLevel); + UE_LOG(LogModio, Display, TEXT("Setting log level to %d"), (int32) Settings->LogLevel); } ImageCache = MakeUnique(); } @@ -118,9 +119,9 @@ void UModioSubsystem::FetchExternalUpdatesAsync(FOnErrorOnlyDelegateFast OnFetch }); } -void UModioSubsystem::EnableModManagement(FOnModManagementDelegateFast Callback) +FModioErrorCode UModioSubsystem::EnableModManagement(FOnModManagementDelegateFast Callback) { - Modio::EnableModManagement([this, Callback](Modio::ModManagementEvent Event) { + return Modio::EnableModManagement([this, Callback](Modio::ModManagementEvent Event) { // @todo: For some smarter caching, look at the event and see if we should invalidate the cache InvalidateUserInstallationCache(); Callback.ExecuteIfBound(ToUnreal(Event)); @@ -157,9 +158,9 @@ void UModioSubsystem::K2_FetchExternalUpdatesAsync(FOnErrorOnlyDelegate OnFetchD FOnErrorOnlyDelegateFast::CreateLambda([OnFetchDone](FModioErrorCode ec) { OnFetchDone.ExecuteIfBound(ec); })); } -void UModioSubsystem::K2_EnableModManagement(FOnModManagementDelegate Callback) +FModioErrorCode UModioSubsystem::K2_EnableModManagement(FOnModManagementDelegate Callback) { - EnableModManagement(FOnModManagementDelegateFast::CreateLambda( + return EnableModManagement(FOnModManagementDelegateFast::CreateLambda( [Callback](FModioModManagementEvent Event) { Callback.ExecuteIfBound(Event); })); } @@ -549,18 +550,17 @@ void UModioSubsystem::K2_ReportContentAsync(FModioReportParams Report, FOnErrorO [Callback](FModioErrorCode ec) { Callback.ExecuteIfBound(ec); })); } - TArray ToUnreal(const std::vector& OriginalArray) { - TArray Result; + TArray Result; - Result.Reserve(OriginalArray.size()); - for (const auto& It : OriginalArray) - { - Result.Emplace(ToUnreal(It)); - } + Result.Reserve(OriginalArray.size()); + for (const auto& It : OriginalArray) + { + Result.Emplace(ToUnreal(It)); + } - return Result; + return Result; } void UModioSubsystem::GetModDependenciesAsync(FModioModID ModID, FOnGetModDependenciesDelegateFast Callback) @@ -631,6 +631,17 @@ void UModioSubsystem::K2_ArchiveModAsync(FModioModID Mod, FOnErrorOnlyDelegate C Mod, FOnErrorOnlyDelegateFast::CreateLambda([Callback](FModioErrorCode ec) { Callback.ExecuteIfBound(ec); })); } +void UModioSubsystem::VerifyUserAuthenticationAsync(FOnErrorOnlyDelegateFast Callback) +{ + Modio::VerifyUserAuthenticationAsync([Callback](Modio::ErrorCode ec) { Callback.ExecuteIfBound(ToUnreal(ec)); }); +} + +void UModioSubsystem::K2_VerifyUserAuthenticationAsync(FOnErrorOnlyDelegate Callback) +{ + VerifyUserAuthenticationAsync(FOnErrorOnlyDelegateFast::CreateLambda([Callback](FModioErrorCode ec){ + Callback.ExecuteIfBound(ec);})); +} + /// File scope implementations #pragma region Implementation diff --git a/Source/Modio/Private/Tests/ToUnreal.cpp b/Source/Modio/Private/Tests/ToUnreal.cpp index a304496d..a3633973 100644 --- a/Source/Modio/Private/Tests/ToUnreal.cpp +++ b/Source/Modio/Private/Tests/ToUnreal.cpp @@ -1,16 +1,18 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io UE4 Plugin. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ +#include "Internal/Convert/ModStats.h" +#include "Internal/ModioConvert.h" #include "Libraries/ModioSDKLibrary.h" #include "Misc/AutomationTest.h" -#include "Internal/Convert/ModStats.h" +#include "Types/ModioUnsigned64.h" #if WITH_DEV_AUTOMATION_TESTS @@ -32,7 +34,22 @@ bool FModioConvertDataToUnrealFormatTest::RunTest(const FString& Parameters) TestEqual("RatingPercentagePositive", (int32)OutObj.RatingPercentagePositive, (int32)InObj.RatingPercentagePositive); TestEqual("RatingWeightedAggregate", FMath::IsNearlyEqual((float) OutObj.RatingWeightedAggregate, (float) InObj.RatingWeightedAggregate), true); - TestEqual(TEXT("RatingDisplayText"), OutObj.RatingDisplayText.Equals(FString(InObj.RatingDisplayText.c_str())), true); + TestEqual(TEXT("RatingDisplayText"), OutObj.RatingDisplayText.Equals(FString(InObj.RatingDisplayText.c_str())), + true); + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64ConversionTest, "Modio.DataConversion.NativeToUnreal.ModioUnsigned64", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64ConversionTest::RunTest(const FString& Parameters) +{ + uint64 TestValue = 0xF00DF00DF00DF00D; + Modio::FileSize InFileSize = Modio::FileSize(TestValue); + FModioUnsigned64 OutValue = ToUnreal(InFileSize); + TestEqual(TEXT("Underlying"), TestValue, OutValue.Underlying); return true; } diff --git a/Source/Modio/Private/Types/ModioImage.cpp b/Source/Modio/Private/Types/ModioImage.cpp index 0ef59acb..92a56cd6 100644 --- a/Source/Modio/Private/Types/ModioImage.cpp +++ b/Source/Modio/Private/Types/ModioImage.cpp @@ -1,11 +1,11 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io UE4 Plugin. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #include "Types/ModioImageWrapper.h" @@ -15,15 +15,14 @@ #include "Engine/Texture2DDynamic.h" #include "IImageWrapper.h" #include "IImageWrapperModule.h" +#include "Internal/ModioConvert.h" #include "Misc/EngineVersionComparison.h" #include "Misc/FileHelper.h" -#include "Internal/ModioConvert.h" #include "ModioImageCache.h" #include "ModioSubsystem.h" #include "Modules/ModuleManager.h" #include "RenderingThread.h" - #if !UE_SERVER static TOptional> GetImageData(TSharedPtr ImageWrapper, ERGBFormat InFormat); static ERGBFormat GetDesiredErgbFormat(); @@ -43,7 +42,8 @@ class UTexture2DDynamic* FModioImageWrapper::GetTexture() const return Texture; } -TOptional FModioImageWrapper::LoadTextureDataFromDisk(const FString& ImagePath) +TOptional FModioImageWrapper::LoadTextureDataFromDisk( + const FString& ImagePath) { #if !UE_SERVER IImageWrapperModule& ImageWrapperModule = diff --git a/Source/Modio/Private/Types/ModioModCollectionEntryUImpl.cpp b/Source/Modio/Private/Types/ModioModCollectionEntryUImpl.cpp index dd345f20..cc16b500 100644 --- a/Source/Modio/Private/Types/ModioModCollectionEntryUImpl.cpp +++ b/Source/Modio/Private/Types/ModioModCollectionEntryUImpl.cpp @@ -37,3 +37,8 @@ const FString FModioModCollectionEntry::GetPath() const return {}; } } + +FModioUnsigned64 FModioModCollectionEntry::GetSizeOnDisk() const +{ + return FModioUnsigned64(SizeOnDisk); +} \ No newline at end of file diff --git a/Source/Modio/Private/Types/ModioReportParamsUImpl.cpp b/Source/Modio/Private/Types/ModioReportParamsUImpl.cpp index f10a0b3a..344ca6b5 100644 --- a/Source/Modio/Private/Types/ModioReportParamsUImpl.cpp +++ b/Source/Modio/Private/Types/ModioReportParamsUImpl.cpp @@ -32,6 +32,11 @@ FModioReportParams::FModioReportParams(FModioModID Mod, EModioReportType Type, F ReporterContact) {} +FModioReportParams::FModioReportParams(FModioModID Mod, EModioReportType Type) : +FModioReportParams(ToModio(Mod), ResourceType::Mod, Type, FString(), FString(), FString()) +{} + + FModioReportParams::FModioReportParams(int64 ResourceID, ResourceType ReportedResourceType, EModioReportType Type, FString ReportDescription, TOptional ReporterName, TOptional ReporterContact) diff --git a/Source/Modio/Public/Libraries/ModioCommonTypesLibrary.h b/Source/Modio/Public/Libraries/ModioCommonTypesLibrary.h index 21367a92..d674301c 100644 --- a/Source/Modio/Public/Libraries/ModioCommonTypesLibrary.h +++ b/Source/Modio/Public/Libraries/ModioCommonTypesLibrary.h @@ -1,23 +1,22 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io UE4 Plugin. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #pragma once #include "Kismet/BlueprintFunctionLibrary.h" +#include "Types/ModioAuthenticationParams.h" #include "Types/ModioCommonTypes.h" #include "Types/ModioInitializeOptions.h" -#include "Types/ModioAuthenticationParams.h" #include "ModioCommonTypesLibrary.generated.h" - UCLASS() class MODIO_API UModioCommonTypesLibrary : public UBlueprintFunctionLibrary { @@ -41,14 +40,15 @@ class MODIO_API UModioCommonTypesLibrary : public UBlueprintFunctionLibrary static FString Conv_GameIDToString(FModioGameID GameId); /** - * @brief Creates an AuthenticationParams object + * @brief Creates an AuthenticationParams object * @param AuthToken - Authentication provider-supplied OAuth token * @param EmailAddress - User email address, can be left blank * @param bHasAcceptedTOS - Has the user been shown the TOS and accepted the TOS? * @return The constructed FModioAuthenticationParams object for use with <> */ UFUNCTION(BlueprintPure, category = "mod.io|Utilities", meta = (NativeMakeFunc)) - static FModioAuthenticationParams MakeAuthParams(const FString AuthToken, const FString EmailAddress, const bool bHasAcceptedTOS); + static FModioAuthenticationParams MakeAuthParams(const FString AuthToken, const FString EmailAddress, + const bool bHasAcceptedTOS); /** * @brief Create a ApiKey id from a string, should only be used in conjunction with InitializeAsync @@ -57,7 +57,6 @@ class MODIO_API UModioCommonTypesLibrary : public UBlueprintFunctionLibrary UFUNCTION(BlueprintPure, category = "mod.io|Utilities", meta = (NativeMakeFunc)) static FModioApiKey MakeApiKey(const FString ApiKey); - /** * @brief Converts a ApiKey string so you can debug output it * @param ApiKey Input Api Key @@ -123,7 +122,7 @@ class MODIO_API UModioCommonTypesLibrary : public UBlueprintFunctionLibrary * @return FModioEmailAddress object */ UFUNCTION(BlueprintPure, - meta = (DisplayName = "ToEmailAdress (String)", CompactNodeTitle = "->", BlueprintAutocast), + meta = (DisplayName = "ToEmailAddress (String)", CompactNodeTitle = "->", BlueprintAutocast), Category = "mod.io|Utilities") static FModioEmailAddress Conv_StringToEmailAddress(const FString& Email); @@ -140,11 +139,14 @@ class MODIO_API UModioCommonTypesLibrary : public UBlueprintFunctionLibrary /** * @brief Make initialization options, should only be used in conjunction with InitializeAsync * @param GameId - a positive integer that maps to your game - * @param APIKey - APIKey available at https://.test.mod.io/edit/api or https://.mod.io/edit/api + * @param APIKey - APIKey available at https://.test.mod.io/edit/api or + * https://.mod.io/edit/api * @param GameEnvironment - If your environment is setup on test or production */ UFUNCTION(BlueprintPure, category = "mod.io|Utilities", meta = (NativeMakeFunc)) - static FModioInitializeOptions MakeInitializeOptions(int64 GameId, const FString& APIKey, EModioEnvironment GameEnvironment, EModioPortal PortalInUse = EModioPortal::None); + static FModioInitializeOptions MakeInitializeOptions(int64 GameId, const FString& APIKey, + EModioEnvironment GameEnvironment, + EModioPortal PortalInUse = EModioPortal::None); /** * @brief Changes the portal for the provided set of initialization options @@ -156,5 +158,20 @@ class MODIO_API UModioCommonTypesLibrary : public UBlueprintFunctionLibrary static FModioInitializeOptions SetPortal(const FModioInitializeOptions& Options, EModioPortal PortalToUse); UFUNCTION(BlueprintPure, Category = "mod.io|Utilities") - static FModioInitializeOptions SetSessionIdentifier(const FModioInitializeOptions& Options, const FString& SessionIdentifier); + static FModioInitializeOptions SetSessionIdentifier(const FModioInitializeOptions& Options, + const FString& SessionIdentifier); + + /** + * @brief Compares two ModioModIDs, returning true if equal + */ + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Utilities", + meta = (CompactNodeTitle = "==", Keywords = "== equal", DisplayName = "ModioModID == ModioModID")) + static bool EqualTo(const FModioModID& A, const FModioModID& B); + + /** + * @brief Compares two ModioModIDs, returning true if not equal + */ + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Utilities", + meta = (CompactNodeTitle = "!=", Keywords = "!= not equal", DisplayName = "ModioModID != ModioModID")) + static bool NotEqualTo(const FModioModID& A, const FModioModID& B); }; diff --git a/Source/Modio/Public/Libraries/ModioErrorConditionLibrary.h b/Source/Modio/Public/Libraries/ModioErrorConditionLibrary.h index 81a7ecbe..cc081ddd 100644 --- a/Source/Modio/Public/Libraries/ModioErrorConditionLibrary.h +++ b/Source/Modio/Public/Libraries/ModioErrorConditionLibrary.h @@ -33,6 +33,6 @@ class MODIO_API UModioErrorConditionLibrary : public UBlueprintFunctionLibrary // reported here: // https://forums.unrealengine.com/t/ustruct-type-must-be-a-uclass-ustruct-or-uenum/358937 // Because of that, the line below was commented. - // UFUNCTION(BlueprintCallable, Category = "mod.io|Error Handling") + UFUNCTION(BlueprintCallable, Category = "mod.io|Error Handling") static bool ErrorCodeMatches(FModioErrorCode ErrorCode, EModioErrorCondition Condition); }; \ No newline at end of file diff --git a/Source/Modio/Public/Libraries/ModioSDKLibrary.h b/Source/Modio/Public/Libraries/ModioSDKLibrary.h index 28e3c711..db71e026 100644 --- a/Source/Modio/Public/Libraries/ModioSDKLibrary.h +++ b/Source/Modio/Public/Libraries/ModioSDKLibrary.h @@ -20,7 +20,7 @@ UENUM(BlueprintType) enum EFileSizeUnit { - Largest = 0, // Will take the largest one that becomes a number larger than 1 (i.e, 1300mb becomes 1.23MB) + Largest = 0, // Will take the largest one that becomes a number larger than 1 (i.e, 1300mb becomes 1.3gb) B = 1, KB = 1024, MB = 1024 * 1024, @@ -86,12 +86,12 @@ class UModioSDKLibrary : public UBlueprintFunctionLibrary */ UFUNCTION(BlueprintPure, Category = "mod.io|String", meta = (DisplayName = "ToString (Filesize)", CompactNodeTitle = "Filesize")) - static FText Filesize_ToString(int64 FileSize, int32 MaxDecimals = 2, EFileSizeUnit Unit = EFileSizeUnit::Largest); + static MODIO_API FText Filesize_ToString(int64 FileSize, int32 MaxDecimals = 2, EFileSizeUnit Unit = EFileSizeUnit::Largest); /** Converts an integer64 value to a string */ UFUNCTION(BlueprintPure, meta = (DisplayName = "ToString (integer64)", CompactNodeTitle = "->", BlueprintAutocast), Category = "mod.io|Utilities|String") - static FString Conv_Int64ToString(int64 InInt); + static MODIO_API FString Conv_Int64ToString(int64 InInt); /** * @brief Converts a passed in integer to text based on formatting options @@ -104,7 +104,7 @@ class UModioSDKLibrary : public UBlueprintFunctionLibrary */ UFUNCTION(BlueprintPure, meta = (DisplayName = "ToText (integer64)", AdvancedDisplay = "1", BlueprintAutocast), Category = "mod.io|Utilities|Text") - static FText Conv_Int64ToText(int64 Value, bool bAlwaysSign = false, bool bUseGrouping = true, + static MODIO_API FText Conv_Int64ToText(int64 Value, bool bAlwaysSign = false, bool bUseGrouping = true, int32 MinimumIntegralDigits = 1, int32 MaximumIntegralDigits = 324); /** @brief Dividend/Divisor and return the floating point result with no checks **/ @@ -112,5 +112,5 @@ class UModioSDKLibrary : public UBlueprintFunctionLibrary meta = (DisplayName = "Get Percent (integer64/integer64)", CompactNodeTitle = "Percent", Keywords = "/ % percent pct"), Category = "mod.io|Math|integer64") - static float Pct_Int64Int64(int64 Dividend, int64 Divisor); + static MODIO_API float Pct_Int64Int64(int64 Dividend, int64 Divisor); }; diff --git a/Source/Modio/Public/ModioSDK.h b/Source/Modio/Public/ModioSDK.h index 558e107b..2ee5613f 100644 --- a/Source/Modio/Public/ModioSDK.h +++ b/Source/Modio/Public/ModioSDK.h @@ -13,19 +13,18 @@ #define MODIO_PLATFORM_UNREAL 1 -#if defined(_MSC_VER) - #pragma warning(push) - // These warnings are in third party libraries and we don't care about those - #pragma warning(disable : 4265 4996 4668 4191 4583 4582) - // These warnings is in our code, and should be fixed - #pragma warning(disable : 4063) -#endif +/* +#pragma warning(push) +// These warnings are in third party libraries and we don't care about those +#pragma warning(disable : 4265 4996 4668 4191 4583 4582) +// These warnings is in our code, and should be fixed +#pragma warning(disable : 4063) + +*/ #include "modio/ModioSDK.h" #undef MODIO_PLATFORM_UNREAL #undef ASIO_NO_EXCEPTIONS -#if defined(_MSC_VER) - #pragma warning(pop) -#endif +//#pragma warning(pop) diff --git a/Source/Modio/Public/ModioSettings.h b/Source/Modio/Public/ModioSettings.h index a8ad678c..3726a825 100644 --- a/Source/Modio/Public/ModioSettings.h +++ b/Source/Modio/Public/ModioSettings.h @@ -45,7 +45,7 @@ class MODIO_API UModioSettings : public UObject EModioPortal DefaultPortal = EModioPortal::None; #if WITH_EDITORONLY_DATA - UPROPERTY(EditDefaultsOnly, config, Category = "Project|Automation Testing", meta = (ShowOnlyInnerProperties)) + UPROPERTY(EditDefaultsOnly, config, Category = "Project|Automation Testing") FModioInitializeOptions AutomationTestOptions; UPROPERTY(EditDefaultsOnly, config, Category = "Project|Automation Testing") diff --git a/Source/Modio/Public/ModioSubsystem.h b/Source/Modio/Public/ModioSubsystem.h index 5358dc9d..3eb9d485 100644 --- a/Source/Modio/Public/ModioSubsystem.h +++ b/Source/Modio/Public/ModioSubsystem.h @@ -183,7 +183,7 @@ class UModioSubsystem : public UEngineSubsystem * @error ModManagementError::ModManagementAlreadyEnabled|Mod management was already enabled. The mod management * callback has not been changed */ - MODIO_API void EnableModManagement(FOnModManagementDelegateFast Callback); + MODIO_API FModioErrorCode EnableModManagement(FOnModManagementDelegateFast Callback); /** * @brief Disables automatic installation or uninstallation of mods based on the user's subscriptions. Allows @@ -390,7 +390,8 @@ class UModioSubsystem : public UEngineSubsystem * @requires no-authenticated-user * @errorcategory NetworkError|Couldn't connect to mod.io servers * @error GenericError::SDKNotInitialized|SDK not initialized - * @error UserAuthError::AlreadyAuthenticated|Authenticated user already signed-in. Call ClearUserDataAsync to + * @error +|Authenticated user already signed-in. Call ClearUserDataAsync to * de-authenticate the old user, then Shutdown() and reinitialize the SDK first. **/ MODIO_API void RequestEmailAuthCodeAsync(const FModioEmailAddress& EmailAddress, FOnErrorOnlyDelegateFast Callback); @@ -413,7 +414,7 @@ class UModioSubsystem : public UEngineSubsystem /** * @brief Uses platform-specific authentication to associate a Mod.io user account with the current platform user - * @param User Authentication payload data to submit to the provider. + * @param User Authentication payload data to submit to the provider. * @param Provider The provider to use to perform the authentication * @param Callback Callback invoked once the authentication request has been made * @requires initialized-sdk @@ -427,6 +428,20 @@ class UModioSubsystem : public UEngineSubsystem MODIO_API void AuthenticateUserExternalAsync(const FModioAuthenticationParams& User, EModioAuthenticationProvider Provider, FOnErrorOnlyDelegateFast Callback); + /** + * @docpublic + * @brief Queries the server to verify the state of the currently authenticated user if there is one present. An + * empty ErrorCode is passed to the callback to indicate successful verification, i.e. the mod.io server was + * contactable and the user's authentication remains valid. + * @param Callback Callback invoked with the results of the verification process + * @requires initialized-sdk + * @requires no-rate-limiting + * @requires authenticated-user + * @errorcategory NetworkError|Couldn't connect to mod.io servers + * @error GenericError::SDKNotInitialized|SDK not initialized + * @error UserDataError::InvalidUser|No authenticated user + */ + MODIO_API void VerifyUserAuthenticationAsync(FOnErrorOnlyDelegateFast Callback); /** * @docpublic @@ -490,6 +505,7 @@ class UModioSubsystem : public UEngineSubsystem /** Get our image cache */ struct FModioImageCache& GetImageCache() const; + void ShowUserAuthenticationDialog(); /* @brief Archives a mod. This mod will no longer be able to be viewed or retrieved via the SDK, but it will still @@ -580,7 +596,7 @@ class UModioSubsystem : public UEngineSubsystem * by the SDK */ UFUNCTION(BlueprintCallable, DisplayName = "EnableModManagement", Category = "mod.io|Mod Management") - MODIO_API void K2_EnableModManagement(FOnModManagementDelegate Callback); + MODIO_API FModioErrorCode K2_EnableModManagement(FOnModManagementDelegate Callback); /** * @brief Provides progress information for a mod installation or update operation if one is currently in progress. @@ -770,6 +786,22 @@ class UModioSubsystem : public UEngineSubsystem EModioAuthenticationProvider Provider, FOnErrorOnlyDelegate Callback); + /** + * @docpublic + * @brief Queries the server to verify the state of the currently authenticated user if there is one present. An + * empty ErrorCode is passed to the callback to indicate successful verification, i.e. the mod.io server was + * contactable and the user's authentication remains valid. + * @param Callback Callback invoked with the results of the verification process + * @requires initialized-sdk + * @requires no-rate-limiting + * @requires authenticated-user + * @errorcategory NetworkError|Couldn't connect to mod.io servers + * @error GenericError::SDKNotInitialized|SDK not initialized + * @error UserDataError::InvalidUser|No authenticated user + */ + UFUNCTION(BlueprintCallable, DisplayName = "VerifyUserAuthenticationAsync", Category = "mod.io|Authentication") + MODIO_API void K2_VerifyUserAuthenticationAsync(FOnErrorOnlyDelegate Callback); + /** * @brief This function retrieves the information required for a game to display the mod.io terms of use to a player * who wishes to create a mod.io account diff --git a/Source/Modio/Public/Types/ModioCommonTypes.h b/Source/Modio/Public/Types/ModioCommonTypes.h index 74fa2eb8..744921dd 100644 --- a/Source/Modio/Public/Types/ModioCommonTypes.h +++ b/Source/Modio/Public/Types/ModioCommonTypes.h @@ -48,6 +48,22 @@ enum class EModioPortal : uint8 XboxLive }; +/** @brief Enum representing the platform(s) that a modfile is enabled for */ +enum class EModioModfilePlatform : uint8 +{ + Windows, + Mac, + Linux, + Android, + iOS, + XboxOne, + XboxSeriesX, + PS4, + PS5, + Switch, + Oculus +}; + /** @brief Enum representing mod logo sizes */ UENUM(BlueprintType) enum class EModioLogoSize : uint8 @@ -249,7 +265,6 @@ struct MODIO_API FModioGameID friend struct Modio::GameID ToModio(const FModioGameID& In); UPROPERTY(EditAnywhere, meta = (AllowPrivateAccess = true), Category = "mod.io|CommonTypes") int64 GameId; - }; template<> diff --git a/Source/Modio/Public/Types/ModioCreateModFileParams.h b/Source/Modio/Public/Types/ModioCreateModFileParams.h index 219581b5..c47a1c98 100644 --- a/Source/Modio/Public/Types/ModioCreateModFileParams.h +++ b/Source/Modio/Public/Types/ModioCreateModFileParams.h @@ -27,4 +27,6 @@ struct MODIO_API FModioCreateModFileParams TOptional bSetAsActiveRelease; TOptional MetadataBlob; + + TOptional> ModfilePlatforms; }; \ No newline at end of file diff --git a/Source/Modio/Public/Types/ModioFilterParams.h b/Source/Modio/Public/Types/ModioFilterParams.h index 21138cf3..31fc1972 100644 --- a/Source/Modio/Public/Types/ModioFilterParams.h +++ b/Source/Modio/Public/Types/ModioFilterParams.h @@ -31,7 +31,8 @@ enum class EModioSortFieldType : uint8 SubscriberCount, /** use number of subscribers */ Rating, /** use mod rating */ DateMarkedLive, /** use date mod was marked live */ - DateUpdated /** use date mod was last updated */ + DateUpdated, /** use date mod was last updated */ + DownloadsTotal /** use downloads total */ }; /// @brief Enum indicating which direction sorting should be applied diff --git a/Source/Modio/Public/Types/ModioModCollectionEntry.h b/Source/Modio/Public/Types/ModioModCollectionEntry.h index ffed236c..e95bb68c 100644 --- a/Source/Modio/Public/Types/ModioModCollectionEntry.h +++ b/Source/Modio/Public/Types/ModioModCollectionEntry.h @@ -1,22 +1,21 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io UE4 Plugin. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #pragma once #include "Types/ModioCommonTypes.h" #include "Types/ModioModInfo.h" +#include "Types/ModioUnsigned64.h" #include "ModioModCollectionEntry.generated.h" - - namespace Modio { class ModCollectionEntry; @@ -48,9 +47,11 @@ struct MODIO_API FModioModCollectionEntry const FString GetPath() const; + FModioUnsigned64 GetSizeOnDisk() const; + private: friend struct FModioModCollectionEntry ToUnreal(const class Modio::ModCollectionEntry& In); - + FModioUnsigned64 SizeOnDisk; EModioModState ModState; FModioModID ModID; TOptional ModPath; diff --git a/Source/Modio/Public/Types/ModioModInfo.h b/Source/Modio/Public/Types/ModioModInfo.h index 412cd9e3..06e44a14 100644 --- a/Source/Modio/Public/Types/ModioModInfo.h +++ b/Source/Modio/Public/Types/ModioModInfo.h @@ -1,11 +1,11 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io UE4 Plugin. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #pragma once @@ -19,7 +19,6 @@ #include "ModioModInfo.generated.h" - namespace Modio { struct ModInfo; @@ -34,7 +33,6 @@ enum class EModioMaturityFlags : uint8 Explicit = 8 }; - /** @brief Full mod profile including current release information, media links, and stats */ USTRUCT(BlueprintType) struct MODIO_API FModioModInfo @@ -89,6 +87,10 @@ struct MODIO_API FModioModInfo UPROPERTY(BlueprintReadOnly, Category = "Profile") EModioMaturityFlags ProfileMaturityOption; + /** @brief Is the mod marked as visible? */ + UPROPERTY(BlueprintReadOnly, Category = "Profile") + bool bVisible; + UPROPERTY(BlueprintReadOnly, Category = "Metadata") FString MetadataBlob; @@ -119,6 +121,7 @@ struct MODIO_API FModioModInfo /** @brief Stats and rating information for the mod */ UPROPERTY(BlueprintReadOnly, Category = "Stats") FModioModStats Stats; + friend struct FModioModInfo ToUnreal(const struct Modio::ModInfo& In); }; diff --git a/Source/Modio/Public/Types/ModioModProgressInfo.h b/Source/Modio/Public/Types/ModioModProgressInfo.h index b5e3b5ce..80376535 100644 --- a/Source/Modio/Public/Types/ModioModProgressInfo.h +++ b/Source/Modio/Public/Types/ModioModProgressInfo.h @@ -11,6 +11,8 @@ #pragma once #include "Types/ModioCommonTypes.h" +#include "Types/ModioUnsigned64.h" + #include "ModioModProgressInfo.generated.h" @@ -27,19 +29,19 @@ struct MODIO_API FModioModProgressInfo /** @brief Total size of the downloaded file */ UPROPERTY(BlueprintReadOnly,Category="ModProgressInfo") - int64 TotalDownloadSize; + FModioUnsigned64 TotalDownloadSize; /** @brief Current amount downloaded in bytes */ UPROPERTY(BlueprintReadOnly,Category="ModProgressInfo|Current") - int64 CurrentlyDownloadedBytes; + FModioUnsigned64 CurrentlyDownloadedBytes; /** @brief Total size on disk when fully extracted */ UPROPERTY(BlueprintReadOnly,Category="ModProgressInfo") - int64 TotalExtractedSizeOnDisk; + FModioUnsigned64 TotalExtractedSizeOnDisk; /** @brief Amount of data currently extracted */ UPROPERTY(BlueprintReadOnly,Category="ModProgressInfo|Current") - int64 CurrentlyExtractedBytes; + FModioUnsigned64 CurrentlyExtractedBytes; /** @brief The mod ID of the mod being processed */ UPROPERTY(BlueprintReadOnly,Category="ModProgressInfo") diff --git a/Source/Modio/Public/Types/ModioReportParams.h b/Source/Modio/Public/Types/ModioReportParams.h index 900eb66e..a8248e8f 100644 --- a/Source/Modio/Public/Types/ModioReportParams.h +++ b/Source/Modio/Public/Types/ModioReportParams.h @@ -35,10 +35,16 @@ USTRUCT(BlueprintType) struct MODIO_API FModioReportParams { GENERATED_BODY(); - - + FModioReportParams(); + /// @docpublic + /// @brief Creates a content report for a game. + /// @param Mod The ID of the content being reported + /// @param Type The nature of the content report + FModioReportParams(struct FModioModID Mod, EModioReportType Type); + + /// @docpublic /// @brief Creates a content report for a game. /// @param Game The ID of the game being reported /// @param Type The nature of the content report @@ -70,8 +76,6 @@ struct MODIO_API FModioReportParams /// empty FModioReportParams(struct FModioModID Mod, EModioReportType Type, FString ReportDescription, TOptional ReporterName, TOptional ReporterContact); - -private: enum class ResourceType : uint8 diff --git a/Source/Modio/Public/Types/ModioUnsigned64.h b/Source/Modio/Public/Types/ModioUnsigned64.h new file mode 100644 index 00000000..4d0eb5fc --- /dev/null +++ b/Source/Modio/Public/Types/ModioUnsigned64.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2021 mod.io Pty Ltd. + * + * This file is part of the mod.io UE4 Plugin. + * + * Distributed under the MIT License. (See accompanying file LICENSE or + * view online at ) + * + */ + +#pragma once + +#include "Kismet/BlueprintFunctionLibrary.h" + +#include "ModioUnsigned64.generated.h" + +/// @brief Trivial Blueprint-compatible wrapper around an unsigned 64-bit integer +USTRUCT(BlueprintType) +struct MODIO_API FModioUnsigned64 +{ + GENERATED_BODY(); + + uint64 Underlying; + + FModioUnsigned64() : Underlying(0) {}; + FModioUnsigned64(const FModioUnsigned64& Other) = default; + FModioUnsigned64(FModioUnsigned64&& Other) = default; + + explicit FModioUnsigned64(uint64 Value) : Underlying(Value) {}; + + constexpr explicit operator uint64() const + { + return Underlying; + } + + constexpr explicit operator bool() const + { + return (bool) Underlying; + } + + constexpr explicit operator double() const + { + return double(Underlying); + } + constexpr explicit operator float() const + { + return float(Underlying); + } + FORCEINLINE FModioUnsigned64& operator=(const FModioUnsigned64& Other) + { + if (this != &Other) + { + Underlying = Other.Underlying; + } + return *this; + } + + FORCEINLINE friend bool operator<(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS.Underlying < RHS.Underlying; + } + FORCEINLINE friend bool operator>(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS.Underlying > RHS.Underlying; + } + FORCEINLINE friend bool operator==(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS.Underlying == RHS.Underlying; + } + FORCEINLINE friend bool operator!=(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return !(LHS == RHS); + } + FORCEINLINE friend bool operator==(const FModioUnsigned64& LHS, const uint64& RHS) + { + return LHS.Underlying == RHS; + } + + FORCEINLINE friend FModioUnsigned64 operator/(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return FModioUnsigned64(LHS.Underlying / RHS.Underlying); + } + + FORCEINLINE friend FModioUnsigned64 operator+(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return FModioUnsigned64(LHS) += RHS; + } + + FORCEINLINE friend FModioUnsigned64 operator-(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return FModioUnsigned64(LHS) -= RHS; + } + FORCEINLINE friend FModioUnsigned64 operator+(const FModioUnsigned64& LHS, const uint64 RHS) + { + return FModioUnsigned64(LHS.Underlying + RHS); + } + FORCEINLINE friend FModioUnsigned64 operator-(const FModioUnsigned64& LHS, const uint64 RHS) + { + return FModioUnsigned64(LHS.Underlying - RHS); + } + + FORCEINLINE friend double operator/(const FModioUnsigned64& LHS, double Divisor) + { + return LHS.Underlying / Divisor; + } + + FORCEINLINE FModioUnsigned64& operator+=(const FModioUnsigned64& Other) + { + Underlying += Other.Underlying; + return *this; + } + FORCEINLINE FModioUnsigned64& operator-=(const FModioUnsigned64& Other) + { + Underlying -= Other.Underlying; + return *this; + } +}; + +UCLASS() +class MODIO_API UModioUnsigned64Library : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = "===", Keywords = "== equal", + DisplayName = "ModioUnsigned64 == ModioUnsigned64")) + static bool EqualTo(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS == RHS; + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = "!=", Keywords = "!= not equal", + DisplayName = "ModioUnsigned64 != ModioUnsigned64")) + static bool NotEqualTo(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS != RHS; + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = ">", Keywords = "> greater than", + DisplayName = "ModioUnsigned64 > ModioUnsigned64")) + static bool GreaterThan(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS > RHS; + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = "<", Keywords = "< less than", + DisplayName = "ModioUnsigned64 < ModioUnsigned64")) + static bool LessThan(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS < RHS; + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = "-", Keywords = "- subtract minus", + DisplayName = "ModioUnsigned64 - ModioUnsigned64")) + static FModioUnsigned64 Subtract(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS - RHS; + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = "+", Keywords = "+ add plus", + DisplayName = "ModioUnsigned64 + ModioUnsigned64")) + static FModioUnsigned64 Add(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS + RHS; + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = "/", Keywords = "/ divide", DisplayName = "ModioUnsigned64 / ModioUnsigned64")) + static FModioUnsigned64 Divide(const FModioUnsigned64& LHS, const FModioUnsigned64& RHS) + { + return LHS / RHS; + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (CompactNodeTitle = "/", Keywords = "/ divide", DisplayName = "ModioUnsigned64 / float")) + static float DivideFloat(const FModioUnsigned64& LHS, const float RHS) + { + return (float) (LHS / (double) RHS); + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64") + static void BreakToComponents(const FModioUnsigned64& In, int32& High, int32& Low) + { + High = static_cast(In.Underlying >> 32); + Low = static_cast(static_cast(In.Underlying)); + } + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64") + static FModioUnsigned64 MakeFromComponents(const int32& High, const int32& Low) + { + uint64 RawValue = static_cast(High); + RawValue = RawValue << 32; + RawValue |= static_cast(Low); + return FModioUnsigned64(RawValue); + } + + UFUNCTION(BlueprintPure, BlueprintCallable, Category = "mod.io|Unsigned64", + meta = (DisplayName = "TruncateModioUnsigned64ToFloat", BlueprintAutocast)) + static float Conv_FModioUnsigned64ToFloat(const FModioUnsigned64& In) + { + return float(In.Underlying); + } +}; \ No newline at end of file diff --git a/Source/ModioTests/Private/Tests/ModioUnsigned64Tests.cpp b/Source/ModioTests/Private/Tests/ModioUnsigned64Tests.cpp new file mode 100644 index 00000000..e455ef66 --- /dev/null +++ b/Source/ModioTests/Private/Tests/ModioUnsigned64Tests.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2021 mod.io Pty Ltd. + * + * This file is part of the mod.io UE4 Plugin. + * + * Distributed under the MIT License. (See accompanying file LICENSE or + * view online at ) + * + */ + +#include "Engine.h" +#include "Libraries/ModioSDKLibrary.h" +#include "Misc/AutomationTest.h" +#include "Types/ModioUnsigned64.h" + +#if WITH_DEV_AUTOMATION_TESTS + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64ConversionBoolZeroTest, + "Modio.ModioUnsigned64.Conversion.Bool.ZeroFalse", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) +bool FModioUnsigned64ConversionBoolZeroTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 Empty = FModioUnsigned64(0); + TestEqual("ZeroIsFalse", (bool)Empty, false); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64ConversionBoolNonZeroTest, + "Modio.ModioUnsigned64.Conversion.Bool.NonZeroTrue", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64ConversionBoolNonZeroTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 NonZero = FModioUnsigned64(123); + TestEqual("NonZeroIsTrue", (bool)NonZero, true); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64OperatorLessTest, "Modio.ModioUnsigned64.Arithmetic.LessThan", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64OperatorLessTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 First = FModioUnsigned64(1); + FModioUnsigned64 Second = FModioUnsigned64(2); + TestEqual("LessThanTrue", First < Second, true); + TestEqual("LessThanFalse", Second < First, false); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64OperatorGreaterTest, "Modio.ModioUnsigned64.Arithmetic.GreaterThan", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64OperatorGreaterTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 First = FModioUnsigned64(1); + FModioUnsigned64 Second = FModioUnsigned64(2); + TestEqual("GreaterThanTrue", Second > First, true); + TestEqual("GreaterThanFalse", First > Second, false); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64OperatorEqualTest, "Modio.ModioUnsigned64.Arithmetic.Equal", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64OperatorEqualTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 First = FModioUnsigned64(123456789); + FModioUnsigned64 Second = FModioUnsigned64(123456789); + FModioUnsigned64 Third = FModioUnsigned64(987654321); + TestEqual("EqualsTrue", First == Second, true); + TestEqual("EqualsFalse", First == Third, false); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64OperatorNotEqualTest, "Modio.ModioUnsigned64.Arithmetic.NotEqual", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64OperatorNotEqualTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 First = FModioUnsigned64(123456789); + FModioUnsigned64 Second = FModioUnsigned64(123456789); + FModioUnsigned64 Third = FModioUnsigned64(987654321); + TestEqual("NotEqualsTrue", First != Third, true); + TestEqual("NotEqualsFalse", First != Second, false); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64OperatorSubtractTest, "Modio.ModioUnsigned64.Arithmetic.Subtract", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64OperatorSubtractTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 First = FModioUnsigned64(10); + FModioUnsigned64 Second = FModioUnsigned64(4); + FModioUnsigned64 Result = FModioUnsigned64(6); + TestEqual("SubtractionCorrectResult", First - Second, Result); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64OperatorAddTest, "Modio.ModioUnsigned64.Arithmetic.Add", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64OperatorAddTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 First = FModioUnsigned64(6); + FModioUnsigned64 Second = FModioUnsigned64(4); + FModioUnsigned64 Result = FModioUnsigned64(10); + TestEqual("AdditionCorrectResult", First + Second, Result); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64MakeBreakComponentTest, "Modio.ModioUnsigned64.MakeBreak", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64MakeBreakComponentTest::RunTest(const FString& Parameters) +{ + uint64 Value = 0xabcdF00d1234F00d; + FModioUnsigned64 First = FModioUnsigned64(Value); + int32 High; + int32 Low; + UModioUnsigned64Library::BreakToComponents(First, High, Low); + TestEqual("HighComponentCorrect", static_cast(High), 0xabcdf00d); + TestEqual("LowComponentCorrect", static_cast(Low), 0x1234f00d); + FModioUnsigned64 Second = UModioUnsigned64Library::MakeFromComponents(High, Low); + TestEqual("RoundTripCorrectResult", Second, First); + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioUnsigned64ValueConversionTest, "Modio.ModioUnsigned64.Conversion.UInt64", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) + +bool FModioUnsigned64ValueConversionTest::RunTest(const FString& Parameters) +{ + FModioUnsigned64 Value = FModioUnsigned64(0xabcdF00d1234F00d); + uint64 ConvertedValue = (uint64) Value; + TestEqual("ValueConversionCorrect", Value == ConvertedValue, true); + return true; +} + +#endif \ No newline at end of file diff --git a/Source/ThirdParty/NativeSDK b/Source/ThirdParty/NativeSDK index 09d9fc1b..302d4689 160000 --- a/Source/ThirdParty/NativeSDK +++ b/Source/ThirdParty/NativeSDK @@ -1 +1 @@ -Subproject commit 09d9fc1b7919f3c4619f0be7993fd218be8cdaf4 +Subproject commit 302d46897e0f7fbff3e685c3290dfc7e348b7193 diff --git a/Source/uring/Public/liburing/compat.h b/Source/uring/Public/liburing/compat.h deleted file mode 100644 index 9a9ad9bc..00000000 --- a/Source/uring/Public/liburing/compat.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef LIBURING_COMPAT_H -#define LIBURING_COMPAT_H - -#include -#include - -struct __kernel_timespec - { - int64_t tv_sec; - long long tv_nsec; - }; - -# include - - struct open_how - { - uint64_t flags; - uint64_t mode; - uint64_t resolve; - }; - -#ifndef __kernel_rwf_t - typedef int __kernel_rwf_t; -#endif - -#endif