diff --git a/Runtime/API/RequestCache.cs b/Runtime/API/RequestCache.cs
index ca09b644..cff082f8 100644
--- a/Runtime/API/RequestCache.cs
+++ b/Runtime/API/RequestCache.cs
@@ -22,7 +22,7 @@ private struct Entry
private const int ENTRY_LIFETIME = 120;
/// Max cache size.
- private static readonly uint MAX_CACHE_SIZE = PluginSettings.CACHE_SIZE*1024;
+ private static readonly uint MAX_CACHE_SIZE = PluginSettings.CACHE_SIZE_BYTES;
// ---------[ Fields ]---------
/// Map of url to saved responses.
diff --git a/Runtime/ModIOVersion.cs b/Runtime/ModIOVersion.cs
index 3f0cbfe3..f5393543 100644
--- a/Runtime/ModIOVersion.cs
+++ b/Runtime/ModIOVersion.cs
@@ -6,7 +6,7 @@ public struct ModIOVersion : System.IComparable
{
// ---------[ Singleton ]---------
/// Singleton instance for current version.
- public static readonly ModIOVersion Current = new ModIOVersion(2, 3, 2);
+ public static readonly ModIOVersion Current = new ModIOVersion(2, 3, 3);
// ---------[ Fields ]---------
/// Major version number.
diff --git a/Runtime/PluginSettings.cs b/Runtime/PluginSettings.cs
index 4906a7d3..f53e67c9 100644
--- a/Runtime/PluginSettings.cs
+++ b/Runtime/PluginSettings.cs
@@ -9,7 +9,7 @@
namespace ModIO
{
/// Stores the settings used by various classes that are unique to the game/app.
- public class PluginSettings : ScriptableObject
+ public class PluginSettings : ScriptableObject, ISerializationCallbackReceiver
{
// ---------[ NESTED CLASSES ]---------
/// Attribute for denoting a field as containing directory variables.
@@ -33,46 +33,64 @@ public struct RequestLoggingOptions
[System.Serializable]
public struct Data
{
+ // ---------[ Versioning ]---------
+ internal const int VERSION = 1;
+
+ [HideInInspector]
+ [VersionedData(VERSION, VERSION)]
+ public int version;
+
// ---------[ Fields ]---------
[Header("API Settings")]
[Tooltip("API URL to use when making requests")]
+ [VersionedData(0, "")]
public string apiURL;
[Tooltip("Game Id assigned to your game profile")]
+ [VersionedData(0, GameProfile.NULL_ID)]
public int gameId;
[Tooltip("API Key assigned to your game profile")]
+ [VersionedData(0, "")]
public string gameAPIKey;
- [Tooltip("Amount of memory the request cache is permitted to grow to (KB)")]
- public uint requestCacheSizeKB;
+ [Tooltip("Amount of memory the request cache is permitted to grow to (KB)."
+ + "\nA negative value indicates an unlimited cache size.")]
+ [VersionedData(1, (int)-1)]
+ public int requestCacheSizeKB;
/// Request logging options.
public RequestLoggingOptions requestLogging;
[Header("Standalone Directories")]
[Tooltip("Directory to use for mod installations")]
+ [VersionedData(0, @"$DATA_PATH$/mod.io/mods")]
[VariableDirectory]
public string installationDirectory;
[Tooltip("Directory to use for cached server data")]
+ [VersionedData(0, @"$DATA_PATH$/mod.io/cache")]
[VariableDirectory]
public string cacheDirectory;
[Tooltip("Directory to use for user data")]
+ [VersionedData(0, @"$PERSISTENT_DATA_PATH$/mod.io-$GAME_ID$")]
[VariableDirectory]
public string userDirectory;
[Header("Editor Directories")]
[Tooltip("Directory to use for mod installations")]
+ [VersionedData(0, @"$CURRENT_DIRECTORY$/mod.io/editor/$GAME_ID$/mods")]
[VariableDirectory]
public string installationDirectoryEditor;
[Tooltip("Directory to use for cached server data")]
+ [VersionedData(0, @"$CURRENT_DIRECTORY$/mod.io/editor/$GAME_ID$/cache")]
[VariableDirectory]
public string cacheDirectoryEditor;
[Tooltip("Directory to use for user data")]
+ [VersionedData(0, @"$CURRENT_DIRECTORY$/mod.io/editor/$GAME_ID$/user")]
[VariableDirectory]
public string userDirectoryEditor;
@@ -216,9 +234,19 @@ public static RequestLoggingOptions REQUEST_LOGGING
{
get { return PluginSettings.data.requestLogging; }
}
- public static uint CACHE_SIZE
+ public static uint CACHE_SIZE_BYTES
{
- get { return PluginSettings.data.requestCacheSizeKB; }
+ get
+ {
+ if(PluginSettings.data.requestCacheSizeKB < 0)
+ {
+ return uint.MaxValue;
+ }
+ else
+ {
+ return (uint)PluginSettings.data.requestCacheSizeKB * 1024;
+ }
+ }
}
// ---------[ FUNCTIONALITY ]---------
@@ -338,6 +366,31 @@ public static string ReplaceDirectoryVariables(string directory, int gameId)
return directory;
}
+ /// Creates an updated version of passed PluginSettings.Data.
+ public static PluginSettings.Data UpdateVersionedValues(int dataVersion,
+ PluginSettings.Data dataValues)
+ {
+ // early out
+ if(dataVersion >= PluginSettings.Data.VERSION)
+ {
+ return dataValues;
+ }
+ else
+ {
+ return VersionedDataAttribute.UpdateStructFields(dataVersion, dataValues);
+ }
+ }
+
+ // ---------[ ISerializationCallbackReceiver ]---------
+ /// Implement this method to receive a callback after Unity deserializes your object.
+ public void OnAfterDeserialize()
+ {
+ this.m_data = PluginSettings.UpdateVersionedValues(this.m_data.version, this.m_data);
+ }
+
+ /// Implement this method to receive a callback before Unity serializes your object.
+ public void OnBeforeSerialize() {}
+
// ---------[ EDITOR CODE ]---------
#if UNITY_EDITOR
/// Locates the PluginSettings asset used at runtime.
@@ -359,26 +412,16 @@ public static void FocusAsset()
/// Generates a PluginSettings.Data instance with runtime defaults.
public static PluginSettings.Data GenerateDefaultData()
{
- PluginSettings.Data data = new PluginSettings.Data()
+ PluginSettings.Data data = new PluginSettings.Data();
+ data = PluginSettings.UpdateVersionedValues(-1, data);
+
+ // non-constant defaults
+ data.apiURL = APIClient.API_URL_PRODUCTIONSERVER + APIClient.API_VERSION;
+ data.requestLogging = new RequestLoggingOptions()
{
- apiURL = APIClient.API_URL_PRODUCTIONSERVER + APIClient.API_VERSION,
- gameId = GameProfile.NULL_ID,
- gameAPIKey = string.Empty,
- requestCacheSizeKB = 4*1024,
- requestLogging = new RequestLoggingOptions()
- {
- errorsAsWarnings = true,
- logAllResponses = false,
- logOnSend = false,
- },
-
- installationDirectory = IOUtilities.CombinePath("$DATA_PATH$","mod.io","mods"),
- cacheDirectory = IOUtilities.CombinePath("$DATA_PATH$","mod.io","cache"),
- userDirectory = IOUtilities.CombinePath("$PERSISTENT_DATA_PATH$","mod.io-$GAME_ID$"),
-
- installationDirectoryEditor = IOUtilities.CombinePath("$CURRENT_DIRECTORY$","mod.io","editor","$GAME_ID$","mods"),
- cacheDirectoryEditor = IOUtilities.CombinePath("$CURRENT_DIRECTORY$","mod.io","editor","$GAME_ID$","cache"),
- userDirectoryEditor = IOUtilities.CombinePath("$CURRENT_DIRECTORY$","mod.io","editor","$GAME_ID$","user"),
+ errorsAsWarnings = true,
+ logAllResponses = false,
+ logOnSend = false,
};
return data;
diff --git a/Runtime/Utility/VersionedDataAttribute.cs b/Runtime/Utility/VersionedDataAttribute.cs
new file mode 100644
index 00000000..3190fc7a
--- /dev/null
+++ b/Runtime/Utility/VersionedDataAttribute.cs
@@ -0,0 +1,53 @@
+namespace ModIO
+{
+ /// Attribute for determining the version of and default value for a given field.
+ public class VersionedDataAttribute : System.Attribute
+ {
+ // ---------[ Fields ]---------
+ /// Version the field was created.
+ public int version;
+
+ /// Default value for the field.
+ public System.Object defaultValue;
+
+ // ---------[ Initialization ]---------
+ public VersionedDataAttribute(int version, System.Object defaultValue)
+ {
+ this.version = version;
+ this.defaultValue = defaultValue;
+ }
+
+ // ---------[ Utility ]---------
+ /// Creates an updated version of the data structure passed.
+ public static T UpdateStructFields(int dataVersion, T dataValues)
+ where T : struct
+ {
+ // set up data
+ T updatedValues = dataValues;
+ System.Object boxedData = updatedValues;
+
+ // iterate over the typed fields
+ var fieldList = typeof(T).GetFields();
+ foreach(var field in fieldList)
+ {
+ // check for the VersionedDataAttribute attribute
+ var attributeList = field.GetCustomAttributes(typeof(VersionedDataAttribute), false);
+ if(attributeList != null
+ && attributeList.Length == 1)
+ {
+ // set the default value if attribute is newer than the dataVersion
+ VersionedDataAttribute dataAttribute = (VersionedDataAttribute)attributeList[0];
+ if(dataAttribute.version > dataVersion)
+ {
+ field.SetValue(boxedData, dataAttribute.defaultValue);
+ }
+ }
+ }
+
+ // unbox the updatedValues
+ updatedValues = (T)boxedData;
+
+ return updatedValues;
+ }
+ }
+}
diff --git a/Runtime/Utility/VersionedDataAttribute.cs.meta b/Runtime/Utility/VersionedDataAttribute.cs.meta
new file mode 100644
index 00000000..713cc94c
--- /dev/null
+++ b/Runtime/Utility/VersionedDataAttribute.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8e2869d4b03379a48ad42af8aebc8ac0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: