using OWML.Common; using QSB.OrbSync.WorldObjects; using QSB.TransformSync; using QSB.Utility; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine; namespace QSB.WorldSync { public static class QSBWorldSync { public static List OrbSyncList { get; } = new List(); public static List OldOrbList { get; set; } = new List(); public static List OldDialogueTrees { get; set; } = new List(); public static Dictionary DialogueConditions { get; } = new Dictionary(); public static List ShipLogFacts { get; } = new List(); private static readonly List WorldObjects = new List(); public static IEnumerable GetWorldObjects() => WorldObjects.OfType(); public static TWorldObject GetWorldFromId(int id) => GetWorldObjects().ToList()[id]; public static TWorldObject GetWorldFromUnity(TUnityObject unityObject) where TWorldObject : WorldObject where TUnityObject : MonoBehaviour { var allWorldObjects = GetWorldObjects(); if (allWorldObjects.Count() == 0) { DebugLog.ToConsole($"Error - No worldobjects exist of type {typeof(TWorldObject).Name}!", MessageType.Error); return null; } var correctWorldObject = allWorldObjects.First(x => x.AttachedObject == unityObject); return correctWorldObject; } public static int GetIdFromUnity(TUnityObject unityObject) where TWorldObject : WorldObject where TUnityObject : MonoBehaviour => GetWorldFromUnity(unityObject).ObjectId; public static int GetIdFromTypeSubset(TTypeSubset typeSubset) where TTypeSubset : IWorldObjectTypeSubset => GetWorldObjects().ToList().IndexOf(typeSubset); public static void RemoveWorldObjects() { var itemsToRemove = WorldObjects.Where(x => x is TWorldObject); foreach (var item in itemsToRemove) { try { item.OnRemoval(); } catch (Exception e) { DebugLog.ToConsole($"Error - Exception in OnRemoval() for {item.GetType()}. Message : {e.Message}, Stack trace : {e.StackTrace}", MessageType.Error); } } DebugLog.DebugWrite($"Removing {typeof(TWorldObject).Name} : {WorldObjects.Count(x => x is TWorldObject)} instances."); WorldObjects.RemoveAll(x => x is TWorldObject); } public static List Init() where TWorldObject : WorldObject where TUnityObject : MonoBehaviour { RemoveWorldObjects(); var list = Resources.FindObjectsOfTypeAll().ToList(); DebugLog.DebugWrite($"{typeof(TWorldObject).Name} init : {list.Count} instances.", MessageType.Info); for (var id = 0; id < list.Count; id++) { var obj = CreateWorldObject(); obj.Init(list[id], id); } return list; } private static TWorldObject CreateWorldObject() where TWorldObject : IWorldObject { var worldObject = (TWorldObject)Activator.CreateInstance(typeof(TWorldObject)); WorldObjects.Add(worldObject); return worldObject; } public static void RaiseEvent(object instance, string eventName) { if (!(instance.GetType() .GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic)? .GetValue(instance) is MulticastDelegate multiDelegate)) { return; } var delegateList = multiDelegate.GetInvocationList().ToList(); foreach (var del in delegateList) { del.DynamicInvoke(instance); } } public static void HandleSlotStateChange(NomaiInterfaceSlot slot, NomaiInterfaceOrb affectingOrb, bool state) { var slotList = GetWorldObjects().ToList(); if (!slotList.Any()) { return; } var qsbSlot = slotList.FirstOrDefault(x => x.AttachedObject == slot); if (qsbSlot == null) { DebugLog.ToConsole($"Error - No QSBOrbSlot found for {slot.name}!", MessageType.Error); return; } var orbSync = OrbSyncList.First(x => x.AttachedOrb == affectingOrb); if (orbSync.HasAuthority) { qsbSlot.HandleEvent(state, OldOrbList.IndexOf(affectingOrb)); } } public static void SetDialogueCondition(string name, bool state) { if (!QSBCore.IsServer) { DebugLog.ToConsole("Warning - Cannot write to condition dict when not server!", MessageType.Warning); return; } DialogueConditions[name] = state; } public static void AddFactReveal(string id, bool saveGame, bool showNotification) { if (!QSBCore.IsServer) { DebugLog.ToConsole("Warning - Cannot write to fact list when not server!", MessageType.Warning); return; } if (ShipLogFacts.Any(x => x.Id == id)) { DebugLog.ToConsole($"Warning - Fact id {id} already in list!", MessageType.Warning); return; } ShipLogFacts.Add(new FactReveal { Id = id, SaveGame = saveGame, ShowNotification = showNotification }); } } }