diff --git a/HitScoreVisualizer.sln b/HitScoreVisualizer.sln
index 6c22596..89d8399 100644
--- a/HitScoreVisualizer.sln
+++ b/HitScoreVisualizer.sln
@@ -1,9 +1,9 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27703.2035
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28729.10
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitScoreVisualizer", "HitScoreVisualizer\HitScoreVisualizer.csproj", "{7D8A403B-A4EE-42AD-85EF-ACFD7F087A79}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HitScoreVisualizer", "HitScoreVisualizer\HitScoreVisualizer.csproj", "{B05E8128-7D91-4C6A-A403-6FC998CE8B39}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,15 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {7D8A403B-A4EE-42AD-85EF-ACFD7F087A79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7D8A403B-A4EE-42AD-85EF-ACFD7F087A79}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7D8A403B-A4EE-42AD-85EF-ACFD7F087A79}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7D8A403B-A4EE-42AD-85EF-ACFD7F087A79}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B05E8128-7D91-4C6A-A403-6FC998CE8B39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B05E8128-7D91-4C6A-A403-6FC998CE8B39}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B05E8128-7D91-4C6A-A403-6FC998CE8B39}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B05E8128-7D91-4C6A-A403-6FC998CE8B39}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {FCB42BAF-E3A9-4B03-B8A5-2538DB0373DF}
+ SolutionGuid = {CB5A769E-6A21-4819-99FD-81F6F864AA9F}
EndGlobalSection
EndGlobal
diff --git a/HitScoreVisualizer/Configs.cs b/HitScoreVisualizer/Configs.cs
new file mode 100644
index 0000000..1d37ef2
--- /dev/null
+++ b/HitScoreVisualizer/Configs.cs
@@ -0,0 +1,464 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TMPro;
+using UnityEngine;
+
+using static HitScoreVisualizer.Utils.ReflectionUtil;
+
+namespace HitScoreVisualizer
+{
+ public class Configs
+ {
+ public static Configs instance;
+
+ // If true, this config will not overwrite the existing config file.
+ // (This gets set if a config from a newer version is detected.)
+ [JsonIgnore]
+ public bool noSerialize;
+
+ public struct Judgment
+ {
+ // This judgment will be applied only to notes hit with score >= this number.
+ // Note that if no judgment can be applied to a note, the text will appear as in the unmodded
+ // game.
+ [DefaultValue(0)]
+ public int threshold;
+
+ // The text to display (if judgment text is enabled).
+ [DefaultValue("")]
+ public string text;
+
+ // 4 floats, 0-1; red, green, blue, glow (not transparency!)
+ [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] // leaving this out should look obviously wrong
+ public float[] color;
+
+ // If true, the text color will be lerped between this judgment's color and the previous
+ // based on how close to the next threshold it is.
+ // Specifying fade : true for the first judgment in the array is an error, and will crash the
+ // plugin.
+ [DefaultValue(false)]
+ public bool fade;
+ }
+
+ // Judgments for individual parts of the swing (angle before, angle after, accuracy).
+ public struct SegmentJudgment
+ {
+ // This judgment will be applied only when the appropriate part of the swing contributes score >= this number.
+ // If no judgment can be applied, the judgment for this segment will be "" (the empty string).
+ [DefaultValue(0)]
+ public int threshold;
+ // The text to replace the appropriate judgment specifier with (%B, %C, %A) when this judgment applies.
+ public string text;
+ }
+
+ // If the version number (excluding patch version) of the config is higher than that of the plugin,
+ // the config will not be loaded. If the version number of the config is lower than that of the
+ // plugin, the file will be automatically converted. Conversion is not guaranteed to occur, or be
+ // accurate, across major versions.
+ [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
+ public int majorVersion;
+ [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
+ public int minorVersion;
+ [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
+ public int patchVersion;
+
+ // If this is true, the config will be overwritten with the plugin's default settings after an
+ // update rather than being converted.
+ public bool isDefaultConfig;
+
+ // If set to "format", displays the judgment text, with the following format specifiers allowed:
+ // - %b: The score contributed by the part of the swing before cutting the block.
+ // - %c: The score contributed by the accuracy of the cut.
+ // - %a: The score contributed by the part of the swing after cutting the block.
+ // - %B, %C, %A: As above, except using the appropriate judgment from that part of the swing (as configured for "beforeCutAngleJudgments", "accuracyJudgments", or "afterCutAngleJudgments").
+ // - %s: The total score for the cut.
+ // - %p: The percent out of 110 you achieved with your swing's score
+ // - %%: A literal percent symbol.
+ // - %n: A newline.
+ //
+ // If set to "numeric", displays only the note score.
+ // If set to "textOnly", displays only the judgment text.
+ // If set to "scoreOnTop", displays both (numeric score above judgment text).
+ // Otherwise, displays both (judgment text above numeric score).
+ [DefaultValue("")]
+ public string displayMode;
+
+ // Order from highest threshold to lowest; the first matching judgment will be applied
+ public Judgment[] judgments;
+
+ // Judgments for the part of the swing before cutting the block (score is from 0-70).
+ // Format specifier: %B
+ public SegmentJudgment[] beforeCutAngleJudgments;
+
+ // Judgments for the accuracy of the cut (how close to the center of the block the cut was, score is from 0-10).
+ // Format specifier: %C
+ public SegmentJudgment[] accuracyJudgments;
+
+ // Judgments for the part of the swing after cutting the block (score is from 0-30).
+ // Format specifier: %A
+ public SegmentJudgment[] afterCutAngleJudgments;
+
+ // path to where the config is saved
+ private const string FILE_PATH = "/UserData/HitScoreVisualizerConfig.json";
+
+ private const string DEFAULT_JSON = @"{
+ ""majorVersion"": 2,
+ ""minorVersion"": 1,
+ ""patchVersion"": 6,
+ ""isDefaultConfig"": true,
+ ""displayMode"": ""format"",
+ ""judgments"": [
+ {
+ ""threshold"": 110,
+ ""text"": ""%BFantastic%A%n%s"",
+ ""color"": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ },
+ {
+ ""threshold"": 101,
+ ""text"": ""%BExcellent%A%n%s"",
+ ""color"": [
+ 0.0,
+ 1.0,
+ 0.0,
+ 1.0
+ ]
+},
+ {
+ ""threshold"": 90,
+ ""text"": ""%BGreat%A%n%s"",
+ ""color"": [
+ 1.0,
+ 0.980392158,
+ 0.0,
+ 1.0
+ ]
+ },
+ {
+ ""threshold"": 80,
+ ""text"": ""%BGood%A%n%s"",
+ ""color"": [
+ 1.0,
+ 0.6,
+ 0.0,
+ 1.0
+ ],
+ ""fade"": true
+ },
+ {
+ ""threshold"": 60,
+ ""text"": ""%BDecent%A%n%s"",
+ ""color"": [
+ 1.0,
+ 0.0,
+ 0.0,
+ 1.0
+ ],
+ ""fade"": true
+ },
+ {
+ ""text"": ""%BWay Off%A%n%s"",
+ ""color"": [
+ 0.5,
+ 0.0,
+ 0.0,
+ 1.0
+ ],
+ ""fade"": true
+ }
+ ],
+ ""beforeCutAngleJudgments"": [
+ {
+ ""threshold"": 70,
+ ""text"": ""+""
+ },
+ {
+ ""text"": "" ""
+ }
+ ],
+ ""accuracyJudgments"": [
+ {
+ ""threshold"": 10,
+ ""text"": ""+""
+ },
+ {
+ ""text"": "" ""
+ }
+ ],
+ ""afterCutAngleJudgments"": [
+ {
+ ""threshold"": 30,
+ ""text"": ""+""
+ },
+ {
+ ""text"": "" ""
+ }
+ ]
+}";
+ public static readonly Configs DEFAULT_CONFIG = JsonConvert.DeserializeObject(DEFAULT_JSON,
+ new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate });
+
+ public static readonly Judgment DEFAULT_JUDGMENT = new Judgment
+ {
+ threshold = 0,
+ text = "",
+ color = new float[] { 1f, 1f, 1f, 1f },
+ fade = false
+ };
+
+ public static readonly SegmentJudgment DEFAULT_SEGMENT_JUDGMENT = new SegmentJudgment
+ {
+ threshold = 0,
+ text = ""
+ };
+
+ public static string fullPath => Environment.CurrentDirectory.Replace('\\', '/') + FILE_PATH;
+
+ public static void load()
+ {
+ Plugin.log("Loading config...");
+ if (!File.Exists(fullPath))
+ {
+ Plugin.log("Writing default config.");
+ // if the config file doesn't exist, save the default one
+ resetToDefault();
+ save(true);
+ return;
+ }
+ string configJson = File.ReadAllText(fullPath);
+ Configs loaded = JsonConvert.DeserializeObject(configJson,
+ new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate });
+ if (!validate(loaded))
+ {
+ Plugin.log("Falling back to default config (file will not be overwritten)");
+ // don't try to modify the original default when disabling serialization
+ instance = DEFAULT_CONFIG.MemberwiseClone() as Configs;
+ // since we couldn't read the existing config, don't overwrite it
+ instance.noSerialize = true;
+ return;
+ }
+ if (outdated(loaded))
+ {
+ if (loaded.isDefaultConfig)
+ {
+ loaded = DEFAULT_CONFIG;
+ instance = loaded;
+ save();
+ return;
+ }
+ // put config update logic here
+ bool isDirty = false; // set to true if you modify the config
+ if (loaded.majorVersion == 2 && loaded.minorVersion == 0)
+ {
+ loaded.beforeCutAngleJudgments = new SegmentJudgment[] { DEFAULT_SEGMENT_JUDGMENT };
+ loaded.accuracyJudgments = new SegmentJudgment[] { DEFAULT_SEGMENT_JUDGMENT };
+ loaded.afterCutAngleJudgments = new SegmentJudgment[] { DEFAULT_SEGMENT_JUDGMENT };
+ loaded.minorVersion = 1;
+ loaded.patchVersion = 0;
+ isDirty = true;
+ }
+ if (loaded.majorVersion == 2 && loaded.minorVersion == 1 && loaded.patchVersion < Plugin.patchVersion)
+ {
+ loaded.patchVersion = Plugin.patchVersion;
+ isDirty = true;
+ }
+ if (isDirty) save();
+ }
+ instance = loaded;
+ }
+
+ public static void save(bool force = false)
+ {
+ Plugin.log("Writing file...");
+ if (instance.noSerialize && !force) return;
+ File.WriteAllText(fullPath, JsonConvert.SerializeObject(instance,
+ Formatting.Indented,
+ new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate }));
+ Plugin.log("File written.");
+ }
+
+ public static bool validate(Configs config)
+ {
+ if (tooNew(config))
+ {
+ Plugin.log("Config is for a newer version of HitScoreVisualizer!");
+ return false;
+ }
+ bool judgmentsValid = true;
+ foreach (Judgment j in config.judgments)
+ {
+ if (!validateJudgment(j)) judgmentsValid = false;
+ }
+ if (!judgmentsValid) return false;
+ return true;
+ }
+
+ public static bool validateJudgment(Judgment judgment)
+ {
+ if (judgment.color.Length != 4)
+ {
+ Console.WriteLine("Judgment \"" + judgment.text + "\" with threshold " + judgment.threshold +
+ "has invalid color!");
+ Console.WriteLine("Make sure to include exactly 4 numbers for each judgment's color!");
+ return false;
+ }
+ return true;
+ }
+
+ public static bool outdated(Configs config)
+ {
+ if (config.majorVersion < Plugin.majorVersion) return true;
+ if (config.minorVersion < Plugin.minorVersion) return true;
+ return false;
+ }
+
+ public static bool tooNew(Configs config)
+ {
+ if (config.majorVersion > Plugin.majorVersion) return true;
+ if (config.minorVersion > Plugin.minorVersion) return true;
+ return false;
+ }
+
+ public static void resetToDefault()
+ {
+ instance = DEFAULT_CONFIG;
+ }
+
+ public static void judge(FlyingScoreEffect scoreEffect, NoteCutInfo noteCutInfo, SaberAfterCutSwingRatingCounter saberAfterCutSwingRatingCounter, ref Color color, int score, int before, int after, int accuracy)
+ {
+ // as of 0.13, the TextMeshPro is private; use reflection to grab it out of a private field
+ TextMeshPro text = scoreEffect.getPrivateField("_text");
+ // enable rich text
+ text.richText = true;
+ // disable word wrap, make sure full text displays
+ text.enableWordWrapping = false;
+ text.overflowMode = TextOverflowModes.Overflow;
+
+ Judgment judgment = DEFAULT_JUDGMENT;
+ int index; // save in case we need to fade
+ for (index = 0; index < instance.judgments.Length; index++)
+ {
+ Judgment j = instance.judgments[index];
+ if (score >= j.threshold)
+ {
+ judgment = j;
+ break;
+ }
+ }
+ if (judgment.fade)
+ {
+ Judgment fadeJudgment = instance.judgments[index - 1];
+ Color baseColor = toColor(judgment.color);
+ Color fadeColor = toColor(fadeJudgment.color);
+ float lerpDistance = Mathf.InverseLerp(judgment.threshold, fadeJudgment.threshold, score);
+ color = Color.Lerp(baseColor, fadeColor, lerpDistance);
+ }
+ else
+ {
+ color = toColor(judgment.color);
+ }
+
+ if (instance.displayMode == "format")
+ {
+ StringBuilder formattedBuilder = new StringBuilder();
+ string formatString = judgment.text;
+ int nextPercentIndex = formatString.IndexOf('%');
+ while (nextPercentIndex != -1)
+ {
+ formattedBuilder.Append(formatString.Substring(0, nextPercentIndex));
+ if (formatString.Length == nextPercentIndex + 1)
+ {
+ formatString += " ";
+ }
+ char specifier = formatString[nextPercentIndex + 1];
+
+ switch (specifier)
+ {
+ case 'b':
+ formattedBuilder.Append(before);
+ break;
+ case 'c':
+ formattedBuilder.Append(accuracy);
+ break;
+ case 'a':
+ formattedBuilder.Append(after);
+ break;
+ case 'B':
+ formattedBuilder.Append(judgeSegment(before, instance.beforeCutAngleJudgments));
+ break;
+ case 'C':
+ formattedBuilder.Append(judgeSegment(accuracy, instance.accuracyJudgments));
+ break;
+ case 'A':
+ formattedBuilder.Append(judgeSegment(after, instance.afterCutAngleJudgments));
+ break;
+ case 's':
+ formattedBuilder.Append(score);
+ break;
+ case 'p':
+ formattedBuilder.Append(string.Format("{0:0}", score / 110d * 100));
+ break;
+ case '%':
+ formattedBuilder.Append("%");
+ break;
+ case 'n':
+ formattedBuilder.Append("\n");
+ break;
+ default:
+ formattedBuilder.Append("%" + specifier);
+ break;
+ }
+
+ formatString = formatString.Remove(0, nextPercentIndex + 2);
+ nextPercentIndex = formatString.IndexOf('%');
+ }
+ formattedBuilder.Append(formatString);
+
+ text.text = formattedBuilder.ToString();
+ return;
+ }
+
+ if (instance.displayMode == "textOnly")
+ {
+ text.text = judgment.text;
+ return;
+ }
+ if (instance.displayMode == "numeric")
+ {
+ text.text = score.ToString();
+ return;
+ }
+ if (instance.displayMode == "scoreOnTop")
+ {
+ text.text = score + "\n" + judgment.text + "\n";
+ return;
+ }
+ text.text = judgment.text + "\n" + score + "\n";
+ }
+
+ public static Color toColor(float[] rgba)
+ {
+ return new Color(rgba[0], rgba[1], rgba[2], rgba[3]);
+ }
+
+ public static string judgeSegment(int scoreForSegment, SegmentJudgment[] judgments)
+ {
+ if (judgments == null) return "";
+ foreach(SegmentJudgment j in judgments)
+ {
+ if (scoreForSegment >= j.threshold) return j.text;
+ }
+ return "";
+ }
+ }
+}
diff --git a/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectHandleSaberAfterCutSwingRatingCounterDidChangeEvent.cs b/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectHandleSaberAfterCutSwingRatingCounterDidChangeEvent.cs
index 266ec89..3741c75 100644
--- a/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectHandleSaberAfterCutSwingRatingCounterDidChangeEvent.cs
+++ b/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectHandleSaberAfterCutSwingRatingCounterDidChangeEvent.cs
@@ -16,7 +16,7 @@ static bool Prefix(SaberAfterCutSwingRatingCounter saberAfterCutSwingRatingCount
{
ScoreController.ScoreWithoutMultiplier(____noteCutInfo, saberAfterCutSwingRatingCounter, out int before_plus_acc, out int after, out int accuracy);
int total = before_plus_acc + after;
- Config.judge(__instance, ____noteCutInfo, saberAfterCutSwingRatingCounter, ref ____color, total, before_plus_acc - accuracy, after, accuracy);
+ Configs.judge(__instance, ____noteCutInfo, saberAfterCutSwingRatingCounter, ref ____color, total, before_plus_acc - accuracy, after, accuracy);
return false;
}
}
diff --git a/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectInitAndPresent.cs b/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectInitAndPresent.cs
index a9709a9..85841f4 100644
--- a/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectInitAndPresent.cs
+++ b/HitScoreVisualizer/Harmony Patches/FlyingScoreEffectInitAndPresent.cs
@@ -22,7 +22,7 @@ static void Postfix(SaberAfterCutSwingRatingCounter saberAfterCutSwingRatingCoun
{
ScoreController.ScoreWithoutMultiplier(noteCutInfo, saberAfterCutSwingRatingCounter, out int before_plus_acc, out int after, out int accuracy);
int total = before_plus_acc + after;
- Config.judge(__instance, noteCutInfo, saberAfterCutSwingRatingCounter, ref ____color, total, before_plus_acc - accuracy, after, accuracy);
+ Configs.judge(__instance, noteCutInfo, saberAfterCutSwingRatingCounter, ref ____color, total, before_plus_acc - accuracy, after, accuracy);
}
}
}
diff --git a/HitScoreVisualizer/HitScoreVisualizer.csproj b/HitScoreVisualizer/HitScoreVisualizer.csproj
index 2bbbad9..4e3faa7 100644
--- a/HitScoreVisualizer/HitScoreVisualizer.csproj
+++ b/HitScoreVisualizer/HitScoreVisualizer.csproj
@@ -1,20 +1,22 @@
-
-
+
Debug
AnyCPU
- {7D8A403B-A4EE-42AD-85EF-ACFD7F087A79}
+ 8.0.30703
+ 2.0
+ {B05E8128-7D91-4C6A-A403-6FC998CE8B39}
Library
Properties
HitScoreVisualizer
HitScoreVisualizer
- v4.6
+ v4.7.2
512
+ $(SolutionDir)=C:\
+ portable
true
- full
false
bin\Debug\
DEBUG;TRACE
@@ -31,21 +33,23 @@
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\0Harmony.dll
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\0Harmony.dll
-
- False
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Assembly-CSharp.dll
+
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Assembly-CSharp.dll
+
+
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Plugins\BeatSaberCustomUI.dll
-
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Assembly-CSharp-firstpass.dll
+
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Plugins\BS_Utils.dll
-
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\IllusionPlugin.dll
+
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\IPA.Loader.dll
-
+
False
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Newtonsoft.Json.dll
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Newtonsoft.Json.dll
@@ -53,28 +57,41 @@
-
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Unity.TextMeshPro.dll
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Unity.TextMeshPro.dll
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.dll
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.dll
- ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll
+
+
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UI.dll
+
+
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UIModule.dll
+
+
+ ..\..\..\..\..\..\..\Programs\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.VRModule.dll
-
+
+
+
-
+
+
+ copy /Y "$(TargetDir)$(TargetName).dll" "C:\Programs\Steam\steamapps\common\Beat Saber\Plugins\$(TargetName).dll"
+
\ No newline at end of file
diff --git a/HitScoreVisualizer/Logger.cs b/HitScoreVisualizer/Logger.cs
new file mode 100644
index 0000000..178c123
--- /dev/null
+++ b/HitScoreVisualizer/Logger.cs
@@ -0,0 +1,9 @@
+using IPALogger = IPA.Logging.Logger;
+
+namespace HitScoreVisualizer
+{
+ internal static class Logger
+ {
+ public static IPALogger log { get; set; }
+ }
+}
diff --git a/HitScoreVisualizer/Plugin.cs b/HitScoreVisualizer/Plugin.cs
index 7c7955c..3e281df 100644
--- a/HitScoreVisualizer/Plugin.cs
+++ b/HitScoreVisualizer/Plugin.cs
@@ -1,24 +1,39 @@
using Harmony;
-using IllusionPlugin;
+using IPA;
+using IPA.Config;
+using IPA.Utilities;
using System;
using System.Reflection;
using UnityEngine.SceneManagement;
+using IPALogger = IPA.Logging.Logger;
namespace HitScoreVisualizer
{
- public class Plugin : IPlugin
+ public class Plugin : IBeatSaberPlugin
{
- public string Name => "HitScoreVisualizer";
- public string Version => "2.1.6";
+ internal static Ref config;
+ internal static IConfigProvider configProvider;
internal const int majorVersion = 2;
internal const int minorVersion = 1;
internal const int patchVersion = 6;
+ public void Init(IPALogger logger, [Config.Prefer("json")] IConfigProvider cfgProvider)
+ {
+ Logger.log = logger;
+ configProvider = cfgProvider;
+
+ config = cfgProvider.MakeLink((p, v) =>
+ {
+ if (v.Value == null || v.Value.RegenerateConfig)
+ p.Store(v.Value = new PluginConfig() { RegenerateConfig = false });
+ config = v;
+ });
+ }
+
public void OnApplicationStart()
{
- SceneManager.activeSceneChanged += SceneManagerOnActiveSceneChanged;
- SceneManager.sceneLoaded += SceneManager_sceneLoaded;
+ Logger.log.Debug("OnApplicationStart");
try
{
var harmony = HarmonyInstance.Create("com.arti.BeatSaber.HitScoreVisualizer");
@@ -30,38 +45,37 @@ public void OnApplicationStart()
"installed the plugin properly, as the Harmony DLL should have been installed with it.");
Console.WriteLine(e);
}
- Config.load();
+ Configs.load();
}
- private void SceneManagerOnActiveSceneChanged(Scene arg0, Scene arg1)
+ public void OnApplicationQuit()
{
+ Logger.log.Debug("OnApplicationQuit");
}
- private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
+ public void OnFixedUpdate()
{
- }
- public void OnApplicationQuit()
- {
- SceneManager.activeSceneChanged -= SceneManagerOnActiveSceneChanged;
- SceneManager.sceneLoaded -= SceneManager_sceneLoaded;
}
- public void OnLevelWasLoaded(int level)
+ public void OnUpdate()
{
}
- public void OnLevelWasInitialized(int level)
+ public void OnActiveSceneChanged(Scene prevScene, Scene nextScene)
{
+
}
- public void OnUpdate()
+ public void OnSceneLoaded(Scene scene, LoadSceneMode sceneMode)
{
+
}
- public void OnFixedUpdate()
+ public void OnSceneUnloaded(Scene scene)
{
+
}
internal static void log(object message)
diff --git a/HitScoreVisualizer/PluginConfig.cs b/HitScoreVisualizer/PluginConfig.cs
new file mode 100644
index 0000000..ed1d148
--- /dev/null
+++ b/HitScoreVisualizer/PluginConfig.cs
@@ -0,0 +1,7 @@
+namespace HitScoreVisualizer
+{
+ internal class PluginConfig
+ {
+ public bool RegenerateConfig = true;
+ }
+}
diff --git a/HitScoreVisualizer/Properties/AssemblyInfo.cs b/HitScoreVisualizer/Properties/AssemblyInfo.cs
index e0789dc..64f88a2 100644
--- a/HitScoreVisualizer/Properties/AssemblyInfo.cs
+++ b/HitScoreVisualizer/Properties/AssemblyInfo.cs
@@ -2,7 +2,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("HitScoreVisualizer")]
@@ -10,27 +10,27 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HitScoreVisualizer")]
-[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("7d8a403b-a4ee-42ad-85ef-acfd7f087a79")]
+[assembly: Guid("b05e8128-7d91-4c6a-a403-6fc998ce8b39")]
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.1.6.0")]
-[assembly: AssemblyFileVersion("2.1.6.0")]
+[assembly: AssemblyVersion("0.0.1")]
+[assembly: AssemblyFileVersion("0.0.1")]
diff --git a/HitScoreVisualizer/manifest.json b/HitScoreVisualizer/manifest.json
new file mode 100644
index 0000000..f36618f
--- /dev/null
+++ b/HitScoreVisualizer/manifest.json
@@ -0,0 +1,10 @@
+{
+ "$schema": "https://raw.githubusercontent.com/nike4613/ModSaber-MetadataFileSchema/master/Schema.json",
+ "author": "Auros",
+ "description": "",
+ "features": [],
+ "gameVersion": "0.13.2",
+ "id": null,
+ "name": "HitScoreVisualizer",
+ "version": "2.1.6"
+}
\ No newline at end of file