diff --git a/Doc/documentation.html b/Doc/documentation.html index 543e1c85..1c57340e 100644 --- a/Doc/documentation.html +++ b/Doc/documentation.html @@ -822,6 +822,8 @@

mod.io UE4 Plugin Documentation

  • Query System Installations
  • UnsubscribeFromModAsync
  • SubscribeToModAsync
  • +
  • SubmitNewModFileForMod
  • +
  • SubmitNewModAsync
  • SubmitModRatingAsync
  • ShutdownAsync
  • RequestEmailAuthCodeAsync
  • @@ -838,6 +840,7 @@

    mod.io UE4 Plugin Documentation

  • GetModMediaAsync (Avatar)
  • GetModInfoAsync
  • GetModDependenciesAsync
  • +
  • GetModCreationHandle
  • FetchExternalUpdatesAsync
  • EnableModManagement
  • ClearUserDataAsync
  • @@ -876,15 +879,19 @@

    mod.io UE4 Plugin Documentation

  • ModioOptionalModTagOptions
  • ModioOptionalTerms
  • ModioOptionalModDependencyList
  • +
  • ModioOptionalModID
  • ModioAuthenticationParams
  • ModioEmailAuthCode
  • ModioEmailAddress
  • ModioApiKey
  • ModioGameID
  • +
  • ModioCreateModFileParams
  • +
  • ModioCreateModParams
  • ModioFilterParams
  • ModioImage
  • ModioInitializeOptions
  • ModioModCollectionEntry
  • +
  • ModioModCreationHandle
  • ModioModDependencyList
  • ModioModDependency
  • ModioOptionalModProgressInfo
  • @@ -1984,6 +1991,176 @@
    Parameters

    +

    SubmitNewModFileForMod

    +
    +
    +nd img K2 SubmitNewModFileForMod +
    +
    +
    +
    +
    void K2_SubmitNewModFileForMod(FModioModID Mod, FModioCreateModFileParams Params)
    +
    +
    +
    +

    Queues the upload of a new mod file release for the specified mod, using the submitted parameters. 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.

    +
    +
    + + + + + +
    +
    Note
    +
    +This function is part of an experimental feature and is subject to change. +
    +
    +
    Requirements
    +
    + +
    +
    Parameters
    + ++++ + + + + + + + + + + + + + + +

    Target

    Modio Subsystem Object Reference

    Mod

    The ID of the mod you are submitting a file for

    Params

    Information about the mod file being created, including the root path of the directory that will be archived

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

    UserDataError::InvalidUser

    No authenticated user

    +
    +
    +
    +

    SubmitNewModAsync

    +
    +
    +nd img K2 SubmitNewModAsync +
    +
    +
    +
    +
    void K2_SubmitNewModAsync(FModioModCreationHandle Handle, FModioCreateModParams Params, FOnSubmitNewModDelegate Callback)
    +
    +
    +
    +

    Requests the creation of a new mod on the server with the specified parameters

    +
    +
    + + + + + +
    +
    Note
    +
    +This function is part of an experimental feature and is subject to change. +
    +
    +
    Requirements
    +
    + +
    +
    Parameters
    + ++++ + + + + + + + + + + + + + + + + + + +

    Target

    Modio Subsystem Object Reference

    Handle

    The ModCreationHandle for this submission. Once this method invokes your callback indicating success, the ModCreationHandle is invalid for the rest of the session and you should request a new one for the next submission attempt.

    Params

    Information about the new mod to create

    Callback

    Callback providing a status code and an optional FModioModID for the newly created mod

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

    GenericError::SDKNotInitialized

    SDK not initialized

    UserDataError::InvalidUser

    No authenticated user

    NetworkError

    Couldn’t connect to mod.io servers

    InvalidArgsError

    Some fields in Params did not pass validation

    +
    +
    +

    SubmitModRatingAsync

    @@ -1998,7 +2175,7 @@

    SubmitModRatingAsync

    Submits a rating for a mod on behalf of the current user. Submit a neutral rating to effectively clear a rating already submitted by a user. Submitting other values will overwrite any existing rating submitted by this user.

    -
    Requirements
    +
    Requirements
    • @@ -2012,7 +2189,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2037,7 +2214,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2079,7 +2256,7 @@

    ShutdownAsync

    Cancels any running internal operations, frees SDK resources, and invokes any pending callbacks with Modio::GenericError::OperationCanceled . This function will NOT block while the deinitialization occurs.

    -
    Parameters
    +
    Parameters
    @@ -2113,7 +2290,7 @@

    RequestEmailAuthCodeAsync

    Begins email authentication for the current session by requesting a one-time code be sent to the specified email address if it is associated with a Mod.io account

    -
    Requirements
    +
    Requirements
    • @@ -2127,7 +2304,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2148,7 +2325,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2186,7 +2363,7 @@

    ReportContentAsync

    Sends a content report to mod.io. When using this function, please inform your users that if they provide their contact name or details in the Report parameter, that those may be shared with the person responsible for the content being reported. For more information on what data in a report will be shared with whom, please see our website’s report form for more information.

    -
    Requirements
    +
    Requirements
    • @@ -2194,7 +2371,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2215,7 +2392,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2249,7 +2426,7 @@

    QueryUserProfile

    Fetches the currently authenticated Mod.io user profile if there is one associated with the current platform user

    -
    Parameters
    +
    Parameters
    @@ -2287,7 +2464,7 @@

    QueryCurrentModUpdate

    Provides progress information for a mod installation or update operation if one is currently in progress.

    -
    Parameters
    +
    Parameters
    @@ -2325,7 +2502,7 @@

    ListAllModsAsync

    Provides a list of mods for the current game, that match the parameters specified in the filter

    -
    Requirements
    +
    Requirements
    • @@ -2336,7 +2513,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2357,7 +2534,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2391,7 +2568,7 @@

    InitializeAsync

    Initializes the SDK for the given user. Loads the state of mods installed on the system as well as the set of mods the specified user has installed on this device

    -
    Parameters
    +
    Parameters
    @@ -2429,7 +2606,7 @@

    GetUserMediaAsync (Avatar)

    Downloads the avatar of the currently authenticated user. Will only perform a download if there is no local cache of the avatar or if that cached copy is out-of-date.

    -
    Requirements
    +
    Requirements
    • @@ -2443,7 +2620,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2464,7 +2641,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2502,7 +2679,7 @@

    GetTermsOfUseAsync

    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

    -
    Requirements
    +
    Requirements
    • @@ -2510,7 +2687,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2535,7 +2712,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2569,7 +2746,7 @@

    GetModTagOptionsAsync

    Fetches the available tags used on mods for the current game. These tags can them be used in conjunction with the FilterParams passed to ListAllMods Will be cached when first received

    -
    Requirements
    +
    Requirements
    • @@ -2580,7 +2757,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2597,7 +2774,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2631,7 +2808,7 @@

    GetModMediaAsync (Logo)

    Downloads the logo for the specified mod. Will use existing file if it is already present on disk

    -
    Requirements
    +
    Requirements
    • @@ -2642,7 +2819,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2667,7 +2844,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2709,7 +2886,7 @@

    GetModMediaAsync (Gallery Image)

    Get a gallery image for the specified mod ID. If it already exists on disk the file will be reused unless it is outdated

    -
    Requirements
    +
    Requirements
    • @@ -2720,7 +2897,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2749,7 +2926,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2791,7 +2968,7 @@

    GetModMediaAsync (Avatar)

    Downloads the creator avatar for a specified mod. Will use existing file if it is already present on disk and not outdated

    -
    Requirements
    +
    Requirements
    • @@ -2802,7 +2979,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2827,7 +3004,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2869,7 +3046,7 @@

    GetModInfoAsync

    Fetches detailed information about the specified mod, including description and file metadata for the most recent release

    -
    Requirements
    +
    Requirements
    • @@ -2880,7 +3057,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2901,7 +3078,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -2951,7 +3128,7 @@

    GetModDependenciesAsync

    -
    Requirements
    +
    Requirements
    • @@ -2962,7 +3139,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -2983,7 +3160,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -3003,6 +3180,52 @@
    Error Values

    +

    GetModCreationHandle

    +
    +
    +nd img K2 GetModCreationHandle +
    +
    +
    +
    +
    FModioModCreationHandle K2_GetModCreationHandle()
    +
    +
    +
    +

    Gets a new mod handle for use with SubmitNewModAsync.

    +
    +
    +
    + + + + +
    +
    Note
    +
    +This function is part of an experimental feature and is subject to change. +
    +
    +
    Parameters
    + ++++ + + + + + + + + + + +

    Target

    Modio Subsystem Object Reference

    Return Value

    New handle

    +
    +
    +

    FetchExternalUpdatesAsync

    @@ -3017,7 +3240,7 @@

    FetchExternalUpdatesAsync

    Synchronises the local list of the current user’s subscribed mods with the server. Any mods that have been externally subscribed will be automatically marked for installation, and mods that have been externally removed from the user’s subscriptions may be uninstalled if no other local users have a current subscription.

    -
    Parameters
    +
    Parameters
    @@ -3051,7 +3274,7 @@

    EnableModManagement

    Enables the automatic management of installed mods on the system based on the user’s subscriptions.

    -
    Parameters
    +
    Parameters
    @@ -3085,7 +3308,7 @@

    ClearUserDataAsync

    De-authenticates the current Mod.io user for the current session, and clears all user-specific data stored on the current device. Any subscribed mods that are installed but do not have other local users subscribed will be uninstalled

    -
    Requirements
    +
    Requirements
    • @@ -3099,7 +3322,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -3116,7 +3339,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -3150,7 +3373,7 @@

    AuthenticateUserExternalAsync

    Uses platform-specific authentication to associate a Mod.io user account with the current platform user

    -
    Requirements
    +
    Requirements
    • @@ -3164,7 +3387,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -3189,7 +3412,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -3227,7 +3450,7 @@

    AuthenticateUserEmailAsync

    Completes email authentication for the current session by submitting the one-time code sent to the user’s email address

    -
    Requirements
    +
    Requirements
    • @@ -3241,7 +3464,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -3262,7 +3485,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -3300,7 +3523,7 @@

    Is Mod Management Busy

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

    -
    Parameters
    +
    Parameters
    @@ -3338,7 +3561,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
    • @@ -3346,7 +3569,7 @@
      Requirements
    -
    Parameters
    +
    Parameters
    @@ -3384,7 +3607,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
    @@ -3405,7 +3628,7 @@
    Parameters
    -
    Error Values
    +
    Error Values
    @@ -3443,7 +3666,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
    @@ -3962,6 +4185,10 @@

    ModioOptionalModDependencyList


    +

    ModioOptionalModID

    +
    +
    +

    ModioAuthenticationParams

    Simple struct to encapsulate data passed to external authentication systems

    @@ -4022,6 +4249,54 @@

    ModioGameID


    +

    ModioCreateModFileParams

    +

    Variables

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

    FString

    PathToModRootDirectory

    +
    +
    +
    +

    ModioCreateModParams

    +

    Variables

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

    FString

    PathToLogoFile

    FString

    Name

    FString

    Summary

    +
    +
    +

    ModioFilterParams

    Class storing a set of filter parameters for use in ListAllModsAsync

    @@ -4033,7 +4308,7 @@

    ModioImage

    wrapper for images that’s returned by the api

    -

    Variables

    +

    Variables

    @@ -4052,7 +4327,7 @@

    Variables

    ModioInitializeOptions

    -

    Variables

    +

    Variables

    @@ -4092,6 +4367,10 @@

    ModioModCollectionEntry


    +

    ModioModCreationHandle

    +
    +
    +

    ModioModDependencyList

    Paged list of mod dependencies

    @@ -4127,7 +4406,7 @@

    ModioModDependency

    -

    Variables

    +

    Variables

    @@ -4158,7 +4437,7 @@

    ModioModProgressInfo

    Class representing the progress of a mod installation or update

    -

    Variables

    +

    Variables

    @@ -4204,7 +4483,7 @@

    ModioTerms

    This struct contains strings that should be displayed to a user when displaying the terms of use and offering to create a mod.io account

    -

    Variables

    +

    Variables

    @@ -4248,7 +4527,7 @@

    Variables

    -

    Variables

    +

    Variables

    @@ -4284,7 +4563,7 @@

    ModioValidationError

    Wrapper struct containing information about a field validation error

    -

    Variables

    +

    Variables

    @@ -4326,7 +4605,7 @@

    Set Portal

    Changes the portal for the provided set of initialization options

    -

    Parameters

    +

    Parameters

    @@ -4368,7 +4647,7 @@

    Make Initialize Options

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

    -

    Parameters

    +

    Parameters

    @@ -4414,7 +4693,7 @@

    Make Game Id

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

    -

    Parameters

    +

    Parameters

    @@ -4448,7 +4727,7 @@

    Make Auth Params

    Creates an AuthenticationParams object

    -

    Parameters

    +

    Parameters

    @@ -4494,7 +4773,7 @@

    Make Api Key

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

    -

    Parameters

    +

    Parameters

    @@ -4525,7 +4804,7 @@

    Get Value

    int32 GetValue(FModioErrorCode Error)
    -

    Parameters

    +

    Parameters

    @@ -4560,7 +4839,7 @@

    Get Message

    FString GetMessage(FModioErrorCode Error)
    -

    Parameters

    +

    Parameters

    @@ -4595,7 +4874,7 @@

    Error Code Matches

    Checks if the passed-in ErrorCode matches the specified error condition

    -

    Parameters

    +

    Parameters

    @@ -4637,7 +4916,7 @@

    List User Subscription Async

    Runs a filter over the user’s subscription list

    -

    Parameters

    +

    Parameters

    @@ -4752,7 +5031,7 @@

    Get Logo Size

    FVector2D GetLogoSize(UTexture* Logo, EModioLogoSize LogoSize)
    -

    Parameters

    +

    Parameters

    @@ -4791,7 +5070,7 @@

    Get Gallery Size

    FVector2D GetGallerySize(UTexture* GalleryImage, EModioGallerySize GallerySize)
    -

    Parameters

    +

    Parameters

    @@ -4830,7 +5109,7 @@

    Get Avatar Size

    FVector2D GetAvatarSize(UTexture* Avatar, EModioAvatarSize AvatarSize)
    -

    Parameters

    +

    Parameters

    @@ -4869,7 +5148,7 @@

    Get Path

    FString GetPath(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -4904,7 +5183,7 @@

    Get Mod State

    EModioModState GetModState(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -4939,7 +5218,7 @@

    Get Mod Profile

    FModioModInfo GetModProfile(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -4974,7 +5253,7 @@

    Get ID

    FModioModID GetID(FModioModCollectionEntry Entry)
    -

    Parameters

    +

    Parameters

    @@ -5012,7 +5291,7 @@

    Get Percent (integer64/integer64)

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

    -

    Parameters

    +

    Parameters

    @@ -5047,7 +5326,7 @@

    Is Valid Security Code Format

    bool IsValidSecurityCodeFormat(FString String)
    -

    Parameters

    +

    Parameters

    @@ -5082,7 +5361,7 @@

    Is Valid Email Address Format

    bool IsValidEmailAddressFormat(FString String)
    -

    Parameters

    +

    Parameters

    @@ -5173,7 +5452,7 @@

    ToString (Filesize)

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

    Parameters

    +

    Parameters

    @@ -5330,6 +5609,10 @@

    Values

    + + + +

    Updated

    Mod uninstallation from local storage

    Uploaded

    Mod local installation updated to latest version


    @@ -5932,7 +6215,7 @@

    Values

    diff --git a/Doc/img/nd_img_K2_GetModCreationHandle.png b/Doc/img/nd_img_K2_GetModCreationHandle.png new file mode 100644 index 00000000..64aa1302 Binary files /dev/null and b/Doc/img/nd_img_K2_GetModCreationHandle.png differ diff --git a/Doc/img/nd_img_K2_SubmitNewModAsync.png b/Doc/img/nd_img_K2_SubmitNewModAsync.png new file mode 100644 index 00000000..cccd75a3 Binary files /dev/null and b/Doc/img/nd_img_K2_SubmitNewModAsync.png differ diff --git a/Doc/img/nd_img_K2_SubmitNewModFileForMod.png b/Doc/img/nd_img_K2_SubmitNewModFileForMod.png new file mode 100644 index 00000000..a5f52e83 Binary files /dev/null and b/Doc/img/nd_img_K2_SubmitNewModFileForMod.png differ diff --git a/Source/Modio/GeneratedSource/ArchiveFileImplementation.cpp b/Source/Modio/GeneratedSource/ArchiveFileImplementation.cpp index 9e35edba..08f4e74d 100644 --- a/Source/Modio/GeneratedSource/ArchiveFileImplementation.cpp +++ b/Source/Modio/GeneratedSource/ArchiveFileImplementation.cpp @@ -1,31 +1,32 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io SDK. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #ifdef MODIO_SEPARATE_COMPILATION -#include "modio/detail/compression/zip/ArchiveFileImplementation.h" + #include "modio/detail/compression/zip/ArchiveFileImplementation.h" #endif namespace Modio { namespace Detail { - -void ArchiveFileImplementation::AddEntry(ArchiveEntry Entry) + void ArchiveFileImplementation::AddEntry(ArchiveEntry Entry) { ArchiveEntries.push_back(Entry); } -void ArchiveFileImplementation::AddEntry(std::string FileName, std::uintmax_t FileOffset, - std::uintmax_t CompressedSize, CompressionMethod Compression) + void ArchiveFileImplementation::AddEntry(std::string FileName, std::uintmax_t FileOffset, + std::uintmax_t CompressedSize, std::uintmax_t UncompressedSize, + CompressionMethod Compression, std::uint32_t CRCValue, bool bIsDirectory) { - ArchiveEntries.push_back(ArchiveEntry {Compression, FileName, FileOffset, CompressedSize}); + ArchiveEntries.push_back( + ArchiveEntry {Compression, FileName, FileOffset, CompressedSize, UncompressedSize, CRCValue, bIsDirectory}); } std::uintmax_t ArchiveFileImplementation::GetNumberOfEntries() @@ -44,5 +45,4 @@ void ArchiveFileImplementation::AddEntry(std::string FileName, std::uintmax_t Fi } } // namespace Detail -} - +} // namespace Modio diff --git a/Source/Modio/GeneratedSource/ModioFilterParams.cpp b/Source/Modio/GeneratedSource/ModioFilterParams.cpp index c22103ae..245cd93c 100644 --- a/Source/Modio/GeneratedSource/ModioFilterParams.cpp +++ b/Source/Modio/GeneratedSource/ModioFilterParams.cpp @@ -1,11 +1,11 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io SDK. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #ifdef MODIO_SEPARATE_COMPILATION @@ -72,8 +72,7 @@ namespace Modio Modio::FilterParams& FilterParams::WithTags(std::vector NewTags) { - Tags.clear(); - Tags.insert(Tags.end(), NewTags.begin(), NewTags.end()); + Tags = std::move(NewTags); return *this; } @@ -86,8 +85,7 @@ namespace Modio Modio::FilterParams& FilterParams::WithoutTags(std::vector NewTags) { - ExcludedTags.clear(); - ExcludedTags.insert(Tags.end(), NewTags.begin(), NewTags.end()); + ExcludedTags = std::move(NewTags); return *this; } @@ -98,6 +96,12 @@ namespace Modio return *this; } + Modio::FilterParams& Modio::FilterParams::MetadataLike(std::string SearchString) + { + MetadataBlobSearchString = SearchString; + return *this; + } + Modio::FilterParams& FilterParams::IndexedResults(std::size_t StartIndex, std::size_t ResultCount) { IsPaged = false; @@ -192,7 +196,7 @@ namespace Modio std::string TagStr; for (std::string Tag : Tags) { - TagStr += Tag + " "; + TagStr += Tag + ","; } TagStr.resize(TagStr.size() - 1); FilterFields.push_back(fmt::format("tags={}", TagStr)); @@ -203,12 +207,17 @@ namespace Modio std::string ExcludedTagStr; for (std::string Tag : ExcludedTags) { - ExcludedTagStr += Tag + " "; + ExcludedTagStr += Tag + ","; } ExcludedTagStr.resize(ExcludedTagStr.size() - 1); FilterFields.push_back(fmt::format("tags-not-in={}", ExcludedTagStr)); } + if (MetadataBlobSearchString) + { + FilterFields.push_back(fmt::format("metadata_blob-lk=*{}*", *MetadataBlobSearchString)); + } + std::string ResultLimitStr; if (IsPaged) { diff --git a/Source/Modio/GeneratedSource/ModioHttpParams.cpp b/Source/Modio/GeneratedSource/ModioHttpParams.cpp index 6676286e..9c9dba11 100644 --- a/Source/Modio/GeneratedSource/ModioHttpParams.cpp +++ b/Source/Modio/GeneratedSource/ModioHttpParams.cpp @@ -1,16 +1,18 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io SDK. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #ifdef MODIO_SEPARATE_COMPILATION #include "modio/http/ModioHttpParams.h" #endif + +#include "modio/core/ModioLogger.h" #include "modio/detail/FmtWrapper.h" #include "modio/detail/ModioSDKSessionData.h" @@ -18,6 +20,35 @@ namespace Modio { namespace Detail { + /// @brief Helper to construct payload content from a raw buffer + /// @param RawBuffer The buffer to submit + /// @return PayloadContent wrapping the buffer + MODIO_IMPL PayloadContent MakePayloadContent(Modio::Detail::Buffer RawBuffer) + { + return PayloadContent(std::move(RawBuffer)); + } + + /// @brief Helper to construct payload content referencing a file + /// @param PathToFile The path to the file that will be submitted + /// @return Optional payload content. Will be empty if the file doesn't exist or we could otherwise not retrieve + /// the file size + MODIO_IMPL Modio::Optional MakePayloadContent(Modio::filesystem::path PathToFile) + { + Modio::ErrorCode ec; + std::uintmax_t TmpSize = Modio::filesystem::file_size(PathToFile, ec); + if (!ec) + { + return PayloadContent(PathToFile, Modio::FileSize(TmpSize)); + } + else + { + Modio::Detail::Logger().Log(Modio::LogLevel::Error, Modio::LogCategory::File, + "Could not get size for file payload at {}, got error = {}", + PathToFile.generic_string(), ec.message()); + return {}; + } + } + Modio::Detail::HttpRequestParams& HttpRequestParams::SetGameID(Modio::GameID ID) { this->GameID = ID; @@ -31,13 +62,13 @@ namespace Modio return NewParamsInstance; } - Modio::Detail::HttpRequestParams& HttpRequestParams::SetModID(std::uint32_t ID) + Modio::Detail::HttpRequestParams& HttpRequestParams::SetModID(Modio::ModID ID) { ModID = ID; return *this; } - Modio::Detail::HttpRequestParams HttpRequestParams::SetModID(std::uint32_t ID) const + Modio::Detail::HttpRequestParams HttpRequestParams::SetModID(Modio::ModID ID) const { auto NewParamsInstance = HttpRequestParams(*this); NewParamsInstance.ModID = ID; @@ -69,24 +100,49 @@ namespace Modio return *this; } - Modio::Detail::HttpRequestParams HttpRequestParams::SetFilterString(const std::string& InFilterString) const + HttpRequestParams HttpRequestParams::SetFilterString(const std::string& InFilterString) const { auto NewParamsInstance = HttpRequestParams(*this); NewParamsInstance.SetFilterString(InFilterString); return NewParamsInstance; } - Modio::Detail::HttpRequestParams HttpRequestParams::AppendPayloadValue(std::string Key, std::string Value) const + HttpRequestParams HttpRequestParams::AppendPayloadValue(std::string Key, std::string Value) const { - auto NewParamsInstance = HttpRequestParams(*this); - if (NewParamsInstance.Payload.has_value()) + Modio::Detail::Buffer ValueBuffer(Value.length()); + std::copy(Value.begin(), Value.end(), ValueBuffer.begin()); + return AppendPayloadValue(Key, std::move(ValueBuffer)); + } + + HttpRequestParams HttpRequestParams::AppendPayloadValue(std::string Key, + Modio::Detail::Buffer RawPayloadBuffer) const + { + HttpRequestParams NewParamsInstance = HttpRequestParams(*this); + auto KeyIterator = NewParamsInstance.PayloadMembers.find(Key); + if (KeyIterator != NewParamsInstance.PayloadMembers.end()) { - *NewParamsInstance.Payload += "&" + Key + "=" + Value; + NewParamsInstance.PayloadMembers.erase(KeyIterator); } - else + NewParamsInstance.PayloadMembers.emplace(Key, MakePayloadContent(std::move(RawPayloadBuffer))); + return NewParamsInstance; + } + + HttpRequestParams HttpRequestParams::AppendPayloadFile(std::string Key, + Modio::filesystem::path PathToFileToUpload) const + { + HttpRequestParams NewParamsInstance = HttpRequestParams(*this); + Modio::Optional MaybePayload = MakePayloadContent(PathToFileToUpload); + if (MaybePayload) { - NewParamsInstance.Payload = Key + "=" + Value; + auto KeyIterator = NewParamsInstance.PayloadMembers.find(Key); + if (KeyIterator != NewParamsInstance.PayloadMembers.end()) + { + NewParamsInstance.PayloadMembers.erase(KeyIterator); + } + NewParamsInstance.PayloadMembers.emplace(Key, MaybePayload.value()); } + // Warning about null payload file will be emitted by MakePayloadContent, so we don't need to do it again + // here return NewParamsInstance; } @@ -178,9 +234,106 @@ namespace Modio return CurrentOperationType; } - const Modio::Optional& HttpRequestParams::GetPayload() const + bool HttpRequestParams::ContainsFormData() const + { + if (ContentType) + { + if (Modio::Detail::hash_64_fnv1a_const(ContentType->c_str()) == "multipart/form-data"_hash) + { + return true; + } + } + return false; + } + + const Modio::Optional HttpRequestParams::GetUrlEncodedPayload() const + { + // TODO: make this more performant by treating the mime type as a constant so we can do a early exit if we + // are using form-data + if (Modio::Detail::hash_64_fnv1a_const(ContentType->c_str()) != "application/x-www-form-urlencoded"_hash) + { + return {}; + } + std::string PayloadString; + for (auto& Entry : PayloadMembers) + { + if (Entry.second.RawBuffer) + { + if (PayloadString.length()) + { + PayloadString += "&"; + } + PayloadString += + Entry.first + "=" + std::string(Entry.second.RawBuffer->begin(), Entry.second.RawBuffer->end()); + } + else + { + // Notify the caller we're rejecting the call for a url encoded payload + Modio::Detail::Logger().Log( + Modio::LogLevel::Error, Modio::LogCategory::Http, + "Rejecting request for URLencoded payload because at least one payload parameter is a file {}", + Entry.second.PathToFile.value_or("").u8string()); + + return {}; + } + } + if (PayloadString.length()) + { + return PayloadString; + } + else + { + return {}; + } + } + + Modio::FileSize HttpRequestParams::GetPayloadSize() const + { + if (PayloadMembers.size() == 0) + { + return Modio::FileSize(0); + } + else + { + const std::string BoundaryString = + fmt::format("\r\n--{}\r\nContent-Disposition: form-data; name=\"\"\r\n\r\n", GetBoundaryHash()); + Modio::FileSize PayloadSize = Modio::FileSize(0); + for (auto& ContentElement : PayloadMembers) + { + // Length of the name + PayloadSize += Modio::FileSize(ContentElement.first.size()); + // Length of the data + PayloadSize += ContentElement.second.Size; + if (ContentElement.second.bIsFile) + { + PayloadSize += Modio::FileSize( + fmt::format("; filename=\"{}\"", ContentElement.second.PathToFile->filename().u8string()).size()); + } + // Length of the boundary string + PayloadSize += Modio::FileSize(BoundaryString.size()); + } + // Add final boundary string + const std::string FinalBoundaryString = fmt::format("\r\n--{}\r\n", GetBoundaryHash()); + PayloadSize += Modio::FileSize(FinalBoundaryString.size()); + return PayloadSize; + } + } + + Modio::Optional> HttpRequestParams:: + TakeNextPayloadElement() { - return Payload; + if (PayloadMembers.size()) + { + auto FirstElementIt = PayloadMembers.begin(); + Modio::Optional> FirstElement = + std::move(*FirstElementIt); + PayloadMembers.erase(FirstElementIt); + return FirstElement; + } + else + { + return {}; + } } Modio::Detail::HttpRequestParams::HeaderList HttpRequestParams::GetHeaders() const @@ -222,10 +375,22 @@ namespace Modio break; } - if (Payload || CurrentOperationType == Modio::Detail::Verb::POST || + /*if (Payload || CurrentOperationType == Modio::Detail::Verb::POST || CurrentOperationType == Modio::Detail::Verb::DELETE) { Headers.push_back({"Content-Type", "application/x-www-form-urlencoded"}); + }*/ + if (ContentType.has_value()) + { + if (ContainsFormData()) + { + Headers.push_back( + {"Content-Type", fmt::format("{}; boundary=\"{}\"", *ContentType, GetBoundaryHash())}); + } + else + { + Headers.push_back({"Content-Type", *ContentType}); + } } const Modio::Optional& AuthToken = GetAuthToken(); @@ -235,8 +400,9 @@ namespace Modio } if (StartOffset || EndOffset) { - Headers.push_back({"Range", fmt::format("bytes={}-{}", StartOffset ? StartOffset.value() : (std::uintmax_t) 0, - EndOffset ? fmt::format("{}", EndOffset.value()) : "")}); + Headers.push_back( + {"Range", fmt::format("bytes={}-{}", StartOffset ? StartOffset.value() : (std::uintmax_t) 0, + EndOffset ? fmt::format("{}", EndOffset.value()) : "")}); } if (OverrideLocale) { @@ -264,7 +430,7 @@ namespace Modio { HeaderString += fmt::format("{0}: {1}\r\n", CurrentHeader.first, CurrentHeader.second); } - auto CurrentPayloadString = GetPayload(); + auto CurrentPayloadString = GetUrlEncodedPayload(); if (CurrentPayloadString.has_value()) { if (bPerformURLEncoding) @@ -359,5 +525,67 @@ namespace Modio #ifdef MODIO_SEPARATE_COMPILATION HttpRequestParams InvalidParams; #endif + + PayloadContent::PayloadContent(const PayloadContent& Other) + + { + if (Other.bIsFile) + { + RawBuffer = {}; + PathToFile = Other.PathToFile; + } + else + { + RawBuffer = Other.RawBuffer.value().Clone(); + PathToFile = {}; + } + bIsFile = Other.bIsFile; + Size = Other.Size; + } + + PayloadContent::PayloadContent(Modio::Detail::Buffer InRawBuffer) + : RawBuffer(std::move(InRawBuffer)), + bIsFile(false) + { + Size = Modio::FileSize(this->RawBuffer->GetSize()); + } + + PayloadContent::PayloadContent(Modio::filesystem::path PathToFile, Modio::FileSize Size) + : PathToFile(PathToFile), + bIsFile(true), + Size(Size) + {} + + Modio::Detail::PayloadContent& PayloadContent::operator=(PayloadContent&& Other) + { + bIsFile = std::move(Other.bIsFile); + RawBuffer = std::move(Other.RawBuffer); + PathToFile = std::move(Other.PathToFile); + Size = std::move(Other.Size); + return *this; + } + + PayloadContent& PayloadContent::operator=(const PayloadContent& Other) + { + if (this == &Other) + { + return *this; + } + + if (Other.bIsFile) + { + RawBuffer = {}; + PathToFile = Other.PathToFile; + } + else + { + RawBuffer = Other.RawBuffer.value().Clone(); + PathToFile = {}; + } + bIsFile = Other.bIsFile; + Size = Other.Size; + return *this; + } + } // namespace Detail } // namespace Modio diff --git a/Source/Modio/GeneratedSource/ModioSDKSessionData.cpp b/Source/Modio/GeneratedSource/ModioSDKSessionData.cpp index e319d087..5cdb3aa9 100644 --- a/Source/Modio/GeneratedSource/ModioSDKSessionData.cpp +++ b/Source/Modio/GeneratedSource/ModioSDKSessionData.cpp @@ -1,11 +1,11 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io SDK. - * - * Distributed under the MIT License. (See accompanying file LICENSE or + * + * Distributed under the MIT License. (See accompanying file LICENSE or * view online at ) - * + * */ #ifdef MODIO_SEPARATE_COMPILATION @@ -14,6 +14,7 @@ #include "modio/core/ModioBuffer.h" #include "modio/core/ModioInitializeOptions.h" +#include "modio/core/ModioLogger.h" namespace Modio @@ -26,7 +27,7 @@ namespace Modio return Instance; } - MODIO_IMPL bool SDKSessionData::Initialize(const Modio::InitializeOptions& Options) + MODIO_IMPL bool SDKSessionData::Initialize(const Modio::InitializeOptions& Options) { // If we are already initializing or done with init, bail if (Get().CurrentInitializationState != InitializationState::NotInitialized) @@ -73,7 +74,7 @@ namespace Modio return Get().Environment; } - Modio::Portal SDKSessionData::GetPortal() + Modio::Portal SDKSessionData::GetPortal() { return Get().PortalInUse; } @@ -192,7 +193,6 @@ namespace Modio return Get().UserData.UserModDirectoryOverride; } - void SDKSessionData::SetUserModManagementCallback(std::function Callback) { Get().ModManagementEventCallback = Callback; @@ -214,22 +214,58 @@ namespace Modio return Get().EventLog; } - void SDKSessionData::SetLastValidationError(std::vector ExtendedErrorInformation) + void SDKSessionData::SetLastValidationError(std::vector ExtendedErrorInformation) { Get().LastValidationError = ExtendedErrorInformation; } - - std::vector SDKSessionData::GetLastValidationError() + std::vector SDKSessionData::GetLastValidationError() { return Get().LastValidationError; } - void SDKSessionData::ClearLastValidationError() + void SDKSessionData::ClearLastValidationError() { Get().LastValidationError.clear(); } + void SDKSessionData::AddPendingModfileUpload(Modio::ModID ID, Modio::CreateModFileParams Params) + { + if (Params.RootDirectory.has_filename()) + { + Params.RootDirectory /= ""; + Modio::Detail::Logger().Log( + Modio::LogLevel::Warning, Modio::LogCategory::ModManagement, + "Modfile directory path {} does not end in a path separator. Adding manually"); + } + + auto ExistingEntry = Get().PendingModUploads.find(ID); + if (ExistingEntry != Get().PendingModUploads.end()) + { + Modio::Detail::Logger().Log(Modio::LogLevel::Warning, Modio::LogCategory::ModManagement, + "New modfile upload queued for mod {} which already had a pending upload. " + "Dropping previous modfile upload request.", + ID); + Get().PendingModUploads.erase(ID); + } + Get().PendingModUploads.insert({ID, Params}); + } + + Modio::Optional> SDKSessionData:: + GetNextPendingModfileUpload() + { + if (Get().PendingModUploads.size()) + { + std::pair PendingUpload = *Get().PendingModUploads.begin(); + Get().PendingModUploads.erase(Get().PendingModUploads.begin()); + return PendingUpload; + } + else + { + return {}; + } + } + std::weak_ptr SDKSessionData::StartModDownloadOrUpdate(Modio::ModID ID) { if (Get().CurrentModInProgress != nullptr) @@ -273,6 +309,38 @@ namespace Modio } } + Modio::ModCreationHandle SDKSessionData::GetNextModCreationHandle() + { + if (Get().CreationHandles.size()) + { + Modio::ModCreationHandle NextHandle = Get().CreationHandles.rbegin()->first; + NextHandle += Modio::ModCreationHandle(1); + Get().CreationHandles.insert({NextHandle, {}}); + return NextHandle; + } + else + { + Modio::ModCreationHandle NextHandle = Modio::ModCreationHandle(0); + Get().CreationHandles.insert({NextHandle, {}}); + return NextHandle; + } + } + + Modio::Optional SDKSessionData::ResolveModCreationHandle(Modio::ModCreationHandle Handle) + { + return Get().CreationHandles.at(Handle); + } + + void SDKSessionData::LinkModCreationHandle(Modio::ModCreationHandle Handle, Modio::ModID ID) + { + if (Get().CreationHandles.find(Handle) != Get().CreationHandles.end()) + { + Modio::Detail::Logger().Log(Modio::LogLevel::Warning, Modio::LogCategory::ModManagement, + "Attempting to relink handle {} to mod id {}", Handle, ID); + } + Get().CreationHandles.insert({Handle, ID}); + } + SDKSessionData::SDKSessionData() {} SDKSessionData::SDKSessionData(const Modio::InitializeOptions& Options) diff --git a/Source/Modio/GeneratedSource/SDKModManagement.cpp b/Source/Modio/GeneratedSource/SDKModManagement.cpp index dcbb3565..825823d9 100644 --- a/Source/Modio/GeneratedSource/SDKModManagement.cpp +++ b/Source/Modio/GeneratedSource/SDKModManagement.cpp @@ -1,11 +1,11 @@ -/* +/* * Copyright (C) 2021 mod.io Pty Ltd. - * + * * This file is part of the mod.io SDK. - * - * 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 @@ -22,6 +22,8 @@ #include "modio/detail/ops/ModManagementLoop.h" #include "modio/detail/ops/SubscribeToModOp.h" #include "modio/detail/ops/UnsubscribeFromMod.h" +#include "modio/detail/ops/mod/SubmitNewModFileOp.h" +#include "modio/detail/ops/mod/SubmitNewModOp.h" #include "modio/detail/ops/modmanagement/ForceUninstallModOp.h" #include "modio/impl/SDKPreconditionChecks.h" #include "modio/userdata/ModioUserDataService.h" @@ -180,4 +182,36 @@ namespace Modio } } + void SubmitNewModAsync(Modio::ModCreationHandle Handle, Modio::CreateModParams Params, + std::function CreatedModID)> Callback) + { + if (Modio::Detail::RequireSDKIsInitialized(Callback) && Modio::Detail::RequireUserIsAuthenticated(Callback)) + { + if (Modio::Optional ResolvedID = + Modio::Detail::SDKSessionData::ResolveModCreationHandle(Handle)) + { + Modio::Detail::Logger().Log( + Modio::LogLevel::Warning, Modio::LogCategory::ModManagement, + "Attempted to call SubmitNewModAsync with an already-used handle. Returning existing Mod ID"); + asio::post(Modio::Detail::Services::GetGlobalContext().get_executor(), + [ID = ResolvedID.value(), Callback]() { Callback({}, ID); }); + return; + } + return Modio::Detail::SubmitNewModAsync(Handle, Params, Callback); + } + } + Modio::ModCreationHandle GetModCreationHandle() + { + return Modio::Detail::SDKSessionData::GetNextModCreationHandle(); + } + + MODIOSDK_API void SubmitNewModFileForMod(Modio::ModID Mod, Modio::CreateModFileParams Params) + { + //TODO: @modio-core we should return the error code from this function so we can do our precondition checks + Modio::Detail::SDKSessionData::AddPendingModfileUpload(Mod, Params); + + //(Modio::Detail::RequireSDKIsInitialized(Callback) && Modio::Detail::RequireUserIsAuthenticated(Callback)) && RequireModManagementEnabled + + } + } // namespace Modio diff --git a/Source/Modio/GeneratedSource/deflate_stream.cpp b/Source/Modio/GeneratedSource/deflate_stream.cpp index ebdf0491..5a0d175b 100644 --- a/Source/Modio/GeneratedSource/deflate_stream.cpp +++ b/Source/Modio/GeneratedSource/deflate_stream.cpp @@ -8,7 +8,6 @@ * */ -#if(0) //We don't currently create archives, this will be re-enabled later // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // @@ -48,20 +47,15 @@ #ifndef BOOST_BEAST_ZLIB_DETAIL_DEFLATE_STREAM_IPP #define BOOST_BEAST_ZLIB_DETAIL_DEFLATE_STREAM_IPP -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifdef MODIO_SEPARATE_COMPILATION +#include "modio/detail/compression/zlib/deflate_stream.hpp" +#endif + +#include "modio/detail/compression/zlib/detail/ranges.hpp" + #include #include -#include +#include namespace boost { namespace beast { @@ -142,7 +136,7 @@ gen_codes(ct_data *tree, int max_code, std::uint16_t *bl_count) } // Check that the bit counts in bl_count are consistent. // The last code must be all ones. - BOOST_ASSERT(code + bl_count[maxBits]-1 == (1< for(unsigned n = 0; n < run; ++n) tables.length_code[length++] = code; } - BOOST_ASSERT(length == 0); + assert(length == 0); // Note that the length 255 (match length 258) can be represented // in two different ways: code 284 + 5 bits or code 285, so we // overwrite length_code[255] to use the best encoding: @@ -191,7 +185,7 @@ deflate_stream::get_lut() -> for(unsigned n = 0; n < run; ++n) tables.dist_code[dist++] = code; } - BOOST_ASSERT(dist == 256); + assert(dist == 256); // from now on, all distances are divided by 128 dist >>= 7; for(; code < dCodes; ++code) @@ -201,7 +195,7 @@ deflate_stream::get_lut() -> for(std::size_t n = 0; n < run; ++n) tables.dist_code[256 + dist++] = code; } - BOOST_ASSERT(dist == 256); + assert(dist == 256); } // Construct the codes of the static literal tree @@ -253,15 +247,15 @@ doReset( windowBits = 9; if(level < 0 || level > 9) - BOOST_THROW_EXCEPTION(std::invalid_argument{ + throw(std::invalid_argument{ "invalid level"}); if(windowBits < 8 || windowBits > 15) - BOOST_THROW_EXCEPTION(std::invalid_argument{ + throw(std::invalid_argument{ "invalid windowBits"}); if(memLevel < 1 || memLevel > max_mem_level) - BOOST_THROW_EXCEPTION(std::invalid_argument{ + throw(std::invalid_argument{ "invalid memLevel"}); w_bits_ = windowBits; @@ -330,7 +324,7 @@ doTune( void deflate_stream:: -doParams(z_params& zs, int level, Strategy strategy, error_code& ec) +doParams(z_params& zs, int level, Strategy strategy, Modio::ErrorCode& ec) { compress_func func; @@ -338,7 +332,7 @@ doParams(z_params& zs, int level, Strategy strategy, error_code& ec) level = 6; if(level < 0 || level > 9) { - ec = error::stream_error; + ec = Modio::make_error_code(Modio::ZlibError::StreamError); return; } func = get_config(level_).func; @@ -348,7 +342,7 @@ doParams(z_params& zs, int level, Strategy strategy, error_code& ec) { // Flush the last buffer: doWrite(zs, Flush::block, ec); - if(ec == error::need_buffers && pending_ == 0) + if(ec == Modio::ZlibError::NeedBuffers && pending_ == 0) ec = {}; } if(level_ != level) @@ -362,32 +356,31 @@ doParams(z_params& zs, int level, Strategy strategy, error_code& ec) strategy_ = strategy; } -// VFALCO boost::optional param is a workaround for +// VFALCO Modio::Optional param is a workaround for // gcc "maybe uninitialized" warning // https://github.com/boostorg/beast/issues/532 // void deflate_stream:: -doWrite(z_params& zs, boost::optional flush, error_code& ec) +doWrite(z_params& zs, Modio::Optional flush, Modio::ErrorCode& ec) { maybe_init(); if(zs.next_out == 0 || (zs.next_in == 0 && zs.avail_in != 0) || (status_ == FINISH_STATE && flush != Flush::finish)) { - ec = error::stream_error; + ec = Modio::make_error_code(Modio::ZlibError::StreamError); return; } if(zs.avail_out == 0) { - ec = error::need_buffers; + ec = Modio::make_error_code(Modio::ZlibError::NeedBuffers); return; } // value of flush param for previous deflate call - auto old_flush = boost::make_optional( - last_flush_.is_initialized(), - last_flush_ ? *last_flush_ : Flush::none); + auto old_flush = Modio::Optional { + last_flush_ ? *last_flush_ : Flush::none}; last_flush_ = flush; @@ -403,7 +396,7 @@ doWrite(z_params& zs, boost::optional flush, error_code& ec) * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ - last_flush_ = boost::none; + last_flush_ = boost::beast::zlib::Flush::none; return; } } @@ -415,14 +408,14 @@ doWrite(z_params& zs, boost::optional flush, error_code& ec) * flushes. For repeated and useless calls with Flush::finish, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ - ec = error::need_buffers; + ec = Modio::make_error_code(Modio::ZlibError::NeedBuffers); return; } // User must not provide more input after the first FINISH: if(status_ == FINISH_STATE && zs.avail_in != 0) { - ec = error::need_buffers; + ec = Modio::make_error_code(Modio::ZlibError::NeedBuffers); return; } @@ -436,14 +429,14 @@ doWrite(z_params& zs, boost::optional flush, error_code& ec) switch(strategy_) { case Strategy::huffman: - bstate = deflate_huff(zs, flush.get()); + bstate = deflate_huff(zs, flush.value()); break; case Strategy::rle: - bstate = deflate_rle(zs, flush.get()); + bstate = deflate_rle(zs, flush.value()); break; default: { - bstate = (this->*(get_config(level_).func))(zs, flush.get()); + bstate = (this->*(get_config(level_).func))(zs, flush.value()); break; } } @@ -456,7 +449,7 @@ doWrite(z_params& zs, boost::optional flush, error_code& ec) { if(zs.avail_out == 0) { - last_flush_ = boost::none; /* avoid BUF_ERROR next call, see above */ + last_flush_ = boost::beast::zlib::Flush::none; /* avoid BUF_ERROR next call, see above */ } return; /* If flush != Flush::none && avail_out == 0, the next call @@ -494,7 +487,7 @@ doWrite(z_params& zs, boost::optional flush, error_code& ec) flush_pending(zs); if(zs.avail_out == 0) { - last_flush_ = boost::none; /* avoid BUF_ERROR at next call, see above */ + last_flush_ = boost::beast::zlib::Flush::none; /* avoid BUF_ERROR at next call, see above */ return; } } @@ -502,7 +495,7 @@ doWrite(z_params& zs, boost::optional flush, error_code& ec) if(flush == Flush::finish) { - ec = error::end_of_stream; + ec = Modio::make_error_code(Modio::ZlibError::EndOfStream); return; } } @@ -510,11 +503,11 @@ doWrite(z_params& zs, boost::optional flush, error_code& ec) // VFALCO Warning: untested void deflate_stream:: -doDictionary(Byte const* dict, uInt dictLength, error_code& ec) +doDictionary(Byte const* dict, uInt dictLength, Modio::ErrorCode& ec) { if(lookahead_) { - ec = error::stream_error; + ec = Modio::make_error_code(Modio::ZlibError::StreamError); return; } @@ -564,13 +557,13 @@ doDictionary(Byte const* dict, uInt dictLength, error_code& ec) void deflate_stream:: -doPrime(int bits, int value, error_code& ec) +doPrime(int bits, int value, Modio::ErrorCode& ec) { maybe_init(); if((Byte *)(d_buf_) < pending_out_ + ((Buf_size + 7) >> 3)) { - ec = error::need_buffers; + ec = Modio::make_error_code(Modio::ZlibError::NeedBuffers); return; } @@ -627,7 +620,7 @@ init() if(! buf_ || buf_size_ != needed) { - buf_ = boost::make_unique_noinit< + buf_ = std::make_unique< std::uint8_t[]>(needed); buf_size_ = needed; } @@ -960,7 +953,7 @@ scan_tree( { int n; // iterates over all tree elements int prevlen = -1; // last emitted length - int curlen; // length of current code + int curlen = 0; // length of current code int nextlen = tree[0].dl; // length of next code std::uint16_t count = 0; // repeat count of the current code int max_count = 7; // max repeat count @@ -1064,7 +1057,7 @@ send_tree( send_code(curlen, bl_tree_); count--; } - BOOST_ASSERT(count >= 3 && count <= 6); + assert(count >= 3 && count <= 6); send_code(REP_3_6, bl_tree_); send_bits(count-3, 2); } @@ -1145,8 +1138,8 @@ send_all_trees( { int rank; // index in bl_order - BOOST_ASSERT(lcodes >= 257 && dcodes >= 1 && blcodes >= 4); - BOOST_ASSERT(lcodes <= lCodes && dcodes <= dCodes && blcodes <= blCodes); + assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4); + assert(lcodes <= lCodes && dcodes <= dCodes && blcodes <= blCodes); send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt send_bits(dcodes-1, 5); send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt @@ -1193,7 +1186,7 @@ compress_block( } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); - BOOST_ASSERT(code < dCodes); + assert(code < dCodes); send_code(code, dtree); /* send the distance code */ extra = lut_.extra_dbits[code]; @@ -1205,7 +1198,7 @@ compress_block( } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - BOOST_ASSERT((uInt)(pending_) < lit_bufsize_ + 2*lx); + assert((uInt)(pending_) < lit_bufsize_ + 2*lx); } while(lx < last_lit_); } @@ -1442,7 +1435,7 @@ tr_flush_block( // https://github.com/madler/zlib/issues/172 #if 0 - BOOST_ASSERT(buf); + assert(buf); #endif opt_lenb = static_lenb = stored_len + 5; // force a stored block } @@ -1741,7 +1734,7 @@ longest_match(IPos cur_match) /* The code is optimized for HASH_BITS >= 8 and maxMatch-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ - BOOST_ASSERT(hash_bits_ >= 8 && maxMatch == 258); + assert(hash_bits_ >= 8 && maxMatch == 258); /* Do not waste too much time if we already have a good match: */ if(prev_length_ >= good_match_) { @@ -1753,10 +1746,10 @@ longest_match(IPos cur_match) if((uInt)nice_match > lookahead_) nice_match = lookahead_; - BOOST_ASSERT((std::uint32_t)strstart_ <= window_size_-kMinLookahead); + assert((std::uint32_t)strstart_ <= window_size_-kMinLookahead); do { - BOOST_ASSERT(cur_match < strstart_); + assert(cur_match < strstart_); match = window_ + cur_match; /* Skip to next match if the match length cannot increase @@ -1780,7 +1773,7 @@ longest_match(IPos cur_match) * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; - BOOST_ASSERT(*scan == *match); + assert(*scan == *match); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. @@ -1794,7 +1787,7 @@ longest_match(IPos cur_match) *++scan == *++match && *++scan == *++match && scan < strend); - BOOST_ASSERT(scan <= window_+(unsigned)(window_size_-1)); + assert(scan <= window_+(unsigned)(window_size_-1)); len = maxMatch - (int)(strend - scan); scan = strend - maxMatch; @@ -1845,7 +1838,7 @@ f_stored(z_params& zs, Flush flush) -> /* Fill the window as much as possible: */ if(lookahead_ <= 1) { - BOOST_ASSERT(strstart_ < w_size_+max_dist() || + assert(strstart_ < w_size_+max_dist() || block_start_ >= (long)w_size_); fill_window(zs); @@ -1854,7 +1847,7 @@ f_stored(z_params& zs, Flush flush) -> if(lookahead_ == 0) break; /* flush the current block */ } - BOOST_ASSERT(block_start_ >= 0L); + assert(block_start_ >= 0L); strstart_ += lookahead_; lookahead_ = 0; @@ -2132,7 +2125,7 @@ f_slow(z_params& zs, Flush flush) -> lookahead_--; } } - BOOST_ASSERT(flush != Flush::none); + assert(flush != Flush::none); if(match_available_) { tr_tally_lit(window_[strstart_-1], bflush); @@ -2199,7 +2192,7 @@ f_rle(z_params& zs, Flush flush) -> if(match_length_ > lookahead_) match_length_ = lookahead_; } - BOOST_ASSERT(scan <= window_+(uInt)(window_size_-1)); + assert(scan <= window_+(uInt)(window_size_-1)); } /* Emit match if have run of minMatch or longer, else emit literal */ @@ -2301,4 +2294,3 @@ f_huff(z_params& zs, Flush flush) -> } // boost #endif -#endif \ No newline at end of file diff --git a/Source/Modio/GeneratedSource/inflate_stream.cpp b/Source/Modio/GeneratedSource/inflate_stream.cpp index cbe77b46..f5f5f8cd 100644 --- a/Source/Modio/GeneratedSource/inflate_stream.cpp +++ b/Source/Modio/GeneratedSource/inflate_stream.cpp @@ -47,7 +47,10 @@ #ifndef BOOST_BEAST_ZLIB_DETAIL_INFLATE_STREAM_IPP #define BOOST_BEAST_ZLIB_DETAIL_INFLATE_STREAM_IPP -#include "modio/compression/zlib/detail/inflate_stream.hpp" +#ifdef MODIO_SEPARATE_COMPILATION +#include "modio/detail/compression/zlib/detail/inflate_stream.hpp" +#endif + #include "modio/core/ModioErrorCode.h" #include diff --git a/Source/Modio/Modio.Build.cs b/Source/Modio/Modio.Build.cs index c9cd72d5..492138f4 100644 --- a/Source/Modio/Modio.Build.cs +++ b/Source/Modio/Modio.Build.cs @@ -25,26 +25,31 @@ public Modio(ReadOnlyTargetRules Target) : base(Target) //Add stub generated header { string GeneratedHeaderPath = Path.Combine(ModuleDirectory, "GeneratedHeader"); - //Clean the generated source directory so that we dont have any stale files in it - if (Directory.Exists(GeneratedHeaderPath)) + + // Only process generated headers if we are using the NativeSDK as a git submodule + if (File.Exists(Path.Combine(ModuleDirectory, "../ThirdParty/NativeSDK/.git"))) { - Directory.Delete(GeneratedHeaderPath, true); + //Clean the generated source directory so that we dont have any stale files in it + if (Directory.Exists(GeneratedHeaderPath)) + { + Directory.Delete(GeneratedHeaderPath, true); + } + Directory.CreateDirectory(GeneratedHeaderPath); + + Directory.CreateDirectory(Path.Combine(GeneratedHeaderPath, "Public")); + Directory.CreateDirectory(Path.Combine(GeneratedHeaderPath, "Private")); + + //Because this file is a dummy we don't need it as a dependency + string GeneratedHeaderFilePath = Path.Combine(GeneratedHeaderPath, "Private", "ModioGeneratedVariables.h"); + using (StreamWriter DummyGeneratedHeader = File.AppendText(GeneratedHeaderFilePath)) + { }; + + // Silly hack/workaround until 4.26 adds ConditionalAddModuleDirectory - we may change where this lives in the native SDK later + string ErrorConditionLibraryPath = Path.Combine(ModuleDirectory, "../ThirdParty/NativeSDK/modio/modio/core/ModioErrorCondition.h"); + // Add dependency on the upstream file so if it is modified we re-run and copy it again + ExternalDependencies.Add(ErrorConditionLibraryPath); + File.Copy(ErrorConditionLibraryPath, Path.Combine(GeneratedHeaderPath, "Public", "ModioErrorCondition.h"), true); } - Directory.CreateDirectory(GeneratedHeaderPath); - - Directory.CreateDirectory(Path.Combine(GeneratedHeaderPath, "Public")); - Directory.CreateDirectory(Path.Combine(GeneratedHeaderPath, "Private")); - - //Because this file is a dummy we don't need it as a dependency - string GeneratedHeaderFilePath = Path.Combine(GeneratedHeaderPath, "Private", "ModioGeneratedVariables.h"); - using (StreamWriter DummyGeneratedHeader = File.AppendText(GeneratedHeaderFilePath)) - { }; - - // Silly hack/workaround until 4.26 adds ConditionalAddModuleDirectory - we may change where this lives in the native SDK later - string ErrorConditionLibraryPath = Path.Combine(ModuleDirectory, "../ThirdParty/NativeSDK/modio/modio/core/ModioErrorCondition.h"); - // Add dependency on the upstream file so if it is modified we re-run and copy it again - ExternalDependencies.Add(ErrorConditionLibraryPath); - File.Copy(ErrorConditionLibraryPath, Path.Combine(GeneratedHeaderPath, "Public", "ModioErrorCondition.h"), true); PublicIncludePaths.AddRange(new string[] { @@ -73,6 +78,9 @@ public Modio(ReadOnlyTargetRules Target) : base(Target) } // Add native SDK implementation to this module so we don't have to create an extraneous module // TODO: @modio-ue4 cleanup by using UE_4_26_OR_LATER so we can use ConditionalAddModuleDirectory + + // We only need to check and update generated source if we are consuming the NativeSDK as a git submodule (ie we aren't in a standalone release context) + if (File.Exists(Path.Combine(ModuleDirectory, "../ThirdParty/NativeSDK/.git"))) { string GeneratedSourcePath = Path.Combine(ModuleDirectory, "GeneratedSource"); diff --git a/Source/Modio/Private/Internal/Convert/AuthParams.h b/Source/Modio/Private/Internal/Convert/AuthParams.h index 76d433d1..956c82e2 100644 --- a/Source/Modio/Private/Internal/Convert/AuthParams.h +++ b/Source/Modio/Private/Internal/Convert/AuthParams.h @@ -45,8 +45,8 @@ MODIO_END_CONVERT_SWITCHES FORCEINLINE Modio::AuthenticationParams ToModio(const FModioAuthenticationParams& UnrealParams) { Modio::AuthenticationParams Params; - Params.AuthToken = ToSTD(FGenericPlatformHttp::UrlEncode(UnrealParams.AuthToken)); - Params.UserEmail = UnrealParams.UserEmail.TrimStartAndEnd().IsEmpty() ? Modio::Optional(ToSTD(UnrealParams.UserEmail)) : Modio::Optional(); + Params.AuthToken = ToModio(FGenericPlatformHttp::UrlEncode(UnrealParams.AuthToken)); + Params.UserEmail = UnrealParams.UserEmail.TrimStartAndEnd().IsEmpty() ? Modio::Optional(ToModio(UnrealParams.UserEmail)) : Modio::Optional(); Params.bUserHasAcceptedTerms = UnrealParams.bUserHasAcceptedTerms; return Params; diff --git a/Source/Modio/Private/Internal/Convert/CreateModFileParams.h b/Source/Modio/Private/Internal/Convert/CreateModFileParams.h new file mode 100644 index 00000000..f9d908d4 --- /dev/null +++ b/Source/Modio/Private/Internal/Convert/CreateModFileParams.h @@ -0,0 +1,26 @@ +/* + * 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 "Internal/Convert/Optional.h" +#include "Internal/ModioConvert.h" +#include "ModioSDK.h" +#include "Types/ModioCreateModFileParams.h" + +FORCEINLINE Modio::CreateModFileParams ToModio(const FModioCreateModFileParams& In) +{ + Modio::CreateModFileParams Out; + Out.RootDirectory = ToModio(In.PathToModRootDirectory); + Out.Version = ToModioOptional(In.VersionString); + Out.Changelog = ToModioOptional(In.Changelog); + Out.bSetAsActive = ToModioOptional(In.bSetAsActiveRelease); + Out.MetadataBlob = ToModioOptional(In.MetadataBlob); + return Out; +} \ No newline at end of file diff --git a/Source/Modio/Private/Internal/Convert/CreateModParams.h b/Source/Modio/Private/Internal/Convert/CreateModParams.h new file mode 100644 index 00000000..b6be0b85 --- /dev/null +++ b/Source/Modio/Private/Internal/Convert/CreateModParams.h @@ -0,0 +1,33 @@ +/* + * 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 "Internal/Convert/Optional.h" +#include "Internal/Convert/Numerics.h" +#include "Internal/ModioConvert.h" +#include "ModioSDK.h" +#include "Types/ModioCreateModParams.h" + +FORCEINLINE Modio::CreateModParams ToModio(const FModioCreateModParams& In) +{ + Modio::CreateModParams Out; + Out.PathToLogoFile = ToModio(In.PathToLogoFile); + Out.Name = ToModio(In.Name); + Out.Summary = ToModio(In.Summary); + Out.NamePath = ToModioOptional(In.NamePath); + Out.bVisible = ToModioOptional(In.bVisible); + Out.Description = ToModioOptional(In.Description); + Out.HomepageURL = ToModioOptional(In.HomepageURL); + Out.Stock = ToModioOptional(In.QuantityAvailable); + Out.MaturityRating = In.MaturityFlags.IsSet() ? static_cast(In.MaturityFlags.GetValue()): Modio::Optional{}; + Out.MetadataBlob = ToModioOptional(In.MetadataBlob); + Out.Tags = ToModioOptional>(In.Tags); + 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 73b6d5a2..a1998e6f 100644 --- a/Source/Modio/Private/Internal/Convert/FilterParams.h +++ b/Source/Modio/Private/Internal/Convert/FilterParams.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 @@ -50,34 +50,38 @@ FORCEINLINE Modio::FilterParams::SortFieldType ToModio(EModioSortFieldType Envir } MODIO_END_CONVERT_SWITCHES -FORCEINLINE Modio::FilterParams ToModio(const FModioFilterParams& In ) +FORCEINLINE Modio::FilterParams ToModio(const FModioFilterParams& In) { + Modio::FilterParams Out; + + if (In.isPaged) + { + Out.PagedResults(In.Index, In.Count); + } + else + { + Out.IndexedResults(In.Index, In.Count); + } - Modio::FilterParams Out; - - if (In.isPaged) - { - Out.PagedResults(In.Index,In.Count); - } - else - { - Out.IndexedResults(In.Index,In.Count); - } - if (In.DateRangeBegin) { - Out.MarkedLiveAfter(ToSTD(In.DateRangeBegin.GetValue())); + Out.MarkedLiveAfter(ToModio(In.DateRangeBegin.GetValue())); } - + if (In.DateRangeEnd) { - Out.MarkedLiveBefore(ToSTD(In.DateRangeEnd.GetValue())); + Out.MarkedLiveBefore(ToModio(In.DateRangeEnd.GetValue())); + } + + if (In.MetadataBlobSearchString.IsSet()) + { + Out.MetadataLike(ToModio(In.MetadataBlobSearchString.GetValue())); } - return Out.SortBy(ToModio(In.SortField), ToModio(In.Direction)) - .NameContains(ToSTD(In.SearchKeywords)) - .MatchingIDs(ToModio(In.IncludedIDs)) - .ExcludingIDs(ToModio(In.ExcludedIDs)) - .WithTags(ToSTD(In.Tags)) - .WithoutTags(ToSTD(In.ExcludedTags)); + return Out.SortBy(ToModio(In.SortField), ToModio(In.Direction)) + .NameContains(ToModio(In.SearchKeywords)) + .MatchingIDs(ToModio(In.IncludedIDs)) + .ExcludingIDs(ToModio(In.ExcludedIDs)) + .WithTags(ToModio(In.Tags)) + .WithoutTags(ToModio(In.ExcludedTags)); } \ No newline at end of file diff --git a/Source/Modio/Private/Internal/Convert/ModCreationHandle.h b/Source/Modio/Private/Internal/Convert/ModCreationHandle.h new file mode 100644 index 00000000..3dd02fd2 --- /dev/null +++ b/Source/Modio/Private/Internal/Convert/ModCreationHandle.h @@ -0,0 +1,26 @@ +/* + * 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 "Internal/ModioConvert.h" +#include "ModioSDK.h" +#include "Types/ModioModCreationHandle.h" + +FORCEINLINE FModioModCreationHandle ToUnreal(const Modio::ModCreationHandle& In) +{ + FModioModCreationHandle Out; + Out.Underlying = ToUnreal(*In); + return Out; +} + +FORCEINLINE Modio::ModCreationHandle ToModio(const FModioModCreationHandle& In) +{ + return Modio::ModCreationHandle(In.Underlying); +} \ No newline at end of file diff --git a/Source/Modio/Private/Internal/Convert/ModManagementEvent.h b/Source/Modio/Private/Internal/Convert/ModManagementEvent.h index 18613971..3a573315 100644 --- a/Source/Modio/Private/Internal/Convert/ModManagementEvent.h +++ b/Source/Modio/Private/Internal/Convert/ModManagementEvent.h @@ -26,6 +26,8 @@ FORCEINLINE EModioModManagementEventType ToUnreal(Modio::ModManagementEvent::Eve return EModioModManagementEventType::Uninstalled; case Modio::ModManagementEvent::EventType::Updated: return EModioModManagementEventType::Updated; + case Modio::ModManagementEvent::EventType::Uploaded: + return EModioModManagementEventType::Uploaded; } checkf(false, TEXT("Missed a case in ToModio(EModioEnvironment Environment)")); diff --git a/Source/Modio/Private/Internal/Convert/Numerics.h b/Source/Modio/Private/Internal/Convert/Numerics.h new file mode 100644 index 00000000..0bc8a744 --- /dev/null +++ b/Source/Modio/Private/Internal/Convert/Numerics.h @@ -0,0 +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 + * view online at ) + * + */ + +#pragma once +#include + +FORCEINLINE std::uint8_t ToModio(const uint8& In) +{ + return static_cast(In); +} + +FORCEINLINE uint8 ToUnreal(const std::uint8_t& In) +{ + return static_cast(In); +} \ No newline at end of file diff --git a/Source/Modio/Private/Internal/Convert/Optional.h b/Source/Modio/Private/Internal/Convert/Optional.h new file mode 100644 index 00000000..3237f956 --- /dev/null +++ b/Source/Modio/Private/Internal/Convert/Optional.h @@ -0,0 +1,42 @@ +/* + * 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 "Internal/ModioConvert.h" +#include "ModioSDK.h" +#include "Types/ModioCreateModParams.h" +#include "Templates/EnableIf.h" + +template +FORCEINLINE typename TEnableIf>::Value, typename Modio::Optional>::Type ToModioOptional(const TOptional& In) +{ + if (In.IsSet()) + { + return ToModio((SourceType) In.GetValue()); + } + else + { + return {}; + } +} + +template +FORCEINLINE typename TEnableIf::Value, typename Modio::Optional>::Type ToModioOptional(const TOptional& In) +{ + if (In.IsSet()) + { + return In.GetValue(); + } + else + { + return {}; + } +} \ No newline at end of file diff --git a/Source/Modio/Private/Internal/Convert/ReportParams.h b/Source/Modio/Private/Internal/Convert/ReportParams.h index 99ce9288..26bc5776 100644 --- a/Source/Modio/Private/Internal/Convert/ReportParams.h +++ b/Source/Modio/Private/Internal/Convert/ReportParams.h @@ -25,26 +25,26 @@ FORCEINLINE Modio::ReportParams ToModio(const FModioReportParams& In) if (In.ReporterName && !In.ReporterName->TrimStartAndEnd().IsEmpty()) { - ReporterName = ToSTD(In.ReporterName.GetValue()); + ReporterName = ToModio(In.ReporterName.GetValue()); } if (In.ReporterContact && !In.ReporterContact->TrimStartAndEnd().IsEmpty()) { - ReporterContact = ToSTD(In.ReporterContact.GetValue()); + ReporterContact = ToModio(In.ReporterContact.GetValue()); } switch (In.ReportedResourceType) { case FModioReportParams::ResourceType::Game: - return Modio::ReportParams(Modio::GameID(In.ResourceID), ToModio(In.Type), ToSTD(In.ReportDescription), + return Modio::ReportParams(Modio::GameID(In.ResourceID), ToModio(In.Type), ToModio(In.ReportDescription), ReporterName, ReporterContact); break; case FModioReportParams::ResourceType::Mod: - return Modio::ReportParams(Modio::ModID(In.ResourceID), ToModio(In.Type), ToSTD(In.ReportDescription), + return Modio::ReportParams(Modio::ModID(In.ResourceID), ToModio(In.Type), ToModio(In.ReportDescription), ReporterName, ReporterContact); break; case FModioReportParams::ResourceType::User: - return Modio::ReportParams(Modio::UserID(In.ResourceID), ToModio(In.Type), ToSTD(In.ReportDescription), + return Modio::ReportParams(Modio::UserID(In.ResourceID), ToModio(In.Type), ToModio(In.ReportDescription), ReporterName, ReporterContact); break; } diff --git a/Source/Modio/Private/Internal/ModioConvert.h b/Source/Modio/Private/Internal/ModioConvert.h index 07f7f21e..53bad06b 100644 --- a/Source/Modio/Private/Internal/ModioConvert.h +++ b/Source/Modio/Private/Internal/ModioConvert.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 @@ -21,14 +21,11 @@ #include #include -FORCEINLINE std::string ToSTD(const FString& String); -FORCEINLINE std::vector ToSTD(const TArray& StringArray); -FORCEINLINE std::chrono::system_clock::time_point ToSTD(FDateTime Time); - -// @todo: Make a ToModio that handles TOptional through templates +FORCEINLINE std::string ToModio(const FString& String); +FORCEINLINE std::vector ToModio(const TArray& StringArray); +FORCEINLINE std::chrono::system_clock::time_point ToModio(FDateTime Time); FORCEINLINE int64 ToUnreal(std::int64_t Value); -FORCEINLINE uint8 ToUnreal(std::uint8_t Value); FORCEINLINE double ToUnreal(double Value); FORCEINLINE bool ToUnreal(bool Value); FORCEINLINE uint64 ToUnreal(std::size_t Value); @@ -58,15 +55,13 @@ FORCEINLINE Modio::UserID ToModio(const FModioUserID& In); #pragma region Implementation - // @todo: Rename this to ToModio as it doesn't matter that it's the part of STD of modio -FORCEINLINE std::string ToSTD(const FString& String) +FORCEINLINE std::string ToModio(const FString& String) { return std::string(TCHAR_TO_UTF8(*String)); } -// @todo: Rename this to ToModio as it doesn't matter that it's the part of STD of modio -FORCEINLINE std::vector ToSTD(const TArray& StringArray) +FORCEINLINE std::vector ToModio(const TArray& StringArray) { std::vector Result; Result.reserve(StringArray.Num()); @@ -77,10 +72,8 @@ FORCEINLINE std::vector ToSTD(const TArray& StringArray) return Result; } -// @todo: Rename this to ToModio as it doesn't matter that it's the part of STD of modio -FORCEINLINE std::chrono::system_clock::time_point ToSTD(FDateTime Time) +FORCEINLINE std::chrono::system_clock::time_point ToModio(FDateTime Time) { - // @todonow: Verify that this becomes correct by printf debugging return std::chrono::system_clock::time_point(std::chrono::system_clock::duration(Time.ToUnixTimestamp())); } @@ -94,11 +87,6 @@ FORCEINLINE bool ToUnreal(bool Value) return Value; } -FORCEINLINE uint8 ToUnreal(std::uint8_t Value) -{ - return Value; -} - FORCEINLINE double ToUnreal(double Value) { return Value; @@ -390,5 +378,4 @@ typename TEnableIf>::Va return static_cast(Flags.RawValue()); } - #pragma endregion diff --git a/Source/Modio/Private/Libraries/ModioFilterParamsLibrary.cpp b/Source/Modio/Private/Libraries/ModioFilterParamsLibrary.cpp index 3a64591c..0b3a25b6 100644 --- a/Source/Modio/Private/Libraries/ModioFilterParamsLibrary.cpp +++ b/Source/Modio/Private/Libraries/ModioFilterParamsLibrary.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/ModioFilterParamsLibrary.h" @@ -67,3 +67,8 @@ FModioFilterParams& UModioFilterParamsLibrary::PagedResults(FModioFilterParams& { return Filter.PagedResults(PageNumber, PageSize); } + +FModioFilterParams& UModioFilterParamsLibrary::MetadataLike(FModioFilterParams& Filter, FString SearchString) +{ + return Filter.MetadataLike(SearchString); +} diff --git a/Source/Modio/Private/Libraries/ModioOptionalLibrary.cpp b/Source/Modio/Private/Libraries/ModioOptionalLibrary.cpp index aa96c8f3..91bb3853 100644 --- a/Source/Modio/Private/Libraries/ModioOptionalLibrary.cpp +++ b/Source/Modio/Private/Libraries/ModioOptionalLibrary.cpp @@ -122,3 +122,14 @@ bool UModioOptionalLibrary::GetValue_ModioOptionalModDependencyList( { return GetValueInternal(OptionalDependencyList, DependencyList); } + +bool UModioOptionalLibrary::IsSet_ModioOptionalModID(const struct FModioOptionalModID& OptionalID) +{ + return IsSetInternal(OptionalID); +} + +bool UModioOptionalLibrary::GetValue_ModioOptionalModID(const struct FModioOptionalModID& OptionalID, + struct FModioModID& ID) +{ + return GetValueInternal(OptionalID, ID); +} diff --git a/Source/Modio/Private/ModioSubsystem.cpp b/Source/Modio/Private/ModioSubsystem.cpp index cb6fc702..c1dfdcb2 100644 --- a/Source/Modio/Private/ModioSubsystem.cpp +++ b/Source/Modio/Private/ModioSubsystem.cpp @@ -11,11 +11,14 @@ #include "ModioSubsystem.h" #include "Engine/Engine.h" #include "Internal/Convert/AuthParams.h" +#include "Internal/Convert/CreateModFileParams.h" +#include "Internal/Convert/CreateModParams.h" #include "Internal/Convert/ErrorCode.h" #include "Internal/Convert/FilterParams.h" #include "Internal/Convert/InitializeOptions.h" #include "Internal/Convert/List.h" #include "Internal/Convert/ModCollectionEntry.h" +#include "Internal/Convert/ModCreationHandle.h" #include "Internal/Convert/ModDependency.h" #include "Internal/Convert/ModInfo.h" #include "Internal/Convert/ModInfoList.h" @@ -354,7 +357,8 @@ void UModioSubsystem::GetModTagOptionsAsync(FOnGetModTagOptionsDelegateFast Call Callback.ExecuteIfBound({}, CachedModTags); return; } - + // TODO: @modio-UE4 capturing `this` is bad and we shouldn't do it. Better to store the cached tags as a TSharedPtr + // and capture that by value, so we are guaranteed lifetime Modio::GetModTagOptionsAsync( [this, Callback](Modio::ErrorCode ec, Modio::Optional ModTagOptions) { CachedModTags = ToUnrealOptional(ModTagOptions); @@ -370,6 +374,15 @@ void UModioSubsystem::K2_GetModTagOptionsAsync(FOnGetModTagOptionsDelegate Callb })); } +void UModioSubsystem::SubmitNewModAsync(FModioModCreationHandle Handle, FModioCreateModParams Params, + FOnSubmitNewModDelegateFast Callback) +{ + Modio::SubmitNewModAsync(ToModio(Handle), ToModio(Params), + [Callback](Modio::ErrorCode ec, Modio::Optional NewModID) { + Callback.ExecuteIfBound(ec, ToUnrealOptional(NewModID)); + }); +} + void UModioSubsystem::RequestEmailAuthCodeAsync(const FModioEmailAddress& EmailAddress, FOnErrorOnlyDelegateFast Callback) { @@ -554,7 +567,12 @@ void UModioSubsystem::GetModDependenciesAsync(FModioModID ModID, FOnGetModDepend }); } -MODIO_API void UModioSubsystem::K2_GetModDependenciesAsync(FModioModID ModID, FOnGetModDependenciesDelegate Callback) +FModioModCreationHandle UModioSubsystem::GetModCreationHandle() +{ + return ToUnreal(Modio::GetModCreationHandle()); +} + +void UModioSubsystem::K2_GetModDependenciesAsync(FModioModID ModID, FOnGetModDependenciesDelegate Callback) { GetModDependenciesAsync(ModID, FOnGetModDependenciesDelegateFast::CreateLambda( [Callback](FModioErrorCode ec, TOptional Dependencies) { @@ -563,6 +581,30 @@ MODIO_API void UModioSubsystem::K2_GetModDependenciesAsync(FModioModID ModID, FO })); } +void UModioSubsystem::SubmitNewModFileForMod(FModioModID Mod, FModioCreateModFileParams Params) +{ + Modio::SubmitNewModFileForMod(ToModio(Mod), ToModio(Params)); +} + +void UModioSubsystem::K2_SubmitNewModFileForMod(FModioModID Mod, FModioCreateModFileParams Params) +{ + SubmitNewModFileForMod(Mod, Params); +} + +FModioModCreationHandle UModioSubsystem::K2_GetModCreationHandle() +{ + return GetModCreationHandle(); +} + +void UModioSubsystem::K2_SubmitNewModAsync(FModioModCreationHandle Handle, FModioCreateModParams Params, + FOnSubmitNewModDelegate Callback) +{ + SubmitNewModAsync( + Handle, Params, + FOnSubmitNewModDelegateFast::CreateLambda( + [Callback](FModioErrorCode ec, TOptional NewModID) { Callback.ExecuteIfBound(ec, FModioOptionalModID {NewModID}); })); +} + /// File scope implementations #pragma region Implementation diff --git a/Source/Modio/Private/Types/ModioFilterParamsUImpl.cpp b/Source/Modio/Private/Types/ModioFilterParamsUImpl.cpp index b1dd23ff..145390ad 100644 --- a/Source/Modio/Private/Types/ModioFilterParamsUImpl.cpp +++ b/Source/Modio/Private/Types/ModioFilterParamsUImpl.cpp @@ -1,15 +1,15 @@ -/* +/* * 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/ModioFilterParams.h" #include "Internal/Convert/FilterParams.h" +#include "Types/ModioFilterParams.h" FModioFilterParams& FModioFilterParams::MatchingIDs(const TArray& IDs) { @@ -100,4 +100,10 @@ FModioFilterParams& FModioFilterParams::PagedResults(uint64 PageNumber, uint64 P FString FModioFilterParams::ToString() const { return FString(UTF8_TO_TCHAR(ToModio(*this).ToString().c_str())); +} + +FModioFilterParams& FModioFilterParams::MetadataLike(FString SearchString) +{ + MetadataBlobSearchString = SearchString; + return *this; } \ No newline at end of file diff --git a/Source/Modio/Public/Libraries/ModioFilterParamsLibrary.h b/Source/Modio/Public/Libraries/ModioFilterParamsLibrary.h index 012a7aed..04f0aa35 100644 --- a/Source/Modio/Public/Libraries/ModioFilterParamsLibrary.h +++ b/Source/Modio/Public/Libraries/ModioFilterParamsLibrary.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 @@ -26,7 +26,7 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this */ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& MatchingIDs(UPARAM(ref)FModioFilterParams& Filter, const TArray& IDs) + static FModioFilterParams& MatchingIDs(UPARAM(ref) FModioFilterParams& Filter, const TArray& IDs) { Filter.MatchingIDs(IDs); return Filter; @@ -38,13 +38,12 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this */ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& ExcludingIDs(UPARAM(ref)FModioFilterParams& Filter, const TArray& IDs) + static FModioFilterParams& ExcludingIDs(UPARAM(ref) FModioFilterParams& Filter, const TArray& IDs) { Filter.ExcludingIDs(IDs); return Filter; } - /** * @brief Indicates results should be sorted using the specified field and direction * @param ByField Field to sort with @@ -52,7 +51,8 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& SortBy(UPARAM(ref)FModioFilterParams& Filter, EModioSortFieldType ByField, EModioSortDirection ByDirection); + static FModioFilterParams& SortBy(UPARAM(ref) FModioFilterParams& Filter, EModioSortFieldType ByField, + EModioSortDirection ByDirection); /** * @brief Only include mods where the name contains the provided string @@ -60,15 +60,15 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& NameContains(UPARAM(ref)FModioFilterParams& Filter, const FString& SearchString); - + static FModioFilterParams& NameContains(UPARAM(ref) FModioFilterParams& Filter, const FString& SearchString); + /** * @brief Only include mods where the name contains the provided strings * @param SearchString Search string * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& NameContainsStrings(UPARAM(ref)FModioFilterParams& Filter, const FString& SearchString); + static FModioFilterParams& NameContainsStrings(UPARAM(ref) FModioFilterParams& Filter, const FString& SearchString); /** * @brief Only include mods that were marked live (i.e released) after the specified date @@ -76,7 +76,7 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& MarkedLiveAfter(UPARAM(ref)FModioFilterParams& Filter, FDateTime LiveAfter); + static FModioFilterParams& MarkedLiveAfter(UPARAM(ref) FModioFilterParams& Filter, FDateTime LiveAfter); /** * @brief Only include mods that were marked live (i.e released) before the specified date @@ -84,7 +84,7 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& MarkedLiveBefore(UPARAM(ref)FModioFilterParams& Filter, FDateTime LiveBefore); + static FModioFilterParams& MarkedLiveBefore(UPARAM(ref) FModioFilterParams& Filter, FDateTime LiveBefore); /** * @brief Only include mods that have the specified tag @@ -92,7 +92,7 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& WithTag(UPARAM(ref)FModioFilterParams& Filter, const FString& Tag); + static FModioFilterParams& WithTag(UPARAM(ref) FModioFilterParams& Filter, const FString& Tag); /** * @brief Only include mods that have all the specified tags (tag1 AND tag2 AND tagN...) @@ -100,7 +100,7 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& WithTags(UPARAM(ref)FModioFilterParams& Filter, const TArray& NewTags); + static FModioFilterParams& WithTags(UPARAM(ref) FModioFilterParams& Filter, const TArray& NewTags); /** * @brief Only include mods that do not have the specified tag @@ -108,7 +108,7 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& WithoutTag(UPARAM(ref)FModioFilterParams& Filter, const FString& Tag); + static FModioFilterParams& WithoutTag(UPARAM(ref) FModioFilterParams& Filter, const FString& Tag); /** * @brief Only include mods that do not have any of the specified tags ( NOT (tag1 OR tag2 OR tagN...)) @@ -116,7 +116,7 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& WithoutTags(UPARAM(ref)FModioFilterParams& Filter, const TArray& NewTags); + static FModioFilterParams& WithoutTags(UPARAM(ref) FModioFilterParams& Filter, const TArray& NewTags); /** * @brief Returns a sub-range of query results from StartIndex to StartIndex + ResultCount @@ -125,7 +125,8 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& IndexedResults(UPARAM(ref)FModioFilterParams& Filter, int64 StartIndex, int64 ResultCount); + static FModioFilterParams& IndexedResults(UPARAM(ref) FModioFilterParams& Filter, int64 StartIndex, + int64 ResultCount); /** * @brief Returns a sub-range of query results based on a specified page size and index @@ -134,5 +135,13 @@ class MODIO_API UModioFilterParamsLibrary : public UBlueprintFunctionLibrary * @return *this **/ UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") - static FModioFilterParams& PagedResults(UPARAM(ref)FModioFilterParams& Filter, int64 PageNumber, int64 PageSize); + static FModioFilterParams& PagedResults(UPARAM(ref) FModioFilterParams& Filter, int64 PageNumber, int64 PageSize); + + /** + * @brief Only include mods with a metadata blob containing the specified substring + * @param SearchString The substring to search for + * @return *this + **/ + UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Filter") + static FModioFilterParams& MetadataLike(UPARAM(ref) FModioFilterParams& Filter, FString SearchString); }; diff --git a/Source/Modio/Public/Libraries/ModioOptionalLibrary.h b/Source/Modio/Public/Libraries/ModioOptionalLibrary.h index 260035e1..7ad5412a 100644 --- a/Source/Modio/Public/Libraries/ModioOptionalLibrary.h +++ b/Source/Modio/Public/Libraries/ModioOptionalLibrary.h @@ -200,4 +200,25 @@ class MODIO_API UModioOptionalLibrary : public UBlueprintFunctionLibrary static bool GetValue_ModioOptionalModDependencyList( const struct FModioOptionalModDependencyList& OptionalDependencyList, struct FModioModDependencyList& DependencyList); + + + /** + * Check if the ModioModID has a valid value + * + * @param OptionalID - The optional to check + * @return true if it has a value set + */ + UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Optional", + meta = (DisplayName = "IsSet (ModioModID)", CompactNodeTitle = "IsSet")) + static bool IsSet_ModioOptionalModID(const struct FModioOptionalModID& OptionalID); + + /** + * Get the ID from the optional if it's set + * + * @param OptionalID - if this returned false, then this will be defaulted + * @param ID - the underlying value + * @return true if the optional has a value set + */ + UFUNCTION(BlueprintPure, Category = "mod.io|Utilities|Optional", DisplayName = "GetValue (ModioOptionalID)") + static bool GetValue_ModioOptionalModID(const struct FModioOptionalModID& OptionalID, struct FModioModID& ID); }; diff --git a/Source/Modio/Public/ModioSubsystem.h b/Source/Modio/Public/ModioSubsystem.h index 9f06e309..1162eba8 100644 --- a/Source/Modio/Public/ModioSubsystem.h +++ b/Source/Modio/Public/ModioSubsystem.h @@ -14,11 +14,14 @@ #include "Subsystems/EngineSubsystem.h" #include "Types/ModioAuthenticationParams.h" #include "Types/ModioCommonTypes.h" +#include "Types/ModioCreateModFileParams.h" +#include "Types/ModioCreateModParams.h" #include "Types/ModioErrorCode.h" #include "Types/ModioFilterParams.h" #include "Types/ModioImage.h" #include "Types/ModioInitializeOptions.h" #include "Types/ModioModCollectionEntry.h" +#include "Types/ModioModCreationHandle.h" #include "Types/ModioModDependencyList.h" #include "Types/ModioModInfo.h" #include "Types/ModioModInfoList.h" @@ -42,6 +45,7 @@ DECLARE_DELEGATE_TwoParams(FOnGetMediaDelegateFast, FModioErrorCode, TOptional); DECLARE_DELEGATE_TwoParams(FOnGetTermsOfUseDelegateFast, FModioErrorCode, TOptional); DECLARE_DELEGATE_TwoParams(FOnGetModDependenciesDelegateFast, FModioErrorCode, TOptional); +DECLARE_DELEGATE_TwoParams(FOnSubmitNewModDelegateFast, FModioErrorCode, TOptional); // Blueprint version of delegates DECLARE_DYNAMIC_DELEGATE_OneParam(FOnErrorOnlyDelegate, FModioErrorCode, ErrorCode); @@ -55,6 +59,7 @@ DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnGetModTagOptionsDelegate, FModioErrorCode, DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnGetTermsOfUseDelegate, FModioErrorCode, ErrorCode, FModioOptionalTerms, Terms); DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnGetModDependenciesDelegate, FModioErrorCode, ErrorCode, FModioOptionalModDependencyList, Dependencies); +DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnSubmitNewModDelegate, FModioErrorCode, ErrorCode, FModioOptionalModID, NewModID); /** * @brief Thin wrapper around the mod.io SDK. This mostly wraps all the functions available in modio/ModioSDK.h that's @@ -335,6 +340,46 @@ class UModioSubsystem : public UEngineSubsystem **/ MODIO_API void GetModDependenciesAsync(FModioModID ModID, FOnGetModDependenciesDelegateFast Callback); + /** + * @brief Gets a new mod handle for use with SubmitNewModAsync. + * @returns New handle + * @experimental + */ + MODIO_API FModioModCreationHandle GetModCreationHandle(); + + /** + * @brief Requests the creation of a new mod on the server with the specified parameters + * @param Handle The ModCreationHandle for this submission. Once this method invokes your callback indicating + * success, the ModCreationHandle is invalid for the rest of the session and you should request a new one for the + * next submission attempt. + * @param Params Information about the new mod to create + * @param Callback Callback providing a status code and an optional FModioModID for the newly created mod + * @experimental + * @requires initialized-sdk + * @requires authenticated-user + * @requires no-rate-limiting + * @errorcategory NetworkError|Couldn't connect to mod.io servers + * @error GenericError::SDKNotInitialized|SDK not initialized + * @errorcategory InvalidArgsError|Some fields in Params did not pass validation + * @error UserDataError::InvalidUser|No authenticated user + */ + MODIO_API void SubmitNewModAsync(FModioModCreationHandle Handle, FModioCreateModParams Params, + FOnSubmitNewModDelegateFast Callback); + + /** + * @brief Queues the upload of a new mod file release for the specified mod, using the submitted parameters. 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. + * @param Mod The ID of the mod you are submitting a file for + * @param Params Information about the mod file being created, including the root path of the directory that will be + * archived + * @experimental + * @requires initialized-sdk + * @requires authenticated-user + * @requires no-rate-limiting + * @error UserDataError::InvalidUser|No authenticated user + */ + MODIO_API void SubmitNewModFileForMod(FModioModID Mod, FModioCreateModFileParams Params); /** * @brief Begins email authentication for the current session by requesting a one-time code be sent to the * specified email address if it is associated with a Mod.io account @@ -769,6 +814,50 @@ class UModioSubsystem : public UEngineSubsystem UFUNCTION(BlueprintCallable, DisplayName = "SubmitModRatingAsync", Category = "mod.io|Mods") MODIO_API void K2_SubmitModRatingAsync(FModioModID Mod, EModioRating Rating, FOnErrorOnlyDelegate Callback); + /** + * @brief Gets a new mod handle for use with SubmitNewModAsync. + * @returns New handle + * @experimental + */ + UFUNCTION(BlueprintCallable, DisplayName = "GetModCreationHandle", Category = "mod.io|Mods|Submission") + MODIO_API FModioModCreationHandle K2_GetModCreationHandle(); + + /** + * @brief Requests the creation of a new mod on the server with the specified parameters + * @param Handle The ModCreationHandle for this submission. Once this method invokes your callback indicating + * success, the ModCreationHandle is invalid for the rest of the session and you should request a new one for the + * next submission attempt. + * @param Params Information about the new mod to create + * @param Callback Callback providing a status code and an optional FModioModID for the newly created mod + * @experimental + * @requires initialized-sdk + * @requires authenticated-user + * @requires no-rate-limiting + * @errorcategory NetworkError|Couldn't connect to mod.io servers + * @error GenericError::SDKNotInitialized|SDK not initialized + * @errorcategory InvalidArgsError|Some fields in Params did not pass validation + * @error UserDataError::InvalidUser|No authenticated user + */ + UFUNCTION(BlueprintCallable, DisplayName = "SubmitNewModAsync", Category = "mod.io|Mods|Submission") + MODIO_API void K2_SubmitNewModAsync(FModioModCreationHandle Handle, FModioCreateModParams Params, + FOnSubmitNewModDelegate Callback); + + /** + * @brief Queues the upload of a new mod file release for the specified mod, using the submitted parameters. 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. + * @param Mod The ID of the mod you are submitting a file for + * @param Params Information about the mod file being created, including the root path of the directory that will be + * archived + * @experimental + * @requires initialized-sdk + * @requires authenticated-user + * @requires no-rate-limiting + * @error UserDataError::InvalidUser|No authenticated user + */ + UFUNCTION(BlueprintCallable, DisplayName = "SubmitNewModFileForMod", Category = "mod.io|Mods|Submission") + MODIO_API void K2_SubmitNewModFileForMod(FModioModID Mod, FModioCreateModFileParams Params); + /** * @brief Sends a content report to mod.io. When using this function, please inform your users that if they provide * their contact name or details in the Report parameter, that those may be shared with the person responsible for diff --git a/Source/Modio/Public/Types/ModioCommonTypes.h b/Source/Modio/Public/Types/ModioCommonTypes.h index de4cc97c..4bfc7c11 100644 --- a/Source/Modio/Public/Types/ModioCommonTypes.h +++ b/Source/Modio/Public/Types/ModioCommonTypes.h @@ -192,6 +192,14 @@ struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 Internal; +}; + /** @brief Strong type for Game IDs */ USTRUCT(BlueprintType, meta = (HasNativeMake = "Modio.ModioCommonTypesLibrary.MakeGameId")) struct MODIO_API FModioGameID diff --git a/Source/Modio/Public/Types/ModioCreateModFileParams.h b/Source/Modio/Public/Types/ModioCreateModFileParams.h new file mode 100644 index 00000000..3b5a2491 --- /dev/null +++ b/Source/Modio/Public/Types/ModioCreateModFileParams.h @@ -0,0 +1,30 @@ +/* + * 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 "ModioCreateModFileParams.generated.h" + +USTRUCT(BlueprintType) +struct MODIO_API FModioCreateModFileParams +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString PathToModRootDirectory; + + TOptional VersionString; + + TOptional Changelog; + + TOptional bSetAsActiveRelease; + + TOptional MetadataBlob; +}; \ No newline at end of file diff --git a/Source/Modio/Public/Types/ModioCreateModParams.h b/Source/Modio/Public/Types/ModioCreateModParams.h new file mode 100644 index 00000000..03fed141 --- /dev/null +++ b/Source/Modio/Public/Types/ModioCreateModParams.h @@ -0,0 +1,45 @@ +/* + * 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 "ModioCreateModParams.generated.h" + +USTRUCT(BlueprintType) +struct MODIO_API FModioCreateModParams +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString PathToLogoFile; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Name; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) + FString Summary; + + TOptional NamePath; + + TOptional bVisible; + + TOptional Description; + + TOptional HomepageURL; + + TOptional QuantityAvailable; + + TOptional MaturityFlags; + + TOptional MetadataBlob; + + TOptional> Tags; + +}; \ No newline at end of file diff --git a/Source/Modio/Public/Types/ModioFilterParams.h b/Source/Modio/Public/Types/ModioFilterParams.h index c58ef4a3..e862355b 100644 --- a/Source/Modio/Public/Types/ModioFilterParams.h +++ b/Source/Modio/Public/Types/ModioFilterParams.h @@ -100,6 +100,13 @@ struct MODIO_API FModioFilterParams **/ FModioFilterParams& MarkedLiveBefore(FDateTime LiveBefore); + /** + * @brief Only include mods with a metadata blob containing the specified substring + * @param SearchString The substring to search for + * @return *this + **/ + FModioFilterParams& MetadataLike(FString SearchString); + /** * @brief Only include mods that have the specified tag * @param Tag Tag to include @@ -164,7 +171,7 @@ struct MODIO_API FModioFilterParams TArray ExcludedTags; TArray IncludedIDs; TArray ExcludedIDs; - + TOptional MetadataBlobSearchString; bool isPaged = false; int64 Index = 0; int64 Count = 100; diff --git a/Source/Modio/Public/Types/ModioModCreationHandle.h b/Source/Modio/Public/Types/ModioModCreationHandle.h new file mode 100644 index 00000000..a1593229 --- /dev/null +++ b/Source/Modio/Public/Types/ModioModCreationHandle.h @@ -0,0 +1,31 @@ +/* + * 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 "ModioModCreationHandle.generated.h" + +namespace Modio +{ + struct ModCreationHandle; +} + +struct FModioModCreationHandle; + +USTRUCT(BlueprintType) +struct MODIO_API FModioModCreationHandle +{ + GENERATED_BODY() + + private: + int64 Underlying; + friend FModioModCreationHandle ToUnreal(const Modio::ModCreationHandle& In); + friend Modio::ModCreationHandle ToModio(const FModioModCreationHandle& In); +}; diff --git a/Source/Modio/Public/Types/ModioModManagementEvent.h b/Source/Modio/Public/Types/ModioModManagementEvent.h index 2bed84e6..d950f0ea 100644 --- a/Source/Modio/Public/Types/ModioModManagementEvent.h +++ b/Source/Modio/Public/Types/ModioModManagementEvent.h @@ -22,7 +22,8 @@ enum class EModioModManagementEventType : uint8 { Installed, /** Mod installation to local storage */ Uninstalled, /** Mod uninstallation from local storage*/ - Updated /** Mod local installation updated to latest version*/ + Updated, /** Mod local installation updated to latest version*/ + Uploaded, /** Mod file was uploaded*/ }; /** @brief Simple struct representing the outcome of a mod management operation */ diff --git a/Source/Modio/Public/Types/ModioReportParams.h b/Source/Modio/Public/Types/ModioReportParams.h index 5d547269..900eb66e 100644 --- a/Source/Modio/Public/Types/ModioReportParams.h +++ b/Source/Modio/Public/Types/ModioReportParams.h @@ -17,7 +17,6 @@ namespace Modio class ReportParams; } - UENUM(BlueprintType) enum class EModioReportType : uint8 { diff --git a/Source/ModioTests/Private/Tests/ListAllModsTest.cpp b/Source/ModioTests/Private/Tests/ListAllModsTest.cpp index 4291e1ca..73566222 100644 --- a/Source/ModioTests/Private/Tests/ListAllModsTest.cpp +++ b/Source/ModioTests/Private/Tests/ListAllModsTest.cpp @@ -213,4 +213,19 @@ bool FModioListAllModsIDFilterTest::RunTest(const FString& Parameters) return true; } +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FModioListAllModsMetadataFilterTest, "Modio.ListAllMods.MetadataFilter", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext | + EAutomationTestFlags::ProductFilter) +bool FModioListAllModsMetadataFilterTest::RunTest(const FString& Parameters) +{ + ADD_LATENT_AUTOMATION_COMMAND(FModioInitializeAsyncCommand(this)); + + + ADD_LATENT_AUTOMATION_COMMAND(FModioListAllModsAsyncCommand(this, FModioFilterParams().MetadataLike("SomeString"))); + + + ADD_LATENT_AUTOMATION_COMMAND(FModioShutdownAsyncCommand(this)); + return true; +} + #endif // WITH_DEV_AUTOMATION_TESTS