Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
VolcanicArts committed Jun 18, 2023
2 parents 1e22d1d + 663f605 commit 4255058
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 110 deletions.
4 changes: 2 additions & 2 deletions VRCOSC.Desktop/VRCOSC.Desktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
<ApplicationIcon>game.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Version>0.0.0</Version>
<FileVersion>2023.617.0</FileVersion>
<FileVersion>2023.618.0</FileVersion>
<Title>VRCOSC</Title>
<Authors>VolcanicArts</Authors>
<Company>VolcanicArts</Company>
<Nullable>enable</Nullable>
<AssemblyVersion>2023.617.0</AssemblyVersion>
<AssemblyVersion>2023.618.0</AssemblyVersion>
</PropertyGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\VRCOSC.Game\VRCOSC.Game.csproj" />
Expand Down
49 changes: 18 additions & 31 deletions VRCOSC.Game/Modules/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Framework.Extensions.EnumExtensions;
using osu.Framework.Extensions.IEnumerableExtensions;
Expand Down Expand Up @@ -65,7 +63,8 @@ public abstract class Module : IComparable<Module>
protected bool IsStopping => State.Value == ModuleState.Stopping;
protected bool HasStopped => State.Value == ModuleState.Stopped;

private SerialisationManager serialisationManager = null!;
private readonly SerialisationManager saveStateSerialisationManager = new();
private readonly SerialisationManager moduleSerialisationManager = new();
private NotificationContainer notifications = null!;

public void InjectDependencies(GameHost host, GameManager gameManager, Scheduler scheduler, Storage storage, NotificationContainer notifications)
Expand All @@ -76,8 +75,7 @@ public void InjectDependencies(GameHost host, GameManager gameManager, Scheduler
this.notifications = notifications;
Storage = storage;

serialisationManager = new SerialisationManager();
serialisationManager.RegisterSerialiser(1, new ModuleSerialiser(storage, notifications, this));
moduleSerialisationManager.RegisterSerialiser(1, new ModuleSerialiser(storage, notifications, this));
}

public void Load()
Expand All @@ -97,43 +95,32 @@ public void Load()

public void Serialise()
{
serialisationManager.Serialise();
moduleSerialisationManager.Serialise();
}

public void Deserialise()
{
serialisationManager.Deserialise();
moduleSerialisationManager.Deserialise();
}

#endregion

#region Persistent State
#region Save State

private readonly object saveLock = new();

/// <summary>
/// Data passed into this will be automatically serialised using JsonConvert and saved as a persistent state for the module
/// </summary>
protected void SaveState(object data)
protected void RegisterSaveStateSerialiser<T>(int version) where T : ISaveStateSerialiser
{
lock (saveLock)
{
var serialisedData = JsonConvert.SerializeObject(data, Formatting.Indented);
File.WriteAllText(Storage.GetFullPath($"module-states/{SerialisedName}.json"), serialisedData);
}
var serialiser = (ISaveStateSerialiser)Activator.CreateInstance(typeof(T), Storage, notifications, this)!;
saveStateSerialisationManager.RegisterSerialiser(version, serialiser);
}

protected T? LoadState<T>()
protected void SaveState()
{
lock (saveLock)
{
if (Storage.Exists($"module-states/{SerialisedName}.json"))
{
return JsonConvert.DeserializeObject<T>(File.ReadAllText(Storage.GetStorageForDirectory("module-states").GetFullPath($"{SerialisedName}.json")));
}
saveStateSerialisationManager.Serialise();
}

return default;
}
protected void LoadState()
{
saveStateSerialisationManager.Deserialise();
}

#endregion
Expand Down Expand Up @@ -428,9 +415,9 @@ protected void SendParameter<T>(Enum lookup, T value, string suffix) where T : s
}

/// <summary>
/// Sends a parameter value to a specified parameter name (that may have been modified), with an optional parameter name suffix
/// Sends a <paramref name="value"/> to an address denoted by <paramref name="lookup"/>
/// </summary>
/// <param name="lookup">The lookup key of the parameter</param>
/// <param name="lookup">The lookup of the parameter</param>
/// <param name="value">The value to send</param>
protected void SendParameter<T>(Enum lookup, T value) where T : struct
{
Expand All @@ -439,7 +426,7 @@ protected void SendParameter<T>(Enum lookup, T value) where T : struct
if (!Parameters.ContainsKey(lookup)) throw new InvalidOperationException($"Parameter {lookup.GetType().Name}.{lookup} has not been defined");

var data = Parameters[lookup];
if (!data.Mode.HasFlagFast(ParameterMode.Write)) throw new InvalidOperationException($"Parameter {lookup.GetType().Name}.{lookup} is a read-parameter and therefore can't be sent!");
if (!data.Mode.HasFlagFast(ParameterMode.Write)) throw new InvalidOperationException($"Parameter {lookup.GetType().Name}.{lookup} is a read-only parameter and therefore can't be sent!");

OscClient.SendValue(data.FormattedAddress, value);
}
Expand Down
23 changes: 23 additions & 0 deletions VRCOSC.Game/Modules/SaveStateSerialiser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) VolcanicArts. Licensed under the GPL-3.0 License.
// See the LICENSE file in the repository root for full license text.

using osu.Framework.Platform;
using VRCOSC.Game.Graphics.Notifications;
using VRCOSC.Game.Serialisation;

namespace VRCOSC.Game.Modules;

public interface ISaveStateSerialiser : ISerialiser
{
}

public abstract class SaveStateSerialiser<TReference, TSerialisable> : Serialiser<TReference, TSerialisable>, ISaveStateSerialiser where TSerialisable : class where TReference : Module
{
protected override string Directory => "module-states";
protected override string FileName => $"{Reference.SerialisedName}.json";

protected SaveStateSerialiser(Storage storage, NotificationContainer notification, TReference reference)
: base(storage, notification, reference)
{
}
}
10 changes: 7 additions & 3 deletions VRCOSC.Game/OSC/Client/OscData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Collections.Generic;
using System.Linq;

namespace VRCOSC.Game.OSC.Client;

Expand All @@ -20,8 +19,13 @@ internal OscData(string address, List<object> values)

internal void PreValidate()
{
if (!Values.All(value => value is (bool or int or float or string)))
throw new ArgumentOutOfRangeException(nameof(Values), "Cannot send values that are not of type bool, int, float, or string");
Values.ForEach(value =>
{
if (value is not (bool or int or float or string))
{
throw new InvalidOperationException($"Cannot send value that is of type {value.GetType().Name} to address {Address}");
}
});
}

internal byte[] Encode() => new OscMessage(Address, Values).Encode();
Expand Down
9 changes: 8 additions & 1 deletion VRCOSC.Game/Serialisation/SerialisationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@ public void Deserialise(string filePathOverride = "")
return;
}

// Since we've got to this point that means a file exists that has no version, or the file is corrupt
// If a version 0 exists then use this to deserialise as it's for legacy migration
if (serialisers.TryGetValue(0, out var legacySerialiser))
{
deserialise(legacySerialiser, filePathOverride);
return;
}

// Since we've got to this point that means the file is corrupt
// As a last resort, attempt to deserialise with the latest serialiser. This also triggers the error notification
if (!serialisers.TryGetValue(latestSerialiserVersion, out var latestSerialiser)) return;

Expand Down
9 changes: 5 additions & 4 deletions VRCOSC.Game/Serialisation/Serialiser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ public abstract class Serialiser<TReference, TSerialisable> : ISerialiser where
{
private readonly object serialisationLock = new();
private readonly NotificationContainer notification;
private readonly TReference reference;
private Storage storage;

protected readonly TReference Reference;

protected virtual string Directory => string.Empty;
protected virtual string FileName => throw new NotImplementedException($"{typeof(Serialiser<TReference, TSerialisable>)} requires a file name");

protected Serialiser(Storage storage, NotificationContainer notification, TReference reference)
{
this.storage = storage;
this.notification = notification;
this.reference = reference;
Reference = reference;
}

public void Initialise()
Expand Down Expand Up @@ -77,7 +78,7 @@ public bool Deserialise(string filePathOverride = "")
var data = performDeserialisation<TSerialisable>(filePath);
if (data is null) return false;

ExecuteAfterDeserialisation(reference, data);
ExecuteAfterDeserialisation(Reference, data);
return true;
}
}
Expand Down Expand Up @@ -125,7 +126,7 @@ public bool Serialise()

private void performSerialisation()
{
var data = GetSerialisableData(reference);
var data = GetSerialisableData(Reference);

var bytes = Encoding.Unicode.GetBytes(JsonConvert.SerializeObject(data, Formatting.Indented));
using var stream = storage.CreateFileSafely(FileName);
Expand Down
26 changes: 13 additions & 13 deletions VRCOSC.Modules/ChatBoxText/ChatBoxTextInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ private void load()
AutoSizeAxes = Axes.Y,
ColumnDimensions = new[]
{
new Dimension(),
new Dimension(maxSize: 150),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension(),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension(),
new Dimension(maxSize: 100),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension(),
new Dimension(maxSize: 100),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension()
new Dimension(maxSize: 100)
},
RowDimensions = new[]
{
Expand All @@ -121,7 +121,7 @@ private void load()
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Key",
Font = FrameworkFont.Regular.With(size: 25)
Font = FrameworkFont.Regular.With(size: 20)
}
},
null,
Expand All @@ -134,7 +134,7 @@ private void load()
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Text",
Font = FrameworkFont.Regular.With(size: 25)
Font = FrameworkFont.Regular.With(size: 20)
}
},
null,
Expand All @@ -147,7 +147,7 @@ private void load()
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Direction",
Font = FrameworkFont.Regular.With(size: 25)
Font = FrameworkFont.Regular.With(size: 20)
}
},
null,
Expand All @@ -160,7 +160,7 @@ private void load()
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Scroll Speed",
Font = FrameworkFont.Regular.With(size: 25)
Font = FrameworkFont.Regular.With(size: 20)
}
},
null,
Expand All @@ -173,7 +173,7 @@ private void load()
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Max Length",
Font = FrameworkFont.Regular.With(size: 25)
Font = FrameworkFont.Regular.With(size: 20)
}
}
}
Expand All @@ -192,15 +192,15 @@ protected override void OnInstanceAdd(ChatBoxTextInstance instance)
AutoSizeAxes = Axes.Y,
ColumnDimensions = new[]
{
new Dimension(),
new Dimension(maxSize: 150),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension(),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension(),
new Dimension(maxSize: 100),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension(),
new Dimension(maxSize: 100),
new Dimension(GridSizeMode.Absolute, 5),
new Dimension()
new Dimension(maxSize: 100)
},
RowDimensions = new[]
{
Expand Down
Loading

0 comments on commit 4255058

Please sign in to comment.