CVR Manager 1.0.0
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace CVRManager.Services;
|
||||
|
||||
public static class CacheGuardService
|
||||
{
|
||||
const string AssemblyName = "CVRCacheGuard";
|
||||
const string AssemblyFile = AssemblyName + ".dll";
|
||||
const int UserAssemblyType = 16;
|
||||
|
||||
static string Source => Path.Combine(AppContext.BaseDirectory, "CacheGuard");
|
||||
|
||||
static string Managed(string gameDir) => Path.Combine(gameDir, "ChilloutVR_Data", "Managed");
|
||||
|
||||
public static void Deploy(string gameDir, Action<string> log, string? source = null)
|
||||
{
|
||||
var managed = Managed(gameDir);
|
||||
var scripting = Path.Combine(gameDir, "ChilloutVR_Data", "ScriptingAssemblies.json");
|
||||
var init = Path.Combine(gameDir, "ChilloutVR_Data", "RuntimeInitializeOnLoads.json");
|
||||
source ??= Source;
|
||||
if (!Directory.Exists(source) || !Directory.Exists(managed) || !File.Exists(scripting) || !File.Exists(init)) return;
|
||||
|
||||
var changed = false;
|
||||
var deps = Path.Combine(managed, AssemblyName);
|
||||
Directory.CreateDirectory(deps);
|
||||
foreach (var file in Directory.EnumerateFiles(source, "*.dll"))
|
||||
{
|
||||
var name = Path.GetFileName(file);
|
||||
var target = name == AssemblyFile ? Path.Combine(managed, name) : Path.Combine(deps, name);
|
||||
changed |= CopyIfDifferent(file, target);
|
||||
}
|
||||
|
||||
var scriptingJson = JsonNode.Parse(File.ReadAllText(scripting))!.AsObject();
|
||||
var names = scriptingJson["names"]!.AsArray();
|
||||
var types = scriptingJson["types"]!.AsArray();
|
||||
if (!names.Any(n => n?.GetValue<string>() == AssemblyFile))
|
||||
{
|
||||
names.Add(AssemblyFile);
|
||||
types.Add(UserAssemblyType);
|
||||
WriteJson(scripting, scriptingJson);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
var initJson = JsonNode.Parse(File.ReadAllText(init))!.AsObject();
|
||||
var root = initJson["root"]!.AsArray();
|
||||
if (!root.Any(e => e?["assemblyName"]?.GetValue<string>() == AssemblyName))
|
||||
{
|
||||
root.Add(new JsonObject
|
||||
{
|
||||
["assemblyName"] = AssemblyName,
|
||||
["nameSpace"] = AssemblyName,
|
||||
["className"] = "Entry",
|
||||
["methodName"] = "Init",
|
||||
["loadTypes"] = 2,
|
||||
["isUnityClass"] = false,
|
||||
});
|
||||
WriteJson(init, initJson);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) log("Multi-instance cache guard added to this install.");
|
||||
}
|
||||
|
||||
public static void Remove(string gameDir, Action<string> log)
|
||||
{
|
||||
var data = Path.Combine(gameDir, "ChilloutVR_Data");
|
||||
var scripting = Path.Combine(data, "ScriptingAssemblies.json");
|
||||
var init = Path.Combine(data, "RuntimeInitializeOnLoads.json");
|
||||
var changed = false;
|
||||
|
||||
if (File.Exists(scripting))
|
||||
{
|
||||
var json = JsonNode.Parse(File.ReadAllText(scripting))!.AsObject();
|
||||
var names = json["names"]!.AsArray();
|
||||
var types = json["types"]!.AsArray();
|
||||
for (var i = names.Count - 1; i >= 0; i--)
|
||||
if (names[i]?.GetValue<string>() == AssemblyFile)
|
||||
{
|
||||
names.RemoveAt(i);
|
||||
if (i < types.Count) types.RemoveAt(i);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) WriteJson(scripting, json);
|
||||
}
|
||||
if (File.Exists(init))
|
||||
{
|
||||
var json = JsonNode.Parse(File.ReadAllText(init))!.AsObject();
|
||||
var root = json["root"]!.AsArray();
|
||||
var before = root.Count;
|
||||
for (var i = root.Count - 1; i >= 0; i--)
|
||||
if (root[i]?["assemblyName"]?.GetValue<string>() == AssemblyName) root.RemoveAt(i);
|
||||
if (root.Count != before)
|
||||
{
|
||||
WriteJson(init, json);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
var managed = Managed(gameDir);
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(managed, AssemblyFile));
|
||||
var deps = Path.Combine(managed, AssemblyName);
|
||||
if (Directory.Exists(deps)) Directory.Delete(deps, true);
|
||||
}
|
||||
catch (Exception e) when (e is IOException or UnauthorizedAccessException) { }
|
||||
if (changed) log("Multi-instance cache guard removed from this install.");
|
||||
}
|
||||
|
||||
static bool CopyIfDifferent(string source, string target)
|
||||
{
|
||||
var s = new FileInfo(source);
|
||||
var t = new FileInfo(target);
|
||||
if (t.Exists && t.Length == s.Length && t.LastWriteTimeUtc == s.LastWriteTimeUtc) return false;
|
||||
try
|
||||
{
|
||||
File.Copy(source, target, true);
|
||||
File.SetLastWriteTimeUtc(target, s.LastWriteTimeUtc);
|
||||
return true;
|
||||
}
|
||||
catch (IOException) when (t.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteJson(string path, JsonNode node) =>
|
||||
File.WriteAllText(path, node.ToJsonString(new JsonSerializerOptions { WriteIndented = false }), new System.Text.UTF8Encoding(false));
|
||||
}
|
||||
Reference in New Issue
Block a user