using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SilkRoomUtils")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+275c2df1d9c5d7fdc7136ab8998caeab3ee513b8")]
[assembly: AssemblyProduct("SilkRoomUtils")]
[assembly: AssemblyTitle("SilkRoomUtils")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace SilksongRooms._1
{
public interface IRoomIntegrator
{
void RegisterRooms(IReadOnlyList<LoadedRoom> rooms);
void OnSceneLoaded(Scene scene, LoadSceneMode mode, IReadOnlyList<LoadedRoom> rooms);
}
[Serializable]
public class RoomDefinition
{
public string id = string.Empty;
public string bundle = string.Empty;
public string prefab = string.Empty;
public Vector3 entryPoint;
public string[] tags = Array.Empty<string>();
public Connection[] connections = Array.Empty<Connection>();
}
[Serializable]
public class Connection
{
public string toRoomId = string.Empty;
public string doorName = string.Empty;
}
public class LoadedRoom
{
public RoomDefinition Definition = new RoomDefinition();
public AssetBundle? Bundle;
public GameObject? Prefab;
public string SourceJsonPath = string.Empty;
}
public sealed class RoomLoader
{
private readonly ManualLogSource _log;
public List<LoadedRoom> LoadedRooms { get; } = new List<LoadedRoom>();
public RoomLoader(ManualLogSource log)
{
_log = log;
}
public void LoadAll(string roomsFolder)
{
LoadedRooms.Clear();
AddFromFolder(roomsFolder);
}
public List<LoadedRoom> AddFromFolder(string roomsFolder)
{
List<LoadedRoom> list = new List<LoadedRoom>();
if (!Directory.Exists(roomsFolder))
{
_log.LogWarning((object)("Rooms folder does not exist: " + roomsFolder));
return list;
}
foreach (string item in Directory.EnumerateFiles(roomsFolder, "*.room.json", SearchOption.AllDirectories))
{
LoadedRoom loaded = TryLoadFromJsonFile(item, roomsFolder);
if (loaded != null)
{
int num = LoadedRooms.FindIndex((LoadedRoom r) => string.Equals(r.Definition.id, loaded.Definition.id, StringComparison.Ordinal));
if (num >= 0)
{
_log.LogWarning((object)("Room id '" + loaded.Definition.id + "' already loaded; replacing with definition from '" + item + "'."));
LoadedRooms[num] = loaded;
}
else
{
LoadedRooms.Add(loaded);
}
list.Add(loaded);
}
}
return list;
}
public LoadedRoom? AddFromJsonFile(string jsonPath, string? resolveRoot = null)
{
string resolveRoot2 = resolveRoot ?? Path.GetDirectoryName(jsonPath) ?? Environment.CurrentDirectory;
LoadedRoom loaded = TryLoadFromJsonFile(jsonPath, resolveRoot2);
if (loaded == null)
{
return null;
}
int num = LoadedRooms.FindIndex((LoadedRoom r) => string.Equals(r.Definition.id, loaded.Definition.id, StringComparison.Ordinal));
if (num >= 0)
{
_log.LogWarning((object)("Room id '" + loaded.Definition.id + "' already loaded; replacing with definition from '" + jsonPath + "'."));
LoadedRooms[num] = loaded;
}
else
{
LoadedRooms.Add(loaded);
}
return loaded;
}
public bool TryGetRoom(string id, out LoadedRoom? room)
{
string id2 = id;
room = LoadedRooms.FirstOrDefault((LoadedRoom r) => string.Equals(r.Definition.id, id2, StringComparison.Ordinal));
return room != null;
}
private LoadedRoom? TryLoadFromJsonFile(string jsonPath, string resolveRoot)
{
try
{
RoomDefinition roomDefinition = JsonUtility.FromJson<RoomDefinition>(File.ReadAllText(jsonPath));
if (roomDefinition == null || string.IsNullOrWhiteSpace(roomDefinition.id))
{
_log.LogWarning((object)("Skipping invalid room: " + jsonPath));
return null;
}
LoadedRoom loadedRoom = new LoadedRoom
{
Definition = roomDefinition,
SourceJsonPath = jsonPath
};
if (!string.IsNullOrWhiteSpace(roomDefinition.bundle))
{
string text = Path.Combine(resolveRoot, roomDefinition.bundle.Replace('/', Path.DirectorySeparatorChar));
if (File.Exists(text))
{
loadedRoom.Bundle = AssetBundle.LoadFromFile(text);
if ((Object)(object)loadedRoom.Bundle == (Object)null)
{
_log.LogError((object)("Failed to load AssetBundle for room '" + roomDefinition.id + "' at '" + text + "'."));
}
else
{
if (!string.IsNullOrWhiteSpace(roomDefinition.prefab))
{
loadedRoom.Prefab = loadedRoom.Bundle.LoadAsset<GameObject>(roomDefinition.prefab);
if ((Object)(object)loadedRoom.Prefab == (Object)null)
{
_log.LogWarning((object)("Prefab '" + roomDefinition.prefab + "' not found in bundle for room '" + roomDefinition.id + "'."));
}
}
if ((Object)(object)loadedRoom.Prefab == (Object)null)
{
string[] allAssetNames = loadedRoom.Bundle.GetAllAssetNames();
foreach (string text2 in allAssetNames)
{
GameObject val = loadedRoom.Bundle.LoadAsset<GameObject>(text2);
if ((Object)(object)val != (Object)null)
{
loadedRoom.Prefab = val;
break;
}
}
if ((Object)(object)loadedRoom.Prefab == (Object)null)
{
_log.LogWarning((object)("No GameObject prefab found in bundle for room '" + roomDefinition.id + "'."));
}
}
}
}
else
{
_log.LogError((object)("Bundle path not found for room '" + roomDefinition.id + "': " + text));
}
}
_log.LogDebug((object)("Loaded definition for room '" + roomDefinition.id + "'."));
return loadedRoom;
}
catch (Exception arg)
{
_log.LogError((object)$"Error loading room JSON '{jsonPath}': {arg}");
return null;
}
}
}
public static class RoomsApi
{
private static readonly List<Action<SilksongRooms__1Plugin>> _pending = new List<Action<SilksongRooms__1Plugin>>();
public static event Action<IReadOnlyList<LoadedRoom>>? RoomsAdded;
internal static void Bind(SilksongRooms__1Plugin plugin)
{
if (_pending.Count <= 0)
{
return;
}
Action<SilksongRooms__1Plugin>[] array = _pending.ToArray();
foreach (Action<SilksongRooms__1Plugin> action in array)
{
try
{
action(plugin);
}
catch (Exception)
{
}
}
_pending.Clear();
}
public static void RegisterRoomsFolder(string folder)
{
string folder2 = folder;
SilksongRooms__1Plugin instanceOrNull = SilksongRooms__1Plugin.InstanceOrNull;
if (instanceOrNull != null)
{
Do(instanceOrNull);
}
else
{
_pending.Add(Do);
}
void Do(SilksongRooms__1Plugin p)
{
IReadOnlyList<LoadedRoom> obj = p.RegisterRoomsFolder(folder2);
RoomsApi.RoomsAdded?.Invoke(obj);
}
}
public static void RegisterRoomJson(string jsonFilePath, string? resolveRoot = null)
{
string jsonFilePath2 = jsonFilePath;
string resolveRoot2 = resolveRoot;
SilksongRooms__1Plugin instanceOrNull = SilksongRooms__1Plugin.InstanceOrNull;
if (instanceOrNull != null)
{
Do(instanceOrNull);
}
else
{
_pending.Add(Do);
}
void Do(SilksongRooms__1Plugin p)
{
LoadedRoom loadedRoom = p.RegisterRoomJson(jsonFilePath2, resolveRoot2);
if (loadedRoom != null)
{
RoomsApi.RoomsAdded?.Invoke(new LoadedRoom[1] { loadedRoom });
}
}
}
public static string GetDefaultRoomsFolder(string pluginName)
{
return Path.Combine(Paths.PluginPath, pluginName, "Rooms");
}
}
public sealed class SilksongRoomIntegrator : IRoomIntegrator
{
private readonly ManualLogSource _log;
public SilksongRoomIntegrator(ManualLogSource log)
{
_log = log;
}
public void RegisterRooms(IReadOnlyList<LoadedRoom> rooms)
{
_log.LogInfo((object)$"Registering {rooms.Count} loaded room(s).");
foreach (LoadedRoom room in rooms)
{
_log.LogInfo((object)("Room: " + room.Definition.id + " | Bundle: " + (Object.op_Implicit((Object)(object)room.Bundle) ? ((Object)room.Bundle).name : "(none)") + " | Prefab: " + (Object.op_Implicit((Object)(object)room.Prefab) ? ((Object)room.Prefab).name : "(none)")));
}
}
public void OnSceneLoaded(Scene scene, LoadSceneMode mode, IReadOnlyList<LoadedRoom> rooms)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
GameObject val = (GameObject)(((object)GameObject.Find("__RoomsSandbox")) ?? ((object)new GameObject("__RoomsSandbox")));
Object.DontDestroyOnLoad((Object)(object)val);
foreach (LoadedRoom room in rooms)
{
if (!((Object)(object)room.Prefab == (Object)null) && !((Object)(object)val.transform.Find(room.Definition.id) != (Object)null))
{
GameObject obj = Object.Instantiate<GameObject>(room.Prefab, room.Definition.entryPoint, Quaternion.identity, val.transform);
((Object)obj).name = room.Definition.id;
obj.SetActive(false);
_log.LogInfo((object)("Spawned prefab for room '" + room.Definition.id + "' into sandbox (inactive). Enable it manually to preview."));
}
}
}
}
[BepInPlugin("io.github.silksongrooms__1", "SilkRoomUtils", "0.1.0")]
public class SilksongRooms__1Plugin : BaseUnityPlugin
{
private static ManualLogSource? _log;
private RoomLoader? _loader;
private IRoomIntegrator? _integrator;
public const string Id = "io.github.silksongrooms__1";
internal static ManualLogSource LogS => _log ?? (_log = Logger.CreateLogSource("SilksongRooms"));
internal static SilksongRooms__1Plugin? InstanceOrNull { get; private set; }
private string RoomsFolder => Path.Combine(Paths.PluginPath, ((BaseUnityPlugin)this).Info.Metadata.Name, "Rooms");
public static string Name => "SilkRoomUtils";
public static string Version => "0.1.0";
private void Awake()
{
InstanceOrNull = this;
Directory.CreateDirectory(RoomsFolder);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " (io.github.silksongrooms__1) has loaded! Rooms folder: " + RoomsFolder));
_loader = new RoomLoader(((BaseUnityPlugin)this).Logger);
_integrator = new SilksongRoomIntegrator(((BaseUnityPlugin)this).Logger);
RoomsApi.Bind(this);
SafeLoadAllRooms();
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
InstanceOrNull = null;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (_loader == null || _integrator == null)
{
return;
}
try
{
_integrator.OnSceneLoaded(scene, mode, _loader.LoadedRooms);
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogError((object)$"Room integrator OnSceneLoaded failed: {arg}");
}
}
private void SafeLoadAllRooms()
{
if (_loader == null || _integrator == null)
{
return;
}
try
{
_loader.LoadAll(RoomsFolder);
_integrator.RegisterRooms(_loader.LoadedRooms);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded {_loader.LoadedRooms.Count} room(s).");
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to load rooms: {arg}");
}
}
internal IReadOnlyList<LoadedRoom> RegisterRoomsFolder(string folder)
{
if (_loader == null || _integrator == null)
{
return Array.Empty<LoadedRoom>();
}
List<LoadedRoom> list = _loader.AddFromFolder(folder);
if (list.Count > 0)
{
_integrator.RegisterRooms(_loader.LoadedRooms);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Added {list.Count} room(s) from '{folder}'. Total: {_loader.LoadedRooms.Count}.");
}
else
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("No rooms found in '" + folder + "'."));
}
return list;
}
internal LoadedRoom? RegisterRoomJson(string jsonFilePath, string? resolveRoot)
{
if (_loader == null || _integrator == null)
{
return null;
}
LoadedRoom loadedRoom = _loader.AddFromJsonFile(jsonFilePath, resolveRoot);
if (loadedRoom != null)
{
_integrator.RegisterRooms(_loader.LoadedRooms);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Added room '{loadedRoom.Definition.id}' from '{jsonFilePath}'. Total: {_loader.LoadedRooms.Count}.");
}
return loadedRoom;
}
}
}