Skip to content

Commit

Permalink
Syncing v2025.2
Browse files Browse the repository at this point in the history
  • Loading branch information
scrambled-eggs-tokens committed Feb 11, 2025
1 parent 589445d commit f5f829b
Show file tree
Hide file tree
Showing 32 changed files with 279 additions and 70 deletions.
8 changes: 8 additions & 0 deletions Additional Packages.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Additional Packages/modio-gog.unitypackage
Binary file not shown.
7 changes: 7 additions & 0 deletions Additional Packages/modio-gog.unitypackage.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified Experimental/modio-ui.unitypackage
Binary file not shown.
8 changes: 8 additions & 0 deletions Platform/GOG.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Platform/Oculus/ModioPlatformExampleOculus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void Awake()
{
// Oculus takes a fair bit of time to initialize and perform the entitlement check. By calling this
// we're telling the plugin to wait until it's ready.
// You MUST call ModioPlatform.SetInitializingFailed if you are later prevented from setting the ModioPlatform
ModioPlatform.SetInitializing();

// Ensure you have your game's App Id set up in the Oculus Settings object provided by the Meta Platform SDK
Expand All @@ -24,6 +25,7 @@ void OnInitialize(Message<PlatformInitialize> message)
{
if (message.IsError)
{
ModioPlatform.SetInitializingFailed();
Logger.Log(LogLevel.Error, $"initializing Oculus Platform: {message.GetError().Message}");
return;
}
Expand All @@ -37,6 +39,7 @@ void OnEntitled(Message message)
{
if (message.IsError)
{
ModioPlatform.SetInitializingFailed();
Logger.Log(LogLevel.Error, $"Error checking Oculus Platform entitlement: {message.GetError().Message}");
return;
}
Expand Down
5 changes: 4 additions & 1 deletion Platform/Oculus/ModioPlatformOculus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,12 @@ public Task<Result> OpenCheckoutFlow(PortalSku sku)
{
if (message.IsError)
{
if (message.GetError().Code == 0)
taskCompletionSource.SetResult(ResultBuilder.Create(ResultCode.Internal_OperationCancelled));

Logger.Log(LogLevel.Error, $"{message.GetError().Message}");

taskCompletionSource.SetResult(ResultBuilder.Create(ResultCode.Internal_OperationCancelled));
taskCompletionSource.SetResult(ResultBuilder.Create(ResultCode.Unknown));
return;
}

Expand Down
38 changes: 38 additions & 0 deletions Platform/Steam/Facepunch/ModioPlatformFacepunch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,44 @@ public override void OpenWebPage(string url)
SteamFriends.OpenWebOverlay(url);
#else
base.OpenWebPage(url);
#endif
}

public override bool TryOpenVirtualKeyboard(
string title,
string text,
string placeholder,
ModioVirtualKeyboardType virtualKeyboardType,
int characterLimit,
bool multiline,
Action<string> onClose)
{
#if UNITY_FACEPUNCH
// This will not work in desktop mode of Steam Deck.
// Facepunch does not support Steam deck API calls yet
// TODO: If the above changes, re-implement to check if we're steam deck
if (!SteamUtils.IsSteamInBigPictureMode) return false;

SteamUtils.OnGamepadTextInputDismissed += OnGamepadTextInputClose;

return SteamUtils.ShowGamepadTextInput(
GamepadTextInputMode.Normal,
multiline ? GamepadTextInputLineMode.MultipleLines : GamepadTextInputLineMode.SingleLine,
title,
characterLimit,
placeholder
);

void OnGamepadTextInputClose(bool isSubmitted)
{
if (!isSubmitted) return;

SteamUtils.OnGamepadTextInputDismissed -= OnGamepadTextInputClose;

onClose.Invoke(SteamUtils.GetEnteredGamepadText());
}
#else
return false;
#endif
}
}
Expand Down
48 changes: 48 additions & 0 deletions Platform/Steam/Steamworks/ModioPlatformSteamworks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public class ModioPlatformSteamworks : ModioPlatform, IModioSsoPlatform
private string betaStoreHomePage => $"https://store.steampowered.com/app/{appId}/modio/?beta=1";
private string betaStoreInventoryPage => $"https://store.steampowered.com/itemstore/{appId}/browse/?filter=all";

#if UNITY_STEAMWORKS && !DISABLESTEAMWORKS
Callback<GamepadTextInputDismissed_t> _virtualKeyboardCallback;
#endif

public static void SetAsPlatform(uint appId)
{
ModioPlatformSteamworks.appId = appId;
Expand Down Expand Up @@ -97,6 +101,50 @@ public override void OpenWebPage(string url)
SteamFriends.ActivateGameOverlayToWebPage(this.betaStoreHomePage, EActivateGameOverlayToWebPageMode.k_EActivateGameOverlayToWebPageMode_Modal);
#else
base.OpenWebPage(url);
#endif
}

public override bool TryOpenVirtualKeyboard(
string title,
string text,
string placeholder,
ModioVirtualKeyboardType virtualKeyboardType,
int characterLimit,
bool multiline,
Action<string> onClose)
{
#if UNITY_STEAMWORKS && !DISABLESTEAMWORKS
if (!SteamUtils.IsSteamRunningOnSteamDeck() || !SteamUtils.IsSteamInBigPictureMode())
return false;

_virtualKeyboardCallback = Callback<GamepadTextInputDismissed_t>.Create(OnGamepadTextInputClose);

return SteamUtils.ShowGamepadTextInput(
EGamepadTextInputMode.k_EGamepadTextInputModeNormal,
multiline ? EGamepadTextInputLineMode.k_EGamepadTextInputLineModeMultipleLines : EGamepadTextInputLineMode.k_EGamepadTextInputLineModeSingleLine,
title,
(uint)characterLimit,
placeholder
);

void OnGamepadTextInputClose(GamepadTextInputDismissed_t result)
{
if (result.m_bSubmitted)
{
uint textLength = SteamUtils.GetEnteredGamepadTextLength();
bool success = SteamUtils.GetEnteredGamepadTextInput(out string enteredText, textLength);

if (!success)
Logger.Log(LogLevel.Warning, $"Failed to retrieve virtual keyboard text");
else
onClose.Invoke(enteredText);
}

_virtualKeyboardCallback.Dispose();
_virtualKeyboardCallback = null;
}
#else
return false;
#endif
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ internal static partial class PlatformConfiguration
#elif UNITY_STANDALONE_LINUX
/// <summary>Holds the value for the platform header value to use in requests.</summary>
public static RestApiPlatform RESTAPI_HEADER = RestApiPlatform.Linux;
#elif MODIO_OCULUS
/// <summary>Holds the value for the platform header value to use in requests.</summary>
public static RestApiPlatform RESTAPI_HEADER = RestApiPlatform.Oculus;
#elif UNITY_ANDROID
/// <summary>Holds the value for the platform header value to use in requests.</summary>
public static RestApiPlatform RESTAPI_HEADER = RestApiPlatform.Android;
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ sidebar_position: 0
---

<a href="https://mod.io"><img src="https://mod.io/images/branding/modio-logo-bluewhite.svg" alt="mod.io" width="360" align="right"/></a>
# mod.io Unity Plugin v2024.11
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/modio/modio-unity/blob/master/LICENSE)
# mod.io Unity Plugin v2025.2
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/modio/modio-unity/blob/master/Documentation/LICENSE.md)
[![Discord](https://img.shields.io/discord/389039439487434752.svg?label=Discord&logo=discord&color=7289DA&labelColor=2C2F33)](https://discord.mod.io)
[![Master docs](https://img.shields.io/badge/docs-master-green.svg)](https://docs.mod.io/unity/)
[![Unity 3D](https://img.shields.io/badge/Unity-2020.3+-lightgrey.svg)](https://unity3d.com)
[![Unity 3D](https://img.shields.io/badge/Unity-2021.3+-lightgrey.svg)](https://unity3d.com)

Welcome to the mod.io Unity Engine plugin [repository](https://github.com/modio/modio-unity)!

Expand All @@ -23,9 +23,9 @@ mod.io enables game developers of all sizes to integrate user-generated content
- Founded by the [ModDB.com](https://moddb.com) team, with over two decades of experience in the UGC space
- Constantly evolving - we continue to work alongside our partners to iterate and improve our plugin support

The mod.io Unity Engine plugin is the simplest and fastest way to integrate UGC into your Unity **2020.3+** game. It handles all of the common tasks, allowing game developers to quickly and easily implement a solution that enables players to access and discover user-generated content for their games.
The mod.io Unity Engine plugin is the simplest and fastest way to integrate UGC into your Unity **2021.3+** game. It handles all of the common tasks, allowing game developers to quickly and easily implement a solution that enables players to access and discover user-generated content for their games.

A custom built [ready-made UI](#browser-ui) for mod discovery is included, along with installation and collection management, and a full-featured [C# interface](#getting-started) which connects to the [mod.io REST API](https://docs.mod.io).
A custom-built [ready-made UI](#browser-ui) for mod discovery is included, along with installation and collection management, and a full-featured [C# interface](#getting-started) which connects to the [mod.io REST API](https://docs.mod.io).
> [!WARNING]
> The Browser UI is scheduled for deprecation, and may not receive updates.
> This is to be replaced with the [Component UI / Template UI](#component-ui)
Expand Down Expand Up @@ -87,7 +87,7 @@ The first thing you'll need to do is [create a game profile](https://mod.io/g/ad
4. Use the *Insert URL* buttons to set the `server URL` depending on where you created your game profile earlier.

> [!WARNING]
> Deselect the config file before entering Play mode. A known Unity bug can cause the Editor to crash in Unity 2019-2021.
> Deselect the config file before entering Play mode. A known Unity bug can cause the Editor to crash.
Your setup is now complete. The following sections will guide you through getting your mod.io integration up and running quickly.

Expand Down
4 changes: 0 additions & 4 deletions Runtime/ModIO.Implementation/Classes/ModCollectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
using ModIO.Implementation.API.Requests;
using Runtime.Enums;

#if UNITY_GAMECORE
using Unity.GameCore;
#endif

namespace ModIO.Implementation
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3470,7 +3470,7 @@ public static async Task<ResultAnd<Entitlement[]>> SyncEntitlements()

config = API.Requests.SyncEntitlements.OculusRequest(userId.value, device);
requestTask = WebRequestManager.Request<SyncEntitlements.ResponseSchema>(config);
#elif UNITY_STANDALONE && !UNITY_EDITOR
#elif UNITY_FACEPUNCH || UNITY_STEAMWORKS
config = API.Requests.SyncEntitlements.SteamRequest();
requestTask = WebRequestManager.Request<SyncEntitlements.ResponseSchema>(config);
#elif ((UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR) && MODIO_MOBILE_IAP
Expand Down
2 changes: 1 addition & 1 deletion Runtime/ModIO.Implementation/Classes/ModIOVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ internal struct ModIOVersion : System.IComparable<ModIOVersion>
{
// ---------[ Singleton ]---------
/// <summary>Singleton instance for current version.</summary>
public static readonly ModIOVersion Current = new ModIOVersion(2024, 11, 0, "");
public static readonly ModIOVersion Current = new ModIOVersion(2025, 2, 0, "");

// ---------[ Fields ]---------
/// <summary>Main Version number.</summary>
Expand Down
105 changes: 76 additions & 29 deletions Runtime/ModIO.Implementation/Classes/ModManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,27 +428,19 @@ static async Task<Result> PerformOperation_Download(ModManagementJob job)
long modId = job.modEntry.modObject.id;
long fileId = job.modEntry.modObject.modfile.id;

bool hasEnoughSpace;

// Consoles separate storage into temporary & persistent, so we check them separately
if (Application.isConsolePlatform)
{
hasEnoughSpace =
await DataStorage.temp.IsThereEnoughDiskSpaceFor(job.modEntry.modObject.modfile.filesize)
&& await DataStorage.persistent.IsThereEnoughDiskSpaceFor(job.modEntry.modObject.modfile.filesize_uncompressed);
}
else
{
// On other platforms, these locations refer to the same drive
long totalRequiredSpace = job.modEntry.modObject.modfile.filesize + job.modEntry.modObject.modfile.filesize_uncompressed;
hasEnoughSpace = await DataStorage.persistent.IsThereEnoughDiskSpaceFor(totalRequiredSpace);
}
bool hasEnoughSpace = await HasEnoughSpace(job.modEntry.modObject.modfile.filesize,
job.modEntry.modObject.modfile.filesize_uncompressed);

if(!hasEnoughSpace)
{
Logger.Log(LogLevel.Error, $"INSUFFICIENT STORAGE FOR DOWNLOAD [{modId}_{fileId}]");
notEnoughStorageMods.Add((ModId)modId);
return ResultBuilder.Create(ResultCode.IO_InsufficientStorage);

Result insufficientStorageResult = ResultBuilder.Create(ResultCode.IO_InsufficientStorage);
InvokeModManagementDelegate((ModId)modId,
ModManagementEventType.DownloadFailed,
insufficientStorageResult);
return insufficientStorageResult;
}

Logger.Log(LogLevel.Message, $"DOWNLOADING MODFILE[{modId}_{fileId}]");
Expand Down Expand Up @@ -572,6 +564,25 @@ await DataStorage.temp.IsThereEnoughDiskSpaceFor(job.modEntry.modObject.modfile.

return result;
}
static async Task<bool> HasEnoughSpace(long tempBytes, long persistentBytes)
{
// Consoles separate storage into temporary & persistent, so we check them separately
bool hasEnoughSpace;
if (Application.isConsolePlatform)
{
hasEnoughSpace =
await DataStorage.temp.IsThereEnoughDiskSpaceFor(tempBytes)
&& await DataStorage.persistent.IsThereEnoughDiskSpaceFor(persistentBytes);
}
else
{
// On other platforms, these locations refer to the same drive
long totalRequiredSpace = tempBytes + persistentBytes;
hasEnoughSpace = await DataStorage.persistent.IsThereEnoughDiskSpaceFor(totalRequiredSpace);
}

return hasEnoughSpace;
}

static Result DownloadCleanup(Result result, long modId, long fileId)
{
Expand Down Expand Up @@ -753,28 +764,21 @@ public static SubscribedModStatus GetModCollectionEntrysSubscribedModStatus(
{
if(DataStorage.TryGetInstallationDirectory(modId, currentFileId,
out string _))
{
return SubscribedModStatus.WaitingToUninstall;
}
return SubscribedModStatus.None;
}
else if(DataStorage.TryGetInstallationDirectory(modId, currentFileId,
out string _))
if(DataStorage.TryGetInstallationDirectory(modId, currentFileId,
out string _))
{
if(currentFileId != fileId)
{
return SubscribedModStatus.WaitingToUpdate;
}
return SubscribedModStatus.Installed;
}
else if(DataStorage.TryGetModfileArchive(modId, fileId, out string _))
if(DataStorage.TryGetModfileArchive(modId, fileId, out string _))
{
return SubscribedModStatus.WaitingToInstall;
}
else
{
return SubscribedModStatus.WaitingToDownload;
}

return SubscribedModStatus.Installed;
return SubscribedModStatus.WaitingToDownload;
}

static async Task<ModManagementJob> GetNextModManagementJob()
Expand Down Expand Up @@ -1011,5 +1015,48 @@ public static void RetryFailedDownload(ModId modid)
taintedMods.Remove(modid);
WakeUp();
}
public static async Task<Result> DoesHaveSpaceForMod(ModId modId)
{
long spaceRequired = 0;
long tempSpaceRequired = 0;

foreach ((ModId key, ModCollectionEntry modCollectionEntry) in ModCollectionManager.Registry.mods)
{
if (currentJob != null && currentJob.modEntry.modObject.id == key.id)
{
float progressRemaining = 1;

if(currentJob.progressHandle != null)
progressRemaining = (1 - currentJob.progressHandle.Progress);

if (currentJob.type == ModManagementOperationType.Download)
{
var currentSize = currentJob.modEntry.currentModfile.filesize;
tempSpaceRequired += (long)(progressRemaining * currentSize);
}
else
{
var currentSize = currentJob.modEntry.currentModfile.filesize_uncompressed;
spaceRequired += (long)(progressRemaining * currentSize);
}
continue;
}

var modStatus = GetModCollectionEntrysSubscribedModStatus(modCollectionEntry);
if (modStatus is SubscribedModStatus.None or SubscribedModStatus.Installed or SubscribedModStatus.ProblemOccurred)
continue;

if (modStatus is SubscribedModStatus.WaitingToDownload or SubscribedModStatus.Downloading)
tempSpaceRequired += currentJob.modEntry.currentModfile.filesize;
if (modStatus is SubscribedModStatus.WaitingToUninstall)
spaceRequired -= currentJob.modEntry.currentModfile.filesize_uncompressed;
else
spaceRequired += currentJob.modEntry.currentModfile.filesize_uncompressed;
}
bool hasEnoughSpace = await HasEnoughSpace(tempSpaceRequired, spaceRequired);
if(!hasEnoughSpace)
return ResultBuilder.Create(ResultCode.IO_InsufficientStorage);
return ResultBuilder.Success;
}
}
}
Loading

0 comments on commit f5f829b

Please sign in to comment.