Initial commit

This commit is contained in:
2026-05-30 18:28:51 -04:00
commit d78e8d0910
11 changed files with 1337 additions and 0 deletions

209
Core/BuildSettings.cs Normal file
View File

@@ -0,0 +1,209 @@
// Undead Universal Patch - for patching Rec Room builds
// Copyright (C) 2026 proxnet.dev (@zombieb)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
using HarmonyLib;
using System;
using System.Linq;
using System.Reflection;
using UndeadUniversalPatch.Core.Exceptions;
namespace UndeadUniversalPatch.Core;
internal static class BuildSettings
{
public static Assembly GetAssemblyCSharp()
{
if (!Init.GetIsRecRoom())
throw new NotRecRoomException();
return AccessTools.TypeByName("BootSequence").Assembly; // always unobfuscated
}
private static Type GetBuildSettings()
{
var assembly = GetAssemblyCSharp();
try
{
Type type = assembly.GetTypes().First(type => Symbols.BuildSettings.Contains(type.Name));
return type;
} catch (ReflectionTypeLoadException ex)
{
Type type = ex.Types.First(type => Symbols.BuildSettings.Contains(type.Name));
return type;
} catch
{
return null;
}
}
public static string GetVersion()
{
var unknown = "Unknown Version";
var buildSettings = GetBuildSettings();
if (buildSettings == null)
#if NET35
{
try
{
// doesn't exist? -> error will be caught & unknown will be returned
var field = AccessTools.Field("PUNNetworkManager:BUILD_VERSION");
if (field != null) return (string)field.GetValue(null);
else return "Unknown Legacy Version";
} catch
{
return unknown;
}
}
#else
return unknown;
#endif
Func<string, bool> check = (string value) =>
{
if (value == null) return false;
return value.StartsWith("20") || value.EndsWith("_EA");
};
try
{
#if NET6_0
return (string)buildSettings.GetRuntimeProperties().Where(prop => prop.PropertyType == typeof(string)).First(prop =>
{
var value = (string)prop.GetValue(null);
return check(value);
}).GetValue(null);
#else
return (string)buildSettings.GetFields().Where(field => field.FieldType == typeof(string)).First(field =>
{
var value = (string)field.GetValue(null);
return check(value);
}).GetValue(null);
#endif
}
catch
{
return unknown;
}
}
public static string GetBuildTimestamp()
{
var unknown = "Unknown Timestamp";
var buildSettings = GetBuildSettings();
if (buildSettings == null) return unknown;
// Only one `long` exists on BuildSettings across all supported builds
try
{
#if NET6_0
var foundProp = buildSettings.GetRuntimeProperties()
.First(prop => prop.PropertyType == typeof(long));
var value = (long)foundProp.GetValue(null);
return new DateTime(value).ToString();
#else
var foundField = buildSettings.GetFields()
.First(field => field.FieldType == typeof(long));
var value = (long)foundField.GetValue(null);
return new DateTime(value).ToString();
#endif
}
catch
{
return unknown;
}
}
private static class Symbols
{
// type list compiled by @zombieb
public static string[] BuildSettings = [
"BuildSettings",
"BBHENFCNLAB",
"KMJJGELKNAP",
"FJEEPOKGDNG",
"LACHJMJGMPK",
"NNBKABHFGFB",
"KMGJBIHAAJL",
"FALNDOJFPMN",
"IODMKGDNMID",
"HIPJBMLBLHH",
"LEADBBLICBL",
"NPPACKKFLIK",
"MOFAAFLMFJO",
"EMIDOAHOJNO",
"IKJNDDBHIAC",
"OOCIKEIJMCA",
"HPFCOJFIIKK",
"MONBJIBCJFA",
"GFDKEKGOMCP",
"MIMHAGFDGND",
"LFJMHJPHKOK",
"NOHBMMJBMIP",
"GJBEJNGDEJM",
"OGBGLFJGKJL",
"PEJOGOOEOKE",
"FDKFNHNNDEE",
"EDNIOJBEKLL",
"FEKFIFPGDDP",
"POOFEABAPOB",
"JHFKADKFKPD",
"GGKABOEOKMI",
"FAPDBIGGJHM",
"EPKEIOCFFMO",
"ECLPNEHKLEP",
"BGMDPOMLCKD",
"IMJIAGILBOG",
"OGGKBKOBHLP",
"DMAKDOEIOFE",
"HHGCEDNGMDD",
"OFDPCKGMCFG",
"FPABNHKCIDD",
"NEOOKMCECAL",
"CKEBMNKBEAH",
"IBPMLICGIOI",
"LMJOEPJHBLC",
"HJINOEPLIMF",
"JMHFJIBKCMG",
"HJKAEMGCIGB",
"BNOEINBHPIG",
"AJJAIFIKCJP",
"FCPHGJMAGPI",
"DDCENHLJGNM",
"AEPEEKCCDJL",
"IDDIAODMAPP",
"CHIMGKLHFMK",
"OGDOAJJPBOC",
"EMABNNHNJIB",
"JNEAMPKAHFM",
"FPGILFHDJNI",
"MDPMNBEPOKF",
"FNKGHFILBEE",
"AEOMDHAKPGC",
"OGEBJBBMDEO",
"CJMCNIDOMCP",
"LCCKMCOLKFI",
"DEIHAEKLPDJ",
"LENMMNLPJOL",
"JKNIDJECBFD",
"FMEMABGECKK",
"HAOBGEPJMAN",
"FDCGGKFBOPN",
"OKCPMCEGCOK",
"BNKCNOFCGDK"
];
}
}

View File

@@ -0,0 +1,19 @@
// Undead Universal Patch - for patching Rec Room builds
// Copyright (C) 2026 proxnet.dev (@zombieb)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
using System;
namespace UndeadUniversalPatch.Core.Exceptions;
public class NotRecRoomException : Exception
{
public NotRecRoomException() : base("Not a build of Rec Room") {}
}

53
Core/Init.cs Normal file
View File

@@ -0,0 +1,53 @@
// Undead Universal Patch - for patching Rec Room builds
// Copyright (C) 2026 proxnet.dev (@zombieb)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
using BepInEx.Logging;
using HarmonyLib;
using System;
using UndeadUniversalPatch.Core.Exceptions;
namespace UndeadUniversalPatch.Core;
public static class Init
{
public static ManualLogSource Log = LoggerUtils.CreateLogSource("Init");
public static bool IsMono;
private static Harmony _hi = new(PluginInfo.Uuid);
public static void Startup(bool isMono)
{
try
{
IsMono = isMono;
if (!GetIsRecRoom()) throw new NotRecRoomException();
Log.LogInfo(LoggerUtils.MultiLine([
"Runtime Information",
$"Is Mono : {IsMono}",
$"Version : {BuildSettings.GetVersion()}",
$"Timestamp : {BuildSettings.GetBuildTimestamp()}"
]));
_hi.PatchAll();
} catch (Exception ex)
{
Log.LogError($"Failed to initialize! Something went terribly wrong!\n{ex}");
}
}
public static bool GetIsRecRoom()
{
return AccessTools.TypeByName("BootSequence") != null;
}
}

27
Core/LoggerUtils.cs Normal file
View File

@@ -0,0 +1,27 @@
// Undead Universal Patch - for patching Rec Room builds
// Copyright (C) 2026 proxnet.dev (@zombieb)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
using BepInEx.Logging;
namespace UndeadUniversalPatch.Core;
public class LoggerUtils
{
public static string MultiLine(params string[] lines)
{
return string.Join("\n ", lines);
}
public static ManualLogSource CreateLogSource(string id)
{
return Logger.CreateLogSource($"{PluginInfo.DisplayName}-{id}");
}
}