Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ServeYouRight v1.0.4
ServeYouRight.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ServeYouRight")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("sighsorry")] [assembly: AssemblyProduct("ServeYouRight")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyFileVersion("1.0.4")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.4.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 ServerSyncModTemplate { [BepInPlugin("sighsorry.ServeYouRight", "ServeYouRight", "1.0.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ServerSyncModTemplatePlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } private class ConfigurationManagerAttributes { public int? Order; } internal const string ModName = "ServeYouRight"; internal const string ModVersion = "1.0.4"; internal const string Author = "sighsorry"; private const string ModGUID = "sighsorry.ServeYouRight"; private static string ConfigFileName = "sighsorry.ServeYouRight.cfg"; private static string ConfigFileFullPath; private static ServerSyncModTemplatePlugin? _instance; private readonly Harmony _harmony = new Harmony("sighsorry.ServeYouRight"); public static readonly ManualLogSource ServerSyncModTemplateLogger; private FileSystemWatcher? _watcher; private readonly object _reloadLock = new object(); private static readonly object DynamicConfigLock; private DateTime _lastConfigReloadTime; private static readonly TimeSpan ConfigReloadDelay; private static readonly Dictionary<string, PerModCategoryConfig> PerModConfigs; private static bool _pendingDynamicConfigSave; public void Awake() { _instance = this; RunWithConfigAutoSaveDisabled(delegate { JotunnBridge.InitializeAndEnableModQuery(); Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChange)); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SaveConfigWithoutWatcher(); SetupWatcher(); }); } private void OnDestroy() { Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(OnLanguageChange)); _watcher?.Dispose(); _watcher = null; RunWithConfigAutoSaveDisabled(SaveConfigWithoutWatcher); } private void OnLanguageChange() { FeasterFoodInjector.RefreshFoodPiecesAndMenu(ObjectDB.instance); } private void SetupWatcher() { _watcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); _watcher.Changed += ReadConfigValues; _watcher.Created += ReadConfigValues; _watcher.Renamed += ReadConfigValues; _watcher.IncludeSubdirectories = true; _watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _watcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { DateTime utcNow = DateTime.UtcNow; if (utcNow - _lastConfigReloadTime < ConfigReloadDelay) { return; } _lastConfigReloadTime = utcNow; lock (_reloadLock) { if (!File.Exists(ConfigFileFullPath)) { ServerSyncModTemplateLogger.LogWarning((object)"Config file does not exist. Skipping reload."); return; } try { ServerSyncModTemplateLogger.LogDebug((object)"Reloading configuration..."); ReloadConfigValues(); ServerSyncModTemplateLogger.LogInfo((object)"Configuration reload complete."); } catch (Exception ex) { ServerSyncModTemplateLogger.LogError((object)("Error reloading configuration: " + ex.Message)); } finally { _lastConfigReloadTime = DateTime.UtcNow; } } } private void ReloadConfigValues() { RunWithConfigAutoSaveDisabled(delegate { ((BaseUnityPlugin)this).Config.Reload(); FeasterFoodInjector.RefreshFoodPiecesAndMenu(ObjectDB.instance); }); } private void RunWithConfigAutoSaveDisabled(Action action) { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; try { action(); } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } } private void SaveConfigWithoutWatcher() { FileSystemWatcher watcher = _watcher; bool flag = watcher?.EnableRaisingEvents ?? false; if (flag) { watcher.EnableRaisingEvents = false; } try { ((BaseUnityPlugin)this).Config.Save(); } finally { if (flag && watcher != null) { watcher.EnableRaisingEvents = true; } } } internal static bool UseModSpecificTab(FoodSourceMod mod, PieceCategory category) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected I4, but got Unknown PerModCategoryConfig orCreatePerModConfig = GetOrCreatePerModConfig(mod); return (category - 5) switch { 1 => orCreatePerModConfig.Food.Value == Toggle.On, 2 => orCreatePerModConfig.Meads.Value == Toggle.On, 0 => orCreatePerModConfig.Feasts.Value == Toggle.On, _ => false, }; } private static PerModCategoryConfig GetOrCreatePerModConfig(FoodSourceMod mod) { lock (DynamicConfigLock) { if (PerModConfigs.TryGetValue(mod.Id, out PerModCategoryConfig value)) { return value; } if ((Object)(object)_instance == (Object)null) { throw new InvalidOperationException("Plugin instance is not initialized."); } string text = "ServingTray - " + SanitizeConfigText(mod.DisplayName) + " (" + SanitizeConfigText(mod.Id) + ")"; PerModCategoryConfig perModCategoryConfig = new PerModCategoryConfig(_instance.config(text, "Food", Toggle.On, "If on, '" + mod.DisplayName + "' Food items go to 'Food - " + mod.DisplayName + "'. If off, they merge into vanilla Food.", 300), _instance.config(text, "Meads", Toggle.On, "If on, '" + mod.DisplayName + "' Mead items go to 'Meads - " + mod.DisplayName + "'. If off, they merge into vanilla Meads.", 200), _instance.config(text, "Feasts", Toggle.On, "If on, '" + mod.DisplayName + "' Feast items go to 'Feasts - " + mod.DisplayName + "'. If off, they merge into vanilla Feasts.", 100)); PerModConfigs[mod.Id] = perModCategoryConfig; _pendingDynamicConfigSave = true; return perModCategoryConfig; } } internal static void FlushPendingDynamicConfigSave() { ServerSyncModTemplatePlugin instance = _instance; if (!((Object)(object)instance == (Object)null)) { bool pendingDynamicConfigSave; lock (DynamicConfigLock) { pendingDynamicConfigSave = _pendingDynamicConfigSave; _pendingDynamicConfigSave = false; } if (pendingDynamicConfigSave) { instance.RunWithConfigAutoSaveDisabled(instance.SaveConfigWithoutWatcher); } } } private static string SanitizeConfigText(string text) { if (string.IsNullOrWhiteSpace(text)) { return "Unknown"; } char[] array = text.ToCharArray(); for (int i = 0; i < array.Length; i++) { if (array[i] == '\r' || "=\n\t\\\"'[]".IndexOf(array[i]) >= 0 || char.IsControl(array[i])) { array[i] = '_'; } } string text2 = new string(array).Trim(); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } return "Unknown"; } private ConfigEntry<T> config<T>(string group, string name, T value, string description, int order) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = order } })); } static ServerSyncModTemplatePlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ServerSyncModTemplateLogger = Logger.CreateLogSource("ServeYouRight"); DynamicConfigLock = new object(); ConfigReloadDelay = TimeSpan.FromSeconds(1.0); PerModConfigs = new Dictionary<string, PerModCategoryConfig>(StringComparer.OrdinalIgnoreCase); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] public static class ObjectDbAwakePatch { private static void Postfix(ObjectDB __instance) { FeasterFoodInjector.Inject(__instance); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] public static class ObjectDbCopyOtherDbPatch { private static void Postfix(ObjectDB __instance) { FeasterFoodInjector.Inject(__instance); } } [HarmonyPatch(typeof(Player), "SetPlaceMode")] public static class PlayerSetPlaceModePatch { private static void Postfix(Player __instance, PieceTable buildPieces) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)buildPieces == (Object)null) && buildPieces.m_canRemoveFeasts) { FeasterFoodInjector.RefreshFoodPiecesAndMenu(ObjectDB.instance, buildPieces); } } } [HarmonyPatch(typeof(PieceTable), "UpdateAvailable")] public static class PieceTableUpdateAvailablePatch { private static void Postfix(PieceTable __instance) { if (!((Object)(object)__instance == (Object)null) && __instance.m_canRemoveFeasts) { FeasterFoodInjector.ApplyCustomCategoryLabels(__instance); } } } [HarmonyPatch(typeof(ItemDrop), "MakePiece")] public static class ItemDropMakePiecePatch { private static void Postfix(ItemDrop __instance) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)__instance).GetComponent<ServeYouRightInjectedPieceMarker>() == (Object)null) { return; } ParticleSystem[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem obj in componentsInChildren) { obj.Stop(true, (ParticleSystemStopBehavior)0); obj.Clear(true); EmissionModule emission = obj.emission; ((EmissionModule)(ref emission)).enabled = false; MainModule main = obj.main; ((MainModule)(ref main)).playOnAwake = false; ParticleSystemRenderer component = ((Component)obj).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = false; } } } } internal static class FeasterFoodInjector { private static bool _isInjecting; private static readonly Dictionary<string, ModCategoryInfo> ModCategoryCache = new Dictionary<string, ModCategoryInfo>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, FoodSourceMod> SourceModHitCache = new Dictionary<string, FoodSourceMod>(StringComparer.OrdinalIgnoreCase); private static readonly object ModCategoryLock = new object(); internal static void RefreshFoodPiecesAndMenu(ObjectDB? objectDb, PieceTable? buildPieces = null) { Inject(objectDb); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { localPlayer.UpdateKnownRecipesList(); localPlayer.UpdateAvailablePiecesList(); ApplyCustomCategoryLabels(buildPieces ?? localPlayer.m_buildPieces); } } public static void Inject(ObjectDB? objectDb) { if (_isInjecting || (Object)(object)objectDb == (Object)null) { return; } _isInjecting = true; try { List<CandidateFood> candidateFoods = GetCandidateFoods(objectDb); if (candidateFoods.Count == 0) { return; } foreach (PieceTable feasterPieceTable in GetFeasterPieceTables(objectDb)) { int num = InjectIntoTable(feasterPieceTable, candidateFoods); if (num > 0) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogInfo((object)$"Added {num} mod food pieces to feaster table '{((Object)feasterPieceTable).name}'."); } ApplyCustomCategoryLabels(feasterPieceTable); } } catch (Exception arg) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogError((object)$"Failed to inject feaster foods: {arg}"); } finally { _isInjecting = false; ServerSyncModTemplatePlugin.FlushPendingDynamicConfigSave(); } } private static List<CandidateFood> GetCandidateFoods(ObjectDB objectDb) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Invalid comparison between Unknown and I4 //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) List<CandidateFood> list = new List<CandidateFood>(); FeastRoutingData feastRoutingData = BuildFeastRoutingData(objectDb); foreach (GameObject item in objectDb.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); SharedData val = component?.m_itemData?.m_shared; if (!((Object)(object)component == (Object)null) && val != null) { string prefabName = Utils.GetPrefabName(((Object)item).name); if (feastRoutingData.MaterialToResultPrefab.TryGetValue(prefabName, out GameObject value)) { list.Add(new CandidateFood(component, value, (PieceCategory)5)); } else if (!feastRoutingData.ResultPrefabNames.Contains(prefabName) && !((Object)(object)((Component)component).GetComponent<Feast>() != (Object)null) && (int)val.m_itemType == 2 && LooksLikeConsumableFood(val)) { PieceCategory category = (PieceCategory)(val.m_isDrink ? 7 : 6); list.Add(new CandidateFood(component, ((Component)component).gameObject, category)); } } } return list; } private static FeastRoutingData BuildFeastRoutingData(ObjectDB objectDb) { //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Invalid comparison between Unknown and I4 //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Invalid comparison between Unknown and I4 //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Invalid comparison between Unknown and I4 //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Invalid comparison between Unknown and I4 Dictionary<string, ItemDrop> dictionary = new Dictionary<string, ItemDrop>(StringComparer.OrdinalIgnoreCase); foreach (GameObject item in objectDb.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null)) { string prefabName = Utils.GetPrefabName(((Object)item).name); if (!dictionary.ContainsKey(prefabName)) { dictionary[prefabName] = component; } } } Dictionary<string, GameObject> dictionary2 = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, ItemDrop> item2 in dictionary) { string key = item2.Key; ItemDrop value = item2.Value; SharedData val = value.m_itemData?.m_shared; Feast component2 = ((Component)value).GetComponent<Feast>(); if ((Object)(object)component2 == (Object)null || val == null) { continue; } ItemDrop foodItem = component2.m_foodItem; string text = (((Object)(object)foodItem != (Object)null) ? Utils.GetPrefabName(((Object)((Component)foodItem).gameObject).name) : string.Empty); bool flag = !string.IsNullOrWhiteSpace(text) && !string.Equals(text, key, StringComparison.OrdinalIgnoreCase); SharedData val2 = foodItem?.m_itemData?.m_shared; bool flag2 = (Object)(object)foodItem != (Object)null && ((Object)(object)((Component)foodItem).GetComponent<Feast>() != (Object)null || (val2 != null && ((int)val2.m_itemType == 2 || LooksLikeConsumableFood(val2)))); if ((int)val.m_itemType == 1) { if (flag && flag2) { dictionary2[key] = ((Component)foodItem).gameObject; hashSet.Add(text); } } else if (flag && flag2 && (int)val.m_itemType != 2 && !LooksLikeConsumableFood(val)) { dictionary2[key] = ((Component)foodItem).gameObject; hashSet.Add(text); } else { hashSet.Add(key); } } foreach (KeyValuePair<string, ItemDrop> item3 in dictionary) { string key2 = item3.Key; SharedData val3 = item3.Value.m_itemData?.m_shared; if (val3 == null || (int)val3.m_itemType != 1) { continue; } ItemDrop appendToolTip = val3.m_appendToolTip; if (!((Object)(object)appendToolTip == (Object)null)) { string prefabName2 = Utils.GetPrefabName(((Object)((Component)appendToolTip).gameObject).name); if (!string.Equals(prefabName2, key2, StringComparison.OrdinalIgnoreCase) && (hashSet.Contains(prefabName2) || (Object)(object)((Component)appendToolTip).GetComponent<Feast>() != (Object)null)) { dictionary2[key2] = ((Component)appendToolTip).gameObject; hashSet.Add(prefabName2); } } } return new FeastRoutingData(dictionary2, hashSet); } private static bool LooksLikeConsumableFood(SharedData shared) { if (!(shared.m_food > 0f) && !(shared.m_foodStamina > 0f) && !(shared.m_foodEitr > 0f)) { return shared.m_isDrink; } return true; } private static IEnumerable<PieceTable> GetFeasterPieceTables(ObjectDB objectDb) { HashSet<PieceTable> uniqueTables = new HashSet<PieceTable>(); foreach (GameObject item in objectDb.m_items) { if (!((Object)(object)item == (Object)null)) { PieceTable val = item.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces; if (!((Object)(object)val == (Object)null) && val.m_canRemoveFeasts && (val.m_categories.Contains((PieceCategory)6) || val.m_categories.Contains((PieceCategory)7) || val.m_categories.Contains((PieceCategory)5)) && uniqueTables.Add(val)) { yield return val; } } } } private static int InjectIntoTable(PieceTable table, List<CandidateFood> candidates) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) EnsureBaseCategories(table); HashSet<int> hashSet = BuildExistingFoodHashSet(table); int num = 0; foreach (CandidateFood candidate in candidates) { ItemDrop itemDrop = candidate.ItemDrop; GameObject placePrefab = candidate.PlacePrefab; int prefabNameHash = GetPrefabNameHash(((Component)itemDrop).gameObject); bool num2 = hashSet.Contains(prefabNameHash); bool flag = (Object)(object)placePrefab.GetComponent<ServeYouRightInjectedPieceMarker>() != (Object)null; if (!num2 || flag) { PieceCategory category = candidate.Category; PieceCategory category2 = ResolveTargetCategory(table, ((Component)itemDrop).gameObject, category); if (TryGetTemplate(table, category2, out Piece templatePiece, out WearNTear templateWearNTear) && PrepareFoodPrefab(placePrefab, itemDrop, category2, templatePiece, templateWearNTear) && !table.m_pieces.Contains(placePrefab)) { table.m_pieces.Add(placePrefab); hashSet.Add(prefabNameHash); num++; } } } return num; } private static void EnsureBaseCategories(PieceTable table) { EnsureBaseCategoryExists(table, (PieceCategory)6, GetBaseCategoryLabel(table, (PieceCategory)6)); EnsureBaseCategoryExists(table, (PieceCategory)7, GetBaseCategoryLabel(table, (PieceCategory)7)); EnsureBaseCategoryExists(table, (PieceCategory)5, GetBaseCategoryLabel(table, (PieceCategory)5)); } public static void ApplyCustomCategoryLabels(PieceTable? table) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)table == (Object)null) { return; } List<ModCategoryInfo> list; lock (ModCategoryLock) { list = ModCategoryCache.Values.ToList(); } foreach (ModCategoryInfo item in list) { int num = table.m_categories.IndexOf(item.Category); if (num >= 0) { while (table.m_categoryLabels.Count <= num) { table.m_categoryLabels.Add(string.Empty); } string baseCategoryLabel = GetBaseCategoryLabel(table, item.BaseCategory); string text = ResolveCategoryDisplayLabel(item.BaseCategory, baseCategoryLabel); table.m_categoryLabels[num] = text + " - " + item.SourceMod.DisplayName; } } } private static bool TryGetTemplate(PieceTable table, PieceCategory category, out Piece templatePiece, out WearNTear templateWearNTear) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) templatePiece = null; templateWearNTear = null; Piece val = null; WearNTear val2 = null; foreach (GameObject piece in table.m_pieces) { if ((Object)(object)piece == (Object)null) { continue; } Piece component = piece.GetComponent<Piece>(); if ((Object)(object)component == (Object)null || component.m_repairPiece || component.m_removePiece) { continue; } WearNTear component2 = piece.GetComponent<WearNTear>(); if (!((Object)(object)component2 == (Object)null)) { if (component.m_category == category) { templatePiece = component; templateWearNTear = component2; return true; } if ((Object)(object)val == (Object)null) { val = component; val2 = component2; } } } if ((Object)(object)val != (Object)null) { templatePiece = val; templateWearNTear = val2; return true; } ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("No feaster template piece found for table '" + ((Object)table).name + "'.")); return false; } private static bool PrepareFoodPrefab(GameObject foodPrefab, ItemDrop sourceItemDrop, PieceCategory category, Piece templatePiece, WearNTear templateWearNTear) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown if ((Object)(object)foodPrefab.GetComponent<ZNetView>() == (Object)null) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Skipping '" + ((Object)foodPrefab).name + "' because it has no ZNetView.")); return false; } Piece val = foodPrefab.GetComponent<Piece>(); if ((Object)(object)val == (Object)null) { val = foodPrefab.AddComponent<Piece>(); CopyPieceTemplate(templatePiece, val); } WearNTear component = foodPrefab.GetComponent<WearNTear>(); if ((Object)(object)component == (Object)null) { component = foodPrefab.AddComponent<WearNTear>(); CopyWearNTearTemplate(templateWearNTear, component); } SharedData shared = sourceItemDrop.m_itemData.m_shared; val.m_name = shared.m_name; val.m_description = shared.m_description; val.m_enabled = true; val.m_category = category; val.m_repairPiece = false; val.m_removePiece = false; val.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = sourceItemDrop, m_amount = 1, m_amountPerLevel = 1, m_recover = true } }; Sprite[] icons = shared.m_icons; if (icons != null && icons.Length > 0) { val.m_icon = sourceItemDrop.m_itemData.GetIcon(); } if ((Object)(object)foodPrefab.GetComponent<ServeYouRightInjectedPieceMarker>() == (Object)null) { foodPrefab.AddComponent<ServeYouRightInjectedPieceMarker>(); } return true; } private static void CopyPieceTemplate(Piece source, Piece destination) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) destination.m_targetNonPlayerBuilt = source.m_targetNonPlayerBuilt; destination.m_icon = source.m_icon; destination.m_isUpgrade = source.m_isUpgrade; destination.m_comfort = source.m_comfort; destination.m_comfortGroup = source.m_comfortGroup; destination.m_comfortObject = source.m_comfortObject; destination.m_groundPiece = source.m_groundPiece; destination.m_allowAltGroundPlacement = source.m_allowAltGroundPlacement; destination.m_groundOnly = source.m_groundOnly; destination.m_cultivatedGroundOnly = source.m_cultivatedGroundOnly; destination.m_waterPiece = source.m_waterPiece; destination.m_clipGround = source.m_clipGround; destination.m_clipEverything = source.m_clipEverything; destination.m_noInWater = source.m_noInWater; destination.m_notOnWood = source.m_notOnWood; destination.m_notOnTiltingSurface = source.m_notOnTiltingSurface; destination.m_inCeilingOnly = source.m_inCeilingOnly; destination.m_notOnFloor = source.m_notOnFloor; destination.m_noClipping = source.m_noClipping; destination.m_onlyInTeleportArea = source.m_onlyInTeleportArea; destination.m_allowedInDungeons = source.m_allowedInDungeons; destination.m_spaceRequirement = source.m_spaceRequirement; destination.m_canRotate = source.m_canRotate; destination.m_randomInitBuildRotation = source.m_randomInitBuildRotation; destination.m_canBeRemoved = source.m_canBeRemoved; destination.m_canRockJade = source.m_canRockJade; destination.m_allowRotatedOverlap = source.m_allowRotatedOverlap; destination.m_vegetationGroundOnly = source.m_vegetationGroundOnly; destination.m_blockingPieces = ((source.m_blockingPieces == null) ? null : new List<Piece>(source.m_blockingPieces)); destination.m_blockRadius = source.m_blockRadius; destination.m_mustConnectTo = source.m_mustConnectTo; destination.m_connectRadius = source.m_connectRadius; destination.m_mustBeAboveConnected = source.m_mustBeAboveConnected; destination.m_noVines = source.m_noVines; destination.m_extraPlacementDistance = source.m_extraPlacementDistance; destination.m_onlyInBiome = source.m_onlyInBiome; destination.m_harvest = source.m_harvest; destination.m_harvestRadius = source.m_harvestRadius; destination.m_harvestRadiusMaxLevel = source.m_harvestRadiusMaxLevel; destination.m_placeEffect = source.m_placeEffect; destination.m_dlc = source.m_dlc; destination.m_craftingStation = source.m_craftingStation; destination.m_returnResourceHeightOffset = source.m_returnResourceHeightOffset; destination.m_destroyedLootPrefab = source.m_destroyedLootPrefab; } private static void CopyWearNTearTemplate(WearNTear source, WearNTear destination) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) destination.m_onDestroyed = source.m_onDestroyed; destination.m_onDamaged = source.m_onDamaged; destination.m_new = source.m_new; destination.m_worn = source.m_worn; destination.m_broken = source.m_broken; destination.m_wet = source.m_wet; destination.m_noRoofWear = source.m_noRoofWear; destination.m_noSupportWear = source.m_noSupportWear; destination.m_ashDamageImmune = source.m_ashDamageImmune; destination.m_ashDamageResist = source.m_ashDamageResist; destination.m_burnable = source.m_burnable; destination.m_materialType = source.m_materialType; destination.m_supports = source.m_supports; destination.m_comOffset = source.m_comOffset; destination.m_forceCorrectCOMCalculation = source.m_forceCorrectCOMCalculation; destination.m_staticPosition = source.m_staticPosition; destination.m_nonSolidRenderers = ((source.m_nonSolidRenderers == null) ? null : new List<Renderer>(source.m_nonSolidRenderers)); destination.m_health = source.m_health; destination.m_damages = source.m_damages; destination.m_minToolTier = source.m_minToolTier; destination.m_hitNoise = source.m_hitNoise; destination.m_destroyNoise = source.m_destroyNoise; destination.m_triggerPrivateArea = source.m_triggerPrivateArea; destination.m_destroyedEffect = source.m_destroyedEffect; destination.m_hitEffect = source.m_hitEffect; destination.m_switchEffect = source.m_switchEffect; destination.m_autoCreateFragments = source.m_autoCreateFragments; destination.m_fragmentRoots = ((source.m_fragmentRoots == null) ? null : ((GameObject[])source.m_fragmentRoots.Clone())); } private static HashSet<int> BuildExistingFoodHashSet(PieceTable table) { HashSet<int> hashSet = new HashSet<int>(); foreach (GameObject piece in table.m_pieces) { if ((Object)(object)piece == (Object)null) { continue; } ItemDrop component = piece.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { continue; } hashSet.Add(GetPrefabNameHash(((Component)component).gameObject)); if (!((Object)(object)piece.GetComponent<Feast>() != (Object)null) && !((Object)(object)piece.GetComponent<ServeYouRightInjectedPieceMarker>() != (Object)null)) { continue; } Requirement[] array = piece.GetComponent<Piece>()?.m_resources ?? Array.Empty<Requirement>(); foreach (Requirement val in array) { if ((Object)(object)val?.m_resItem != (Object)null) { hashSet.Add(GetPrefabNameHash(((Component)val.m_resItem).gameObject)); } } } return hashSet; } private static PieceCategory ResolveTargetCategory(PieceTable table, GameObject foodPrefab, PieceCategory baseCategory) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) string baseCategoryLabel = GetBaseCategoryLabel(table, baseCategory); EnsureBaseCategoryExists(table, baseCategory, baseCategoryLabel); if (!TryResolveFoodSourceMod(foodPrefab, out var sourceMod)) { return baseCategory; } if (!ServerSyncModTemplatePlugin.UseModSpecificTab(sourceMod, baseCategory)) { return baseCategory; } return ResolveOrCreateModCategory(baseCategory, sourceMod); } private static string GetBaseCategoryLabel(PieceTable table, PieceCategory category) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) int num = table.m_categories.IndexOf(category); if (num >= 0 && num < table.m_categoryLabels.Count) { string text = table.m_categoryLabels[num]; if (!string.IsNullOrWhiteSpace(text)) { return text; } } return GetFallbackCategoryLabel(category); } private static PieceCategory ResolveOrCreateModCategory(PieceCategory baseCategory, FoodSourceMod sourceMod) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) string key = $"{sourceMod.Id}:{(int)baseCategory}"; lock (ModCategoryLock) { if (ModCategoryCache.TryGetValue(key, out ModCategoryInfo value)) { return value.Category; } string text = BuildStableCategoryKey(baseCategory, sourceMod.Id); if (!JotunnBridge.TryAddPieceCategory(text, out var category)) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)$"Could not create Jotunn category '{text}'. Falling back to vanilla category '{baseCategory}'."); return baseCategory; } ModCategoryCache[key] = new ModCategoryInfo(category, baseCategory, sourceMod); return category; } } private static string ResolveCategoryDisplayLabel(PieceCategory category, string baseLabel) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(baseLabel)) { string text = baseLabel.Trim(); string text2 = text; if (LooksLikeLocalizationTokenKey(text) && !text.StartsWith("$", StringComparison.Ordinal)) { text2 = "$" + text; } if (Localization.instance != null) { string text3 = Localization.instance.Localize(text2); if (!string.IsNullOrWhiteSpace(text3) && !string.Equals(text3, text2, StringComparison.Ordinal)) { return text3.Trim(); } } if (LooksLikeLocalizationTokenKey(text)) { return GetFallbackCategoryLabel(category); } return text; } return GetFallbackCategoryLabel(category); } private static bool LooksLikeLocalizationTokenKey(string value) { if (string.IsNullOrWhiteSpace(value)) { return false; } if (value.StartsWith("$", StringComparison.Ordinal)) { return true; } if (value.IndexOfAny(new char[4] { ' ', '\t', '\r', '\n' }) >= 0) { return false; } if (!value.Contains("_")) { return false; } foreach (char c in value) { if (!char.IsLetterOrDigit(c) && c != '_' && c != '.' && c != '-') { return false; } } return true; } private static string BuildStableCategoryKey(PieceCategory baseCategory, string modId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected I4, but got Unknown string arg = (baseCategory - 5) switch { 1 => "food", 2 => "meads", 0 => "feasts", _ => $"cat{(int)baseCategory}", }; int num = StringExtensionMethods.GetStableHashCode(modId ?? string.Empty); if (num == int.MinValue) { num = int.MaxValue; } num = Math.Abs(num); return $"syr_{arg}_{num}"; } private unsafe static string GetFallbackCategoryLabel(PieceCategory category) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown return (category - 5) switch { 1 => "Food", 2 => "Meads", 0 => "Feasts", _ => ((object)(*(PieceCategory*)(&category))/*cast due to .constrained prefix*/).ToString(), }; } private static bool TryResolveFoodSourceMod(GameObject foodPrefab, out FoodSourceMod sourceMod) { string prefabName = Utils.GetPrefabName(((Object)foodPrefab).name); if (SourceModHitCache.TryGetValue(prefabName, out var value)) { sourceMod = value; return true; } if (KnownCloneSourceBridge.TryResolveSourceMod(prefabName, out var sourceMod2)) { sourceMod = sourceMod2; SourceModHitCache[prefabName] = sourceMod; return true; } if (JotunnBridge.TryGetPrefabSourceMod(prefabName, out var sourceMod3)) { sourceMod = sourceMod3; SourceModHitCache[prefabName] = sourceMod; return true; } sourceMod = default(FoodSourceMod); return false; } private static void EnsureBaseCategoryExists(PieceTable table, PieceCategory category, string label) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (table.m_categories.IndexOf(category) < 0) { table.m_categories.Add(category); while (table.m_categoryLabels.Count < table.m_categories.Count - 1) { table.m_categoryLabels.Add(((object)table.m_categories[table.m_categoryLabels.Count]/*cast due to .constrained prefix*/).ToString()); } table.m_categoryLabels.Add(label); } } private static int GetPrefabNameHash(GameObject prefab) { return StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Object)prefab).name)); } } internal readonly struct FoodSourceMod { public string Id { get; } public string DisplayName { get; } public FoodSourceMod(string id, string displayName) { Id = id; DisplayName = displayName; } } internal readonly struct CandidateFood { public ItemDrop ItemDrop { get; } public GameObject PlacePrefab { get; } public PieceCategory Category { get; } public CandidateFood(ItemDrop itemDrop, GameObject placePrefab, PieceCategory category) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) ItemDrop = itemDrop; PlacePrefab = placePrefab; Category = category; } } internal sealed class FeastRoutingData { public Dictionary<string, GameObject> MaterialToResultPrefab { get; } public HashSet<string> ResultPrefabNames { get; } public FeastRoutingData(Dictionary<string, GameObject> materialToResultPrefab, HashSet<string> resultPrefabNames) { MaterialToResultPrefab = materialToResultPrefab; ResultPrefabNames = resultPrefabNames; } } internal sealed class ModCategoryInfo { public PieceCategory Category { get; } public PieceCategory BaseCategory { get; } public FoodSourceMod SourceMod { get; } public ModCategoryInfo(PieceCategory category, PieceCategory baseCategory, FoodSourceMod sourceMod) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Category = category; BaseCategory = baseCategory; SourceMod = sourceMod; } } internal sealed class PerModCategoryConfig { public ConfigEntry<ServerSyncModTemplatePlugin.Toggle> Food { get; } public ConfigEntry<ServerSyncModTemplatePlugin.Toggle> Meads { get; } public ConfigEntry<ServerSyncModTemplatePlugin.Toggle> Feasts { get; } public PerModCategoryConfig(ConfigEntry<ServerSyncModTemplatePlugin.Toggle> food, ConfigEntry<ServerSyncModTemplatePlugin.Toggle> meads, ConfigEntry<ServerSyncModTemplatePlugin.Toggle> feasts) { Food = food; Meads = meads; Feasts = feasts; } } internal static class KnownCloneSourceBridge { private const string WackyGuid = "WackyMole.WackysDatabase"; private const string DefaultWackyName = "WackysDatabase"; private static bool _initialized; private static MethodInfo? _wackyGetClonedMap; private static string _wackyDisplayName = "WackysDatabase"; private static readonly HashSet<string> WackyCloneHitCache = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public static bool TryResolveSourceMod(string prefabName, out FoodSourceMod sourceMod) { sourceMod = default(FoodSourceMod); EnsureInitialized(); if (_wackyGetClonedMap == null) { return false; } if (WackyCloneHitCache.Contains(prefabName)) { sourceMod = new FoodSourceMod("WackyMole.WackysDatabase", _wackyDisplayName); return true; } try { if (string.IsNullOrWhiteSpace(_wackyGetClonedMap.Invoke(null, new object[1] { prefabName }) as string)) { return false; } WackyCloneHitCache.Add(prefabName); sourceMod = new FoodSourceMod("WackyMole.WackysDatabase", _wackyDisplayName); return true; } catch (Exception ex) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogDebug((object)("Known clone source resolution failed for '" + prefabName + "': " + ex.Message)); return false; } } private static void EnsureInitialized() { if (_initialized) { return; } _initialized = true; try { _wackyGetClonedMap = Type.GetType("API.WackyAPI, WackysDatabase")?.GetMethod("GetClonedMap", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); if (Chainloader.PluginInfos.TryGetValue("WackyMole.WackysDatabase", out var value)) { object obj; if (value == null) { obj = null; } else { BepInPlugin metadata = value.Metadata; obj = ((metadata != null) ? metadata.Name : null); } if (obj == null) { obj = string.Empty; } string text = (string)obj; if (!string.IsNullOrWhiteSpace(text)) { _wackyDisplayName = text; } } } catch (Exception ex) { _wackyGetClonedMap = null; ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogDebug((object)("Known clone source bridge init failed: " + ex.Message)); } } } internal static class JotunnBridge { private static bool _initialized; private static bool _available; private static MethodInfo? _modQueryEnable; private static MethodInfo? _modQueryGetPrefab; private static PropertyInfo? _pieceManagerInstance; private static MethodInfo? _pieceManagerAddPieceCategory; public static void InitializeAndEnableModQuery() { if (_initialized) { EnableModQuery(); return; } _initialized = true; try { Type? type = Type.GetType("Jotunn.Utils.ModQuery, Jotunn"); Type type2 = Type.GetType("Jotunn.Managers.PieceManager, Jotunn"); _modQueryEnable = type?.GetMethod("Enable", BindingFlags.Static | BindingFlags.Public); _modQueryGetPrefab = type?.GetMethod("GetPrefab", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); _pieceManagerInstance = type2?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); _pieceManagerAddPieceCategory = type2?.GetMethod("AddPieceCategory", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); _available = _modQueryEnable != null && _modQueryGetPrefab != null && _pieceManagerInstance != null && _pieceManagerAddPieceCategory != null; } catch (Exception ex) { _available = false; ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Failed to initialize Jotunn bridge: " + ex.Message)); } if (!_available) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)"Jotunn bridge is unavailable. Mod-specific tabs will fall back to vanilla categories."); } else { EnableModQuery(); } } public static bool TryGetPrefabSourceMod(string prefabName, out FoodSourceMod sourceMod) { sourceMod = default(FoodSourceMod); if (!_available || _modQueryGetPrefab == null) { return false; } try { object obj = _modQueryGetPrefab.Invoke(null, new object[1] { prefabName }); if (obj == null) { return false; } object obj2 = obj.GetType().GetProperty("SourceMod", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj); if (obj2 == null) { return false; } BepInPlugin val = (BepInPlugin)((obj2 is BepInPlugin) ? obj2 : null); if (val != null) { string displayName = (string.IsNullOrWhiteSpace(val.Name) ? val.GUID : val.Name); sourceMod = new FoodSourceMod(val.GUID, displayName); return true; } object obj3 = obj2.GetType().GetProperty("GUID", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj2) as string; string text = obj2.GetType().GetProperty("Name", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj2) as string; if (obj3 == null) { obj3 = string.Empty; } string text2 = (string)obj3; if (string.IsNullOrWhiteSpace(text2)) { return false; } string displayName2 = (string.IsNullOrWhiteSpace(text) ? text2 : text); sourceMod = new FoodSourceMod(text2, displayName2); return true; } catch (Exception ex) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogDebug((object)("ModQuery.GetPrefab failed for '" + prefabName + "': " + ex.Message)); return false; } } public static bool TryAddPieceCategory(string categoryName, out PieceCategory category) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected I4, but got Unknown category = (PieceCategory)6; if (!_available || _pieceManagerInstance == null || _pieceManagerAddPieceCategory == null) { return false; } try { object value = _pieceManagerInstance.GetValue(null); if (value == null) { return false; } object obj = _pieceManagerAddPieceCategory.Invoke(value, new object[1] { categoryName }); if (obj is PieceCategory val) { category = (PieceCategory)(int)val; return true; } if (obj is int num) { category = (PieceCategory)num; return true; } return false; } catch (Exception ex) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Failed to add Jotunn piece category '" + categoryName + "': " + ex.Message)); return false; } } private static void EnableModQuery() { if (!_available || _modQueryEnable == null) { return; } try { _modQueryEnable.Invoke(null, null); } catch (Exception ex) { ServerSyncModTemplatePlugin.ServerSyncModTemplateLogger.LogWarning((object)("Failed to enable Jotunn ModQuery: " + ex.Message)); } } } internal sealed class ServeYouRightInjectedPieceMarker : MonoBehaviour { } }