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 Skyla v0.7.2
plugins/Skyla.dll
Decompiled 2 years ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using Tyrenheim_Skyla.GUI; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Tyrenheim-Ward")] [assembly: AssemblyDescription("")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("Tyrenheim-Ward")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("6941129c-0802-45bb-b0e2-2a2c7a44bc81")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyCompany("")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Tyrenheim_Skyla { public class Assets { [HarmonyPatch(typeof(ObjectDB), "Awake")] public class ObjectDB_Awake_Patch { public static void Postfix(ObjectDB __instance) { LoadAssets(); GameObject[] s_prefabs = Assets.s_prefabs; foreach (GameObject val in s_prefabs) { ItemDrop component = val.GetComponent<ItemDrop>(); if (!((Object)(object)component != (Object)null)) { continue; } __instance.m_items.Add(val); __instance.m_itemByHash.Add(StringExtensionMethods.GetStableHashCode(((Object)val).name), val); if (PerkConfig.s_chimeMap.ContainsKey(component.m_itemData.m_shared.m_name)) { Chime.AddChime(val); Skyla.ChimeType key = PerkConfig.s_chimeMap[component.m_itemData.m_shared.m_name]; if (!PerkConfig.s_chimePrefabMap.ContainsKey(key)) { PerkConfig.s_chimePrefabMap.Add(key, val); } } } Recipe[] s_recipes = Assets.s_recipes; foreach (Recipe item in s_recipes) { __instance.m_recipes.Add(item); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public class ZNetScene_Awake_Patch { public static bool Prefix(ZNetScene __instance) { LoadAssets(); GameObject[] s_prefabs = Assets.s_prefabs; foreach (GameObject val in s_prefabs) { if ((Object)(object)val.GetComponent<ZNetView>() != (Object)null) { __instance.m_prefabs.Add(val); } } return true; } public static void Postfix(ZNetScene __instance) { s_applyBlessingFXPrefab = __instance.GetPrefab(s_applyBlessingFX); s_activateFXPrefab = __instance.GetPrefab(s_activateFX); s_deactivateFXPrefab = __instance.GetPrefab(s_deactivateFX); } } private static bool assetsLoaded = false; public static string s_resourceName = "skyla"; public static GameObject[] s_prefabs = null; public static Recipe[] s_recipes = null; private static string s_applyBlessingFX = "vfx_skyla_applyblessing"; public static GameObject s_applyBlessingFXPrefab; private static string s_activateFX = "sfx_skyla_activate"; public static GameObject s_activateFXPrefab; private static string s_deactivateFX = "sfx_skyla_deactivate"; public static GameObject s_deactivateFXPrefab; private static AssetBundle GetAssetBundleFromResources(string filename) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(filename)); return AssetBundle.LoadFromStream(executingAssembly.GetManifestResourceStream(name)); } public static void LoadAssets() { if (!assetsLoaded) { AssetBundle assetBundleFromResources = GetAssetBundleFromResources(s_resourceName); if ((Object)(object)assetBundleFromResources == (Object)null) { Debug.Log((object)("Failed to load AssetBundle " + s_resourceName)); return; } s_prefabs = assetBundleFromResources.LoadAllAssets<GameObject>(); s_recipes = assetBundleFromResources.LoadAllAssets<Recipe>(); Debug.Log((object)$"Loaded {s_prefabs.Count()} prefabs and {s_recipes.Count()} recipes from assetBundle {s_resourceName}"); assetBundleFromResources.Unload(false); SkylaGUI.Init(); assetsLoaded = true; } } } public class Chime : MonoBehaviour { private static AudioSource s_master; private static HashSet<AudioSource> s_sources = new HashSet<AudioSource>(); private AudioSource m_source; public static void AddChime(GameObject prefab) { if ((Object)(object)prefab.GetComponentInChildren<Chime>() == (Object)null) { GameObject val = prefab; Transform val2 = prefab.transform.Find("attach"); if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).gameObject; } val.AddComponent<Chime>(); } } private void Awake() { m_source = ((Component)this).GetComponentInChildren<AudioSource>(); s_sources.Add(m_source); ((Component)this).GetComponentInChildren<ZSFX>().Play(); if ((Object)(object)s_master == (Object)null) { s_master = m_source; } else { m_source.timeSamples = s_master.timeSamples; } } private void OnDestroy() { s_sources.Remove(m_source); s_master = null; using HashSet<AudioSource>.Enumerator enumerator = s_sources.GetEnumerator(); if (enumerator.MoveNext()) { s_master = enumerator.Current; } } } public class WNTFix { [HarmonyPatch(typeof(WearNTear), "Start")] public class WNT_Patch { public static bool Prefix(WearNTear __instance) { CheckHeightMap(__instance); return false; } } public static void CheckHeightMap(WearNTear wnt) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) wnt.m_connectedHeightMap = Heightmap.FindHeightmap(((Component)wnt).transform.position); if ((Object)(object)wnt.m_connectedHeightMap != (Object)null) { wnt.m_connectedHeightMap.m_clearConnectedWearNTearCache += wnt.ClearCachedSupport; } } [HarmonyPatch(typeof(WearNTear), "UpdateSupport")] public static void Prefix(WearNTear __instance) { CheckHeightMap(__instance); } } internal class ParticleMist_Patch { } internal class SE_Rested_Patch { [HarmonyPatch(typeof(SE_Rested), "CalculateComfortLevel", new Type[] { typeof(bool), typeof(Vector3) })] public static class FE_Resteed_CalculateComfortLevel_Patch { public static void Postfix(bool inShelter, Vector3 position, ref int __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (Skyla.ChimeApplies(position, Skyla.ChimeType.CHIME_COMFORT)) { __result += 3; } } } } internal class EnvManPatch { [HarmonyPatch(typeof(EnvMan), "GetEnvironmentOverride")] public static class EnvMan_GetEnvironmentOverride_Patch { public static void Postfix(EnvMan __instance, ref string __result) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (__result == null && (Object)(object)Player.m_localPlayer != (Object)null) { switch (Skyla.FindWeatherMode(((Component)Player.m_localPlayer).transform.position)) { case PerkConfig.WeatherMode.WEATHER_SNOW: __result = (EnvMan.IsDay() ? "Snow" : "Twilight_Snow"); break; case PerkConfig.WeatherMode.WEATHER_STORM: __result = "ThunderStorm"; break; case PerkConfig.WeatherMode.WEATHER_SNOWSTORM: __result = (EnvMan.IsDay() ? "SnowStorm" : "Twilight_SnowStorm"); break; case PerkConfig.WeatherMode.WEATHER_MISTLANDS_STORM: __result = "Mistlands_thunder"; break; case PerkConfig.WeatherMode.WEATHER_ASHRAIN: __result = "Ashrain"; break; case PerkConfig.WeatherMode.WEATHER_CLEAR: __result = "Clear"; break; } } } } } internal class PiecePatch { [HarmonyPatch(typeof(Piece), "DropResources")] public static class Piece_DropResources_Patch { public static void Postfix(Piece __instance) { Skyla component = ((Component)__instance).GetComponent<Skyla>(); if ((Object)(object)component != (Object)null) { component.DropResources(); } } } [HarmonyPatch(typeof(Piece), "SetCreator")] public static class Piece_SetCreator_Patch { public static void Postfix(Piece __instance, long uid) { if (Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsValid()) { Skyla component = ((Component)__instance).gameObject.GetComponent<Skyla>(); if ((Object)(object)component != (Object)null) { component.OnPlaced(uid); } } } } } public class PerkConfig { public enum WeatherMode { WEATHER_NONE, WEATHER_SNOW, WEATHER_STORM, WEATHER_SNOWSTORM, WEATHER_MISTLANDS_STORM, WEATHER_ASHRAIN, WEATHER_CLEAR, WEATHER_MAX } public class Farming { public const float c_harvestIncreaseProbability = 0.5f; public const int c_harvestIncrease = 1; public const float c_growTimeFactor = 0.85f; } public class Cooking { public const float c_fuelBurnRateFactor = 0.5f; public const float c_cookingTimeFactor = 0.8f; } public class Comfort { public const int c_comfortBoost = 3; } public class Industry { public const float c_fuelBurnRateFactor = 0.5f; public const float c_bakeRateFactor = 1.2f; } public static Dictionary<string, Skyla.ChimeType> s_chimeMap = new Dictionary<string, Skyla.ChimeType> { { "Chime of Fertility", Skyla.ChimeType.CHIME_FARMING }, { "Chime of the Hearth", Skyla.ChimeType.CHIME_COOKING }, { "Chime of Comfort", Skyla.ChimeType.CHIME_COMFORT }, { "Chime of Industry", Skyla.ChimeType.CHIME_INDUSTRY }, { "Snow Chime", Skyla.ChimeType.CHIME_SNOW }, { "Blizzard Chime", Skyla.ChimeType.CHIME_SNOWSTORM }, { "Chime of Ashes", Skyla.ChimeType.CHIME_ASHRAIN }, { "Storm Chime", Skyla.ChimeType.CHIME_STORM }, { "Tempest Chime", Skyla.ChimeType.CHIME_MISTLANDS_STORM }, { "Balmy Chime", Skyla.ChimeType.CHIME_CLEAR } }; public static Dictionary<Skyla.ChimeType, GameObject> s_chimePrefabMap = new Dictionary<Skyla.ChimeType, GameObject>(); public static Dictionary<Skyla.ChimeType, string> s_powerNameMap = new Dictionary<Skyla.ChimeType, string> { { Skyla.ChimeType.CHIME_FARMING, "Fertility" }, { Skyla.ChimeType.CHIME_COOKING, "Hearth" }, { Skyla.ChimeType.CHIME_COMFORT, "Comfort" }, { Skyla.ChimeType.CHIME_INDUSTRY, "Industry" } }; public static Dictionary<WeatherMode, string> s_weatherNameMap = new Dictionary<WeatherMode, string> { { WeatherMode.WEATHER_NONE, "<none>" }, { WeatherMode.WEATHER_CLEAR, "Clear" }, { WeatherMode.WEATHER_SNOW, "Snow" }, { WeatherMode.WEATHER_STORM, "Storm" }, { WeatherMode.WEATHER_SNOWSTORM, "Blizzard" }, { WeatherMode.WEATHER_MISTLANDS_STORM, "Tempest" }, { WeatherMode.WEATHER_ASHRAIN, "Ashrain" } }; } internal class ArmorStandPatch { [HarmonyPatch(typeof(ArmorStand), "UseItem")] public static class ArmorStand_UseItem_Patch { public static bool Prefix(ItemStand __instance, Switch caller, Humanoid user, ItemData item) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)user, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_ITEMSTAND); } } } internal class CookingStationPatch { [HarmonyPatch(typeof(CookingStation), "UpdateFuel")] public static class CookngStation_UpdateFuel_Patch { public static bool Prefix(CookingStation __instance, ref float dt) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (Skyla.ChimeApplies(((Component)__instance).gameObject.transform.position, Skyla.ChimeType.CHIME_COOKING)) { dt *= 0.5f; } return true; } } [HarmonyPatch(typeof(CookingStation), "UpdateCooking")] public static class CookingStation_UpdateCooking_Patch { public static bool Prefix(CookingStation __instance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!ZNetScene.instance.IsAreaReady(((Component)__instance).transform.position)) { return false; } return true; } } [HarmonyPatch(typeof(CookingStation), "GetSlot")] public static class CookingStation_GetSlot_Patch { public static void Postfix(CookingStation __instance, ref string itemName, ref float cookedTime, ref Status status) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (Skyla.ChimeApplies(((Component)__instance).gameObject.transform.position, Skyla.ChimeType.CHIME_COOKING)) { ItemConversion itemConversion = __instance.GetItemConversion(itemName); if (itemConversion != null) { cookedTime = Math.Min(cookedTime, itemConversion.m_cookTime * 1.1f); } } } } [HarmonyPatch(typeof(CookingStation), "SetSlot")] public static class CookingStation_SetSlot_Patch { public static bool Prefix(CookingStation __instance, int slot, ref string itemName, ref float cookedTime, ref Status status) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (Skyla.ChimeApplies(((Component)__instance).gameObject.transform.position, Skyla.ChimeType.CHIME_COOKING)) { float @float = __instance.m_nview.GetZDO().GetFloat("slot" + slot, 0f); if (__instance.m_nview.GetZDO().GetInt("slotstatus" + slot, 0) != (int)status && (int)status == 2) { itemName = __instance.m_nview.GetZDO().GetString("slot" + slot, ""); status = (Status)1; } float num = cookedTime - @float; cookedTime = @float + num * 1.25f; } return true; } } } internal class MineRockPatch { [HarmonyPatch(typeof(MineRock), "RPC_Hit")] public static class MineRock_Hit_Patch { public static bool Prefix(MineRock __instance, long sender, ref HitData hit) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || hit == null) { return false; } if ((Object)(object)hit.GetAttacker() == (Object)null || !hit.GetAttacker().IsPlayer()) { float num = 1f - Skyla.FindMaxSkylaPower(((Component)__instance).transform.position); if (num > 0f) { hit.ApplyModifier(num); return true; } return false; } return Skyla.CheckAccess(hit.GetAttacker(), ((Component)__instance).transform.position, Skyla.ActionType.ACTION_DAMAGE); } } [HarmonyPatch(typeof(MineRock5), "RPC_Damage")] public static class MineRock5_Damage_Patch { public static bool Prefix(MineRock5 __instance, long sender, ref HitData hit) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || hit == null) { return false; } if ((Object)(object)hit.GetAttacker() == (Object)null || !hit.GetAttacker().IsPlayer()) { float num = 1f - Skyla.FindMaxSkylaPower(((Component)__instance).transform.position); if (num > 0f) { hit.ApplyModifier(num); return true; } return false; } return Skyla.CheckAccess(hit.GetAttacker(), ((Component)__instance).transform.position, Skyla.ActionType.ACTION_DAMAGE); } } } internal class SpawnerPatches { [HarmonyPatch(typeof(CreatureSpawner), "Spawn")] public static class CreatureSpawner_Spawn_Patch { public static bool Prefix(CreatureSpawner __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.FindMaxSkylaPower(((Component)__instance).transform.position) < 0.99f; } } [HarmonyPatch(typeof(SpawnArea), "SpawnOne")] public static class SpawnArea_SpawnOne_Patch { public static bool Prefix(SpawnArea __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.FindMaxSkylaPower(((Component)__instance).transform.position) < 0.99f; } } [HarmonyPatch(typeof(SpawnSystem), "UpdateSpawning")] public static class SpawnSystem_UpdateSpawning_Patch { public static bool Prefix(SpawnSystem __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.FindMaxSkylaPower(((Component)__instance).transform.position) < 0.99f; } } } internal class PlantPatch { [HarmonyPatch(typeof(Plant), "Grow")] public static class Plant_Grow_Patch { public static void Postfix(Plant __instance, ref GameObject __result) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)__result == (Object)null) { return; } ZNetView component = __result.GetComponent<ZNetView>(); if ((Object)(object)__result.GetComponent<Pickable>() != (Object)null && (Object)(object)component != (Object)null) { component.GetZDO().Set("ProtectedPickable", true); if (Skyla.ChimeApplies(((Component)__instance).gameObject.transform.position, Skyla.ChimeType.CHIME_FARMING) && Random.value < 0.5f) { component.GetZDO().Set("HarvestAmountOverride", 1); } } } } [HarmonyPatch(typeof(Plant), "GetGrowTime")] public static class Plant_GetGrowTime_Patch { public static void Postfix(Plant __instance, ref float __result) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (Skyla.ChimeApplies(((Component)__instance).gameObject.transform.position, Skyla.ChimeType.CHIME_FARMING)) { __result *= 0.85f; } } } } internal class TreeBasePatch { [HarmonyPatch(typeof(TreeBase), "RPC_Damage")] public static class TreeBase_Damage_Patch { public static bool Prefix(TreeBase __instance, long sender, ref HitData hit) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || hit == null) { return false; } if ((Object)(object)hit.GetAttacker() == (Object)null || !hit.GetAttacker().IsPlayer()) { float num = 1f - Skyla.FindMaxSkylaPower(((Component)__instance).transform.position); if (num > 0f) { hit.ApplyModifier(num); return true; } return false; } return Skyla.CheckAccess(hit.GetAttacker(), ((Component)__instance).transform.position, Skyla.ActionType.ACTION_DAMAGE); } } } internal class TeleporWorld { [HarmonyPatch(typeof(TeleportWorld), "Interact")] public static class TeleportWorld_Interact_Patch { public static bool Prefix(TeleportWorld __instance, Humanoid human, bool hold, bool alt) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)human, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_PORTAL); } } } internal class SmelterPatch { [HarmonyPatch(typeof(Smelter), "Spawn")] public static class Smelter_Spawn_Patch { public static bool Prefix(Smelter __instance, string ore, int stack) { //IL_0027: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } ItemConversion itemConversion = __instance.GetItemConversion(ore); if (itemConversion != null) { __instance.m_produceEffects.Create(((Component)__instance).gameObject.transform.position, ((Component)__instance).gameObject.transform.rotation, (Transform)null, 1f, -1); GameObject obj = Object.Instantiate<GameObject>(((Component)itemConversion.m_to).gameObject, __instance.m_outputPoint.position, __instance.m_outputPoint.rotation); obj.GetComponent<ItemDrop>().m_itemData.m_stack = stack; obj.GetComponent<ZNetView>().GetZDO().Set("ProtectedItem", true); } return false; } } [HarmonyPatch(typeof(Smelter), "SetFuel")] public static class Smelter_SetFuel_Patch { public static bool Prefix(Smelter __instance, ref float __state) { __state = __instance.GetFuel(); return true; } public static void Postfix(Smelter __instance, float __state) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (Skyla.ChimeApplies(((Component)__instance).transform.position, Skyla.ChimeType.CHIME_INDUSTRY)) { float fuel = __instance.GetFuel(); float num = fuel - __state; if (num < 0f) { float fuel2 = fuel - num * 0.5f; __instance.SetFuel(fuel2); } } } } [HarmonyPatch(typeof(Smelter), "SetBakeTimer")] public static class Smelter_SetBakeTimer_Patch { public static bool Prefix(Smelter __instance, ref float __state) { __state = __instance.GetBakeTimer(); return true; } public static void Postfix(Smelter __instance, float __state) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (Skyla.ChimeApplies(((Component)__instance).transform.position, Skyla.ChimeType.CHIME_INDUSTRY)) { float num = __instance.GetBakeTimer() - __state; if (num > 0f) { float bakeTimer = __state + num * 1.2f; __instance.SetBakeTimer(bakeTimer); } } } } } internal class SignPatch { [HarmonyPatch(typeof(Sign), "Interact")] public static class Sign_Interact_Patch { public static bool Prefix(Sign __instance, Humanoid character, bool hold, bool alt) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)character, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_SIGN); } } } internal class ItemStandPatch { [HarmonyPatch(typeof(ItemStand), "Interact")] public static class ItemStand_Interact_Patch { public static bool Prefix(ItemStand __instance, Humanoid user, bool hold, bool alt) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)user, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_ITEMSTAND); } } [HarmonyPatch(typeof(ItemStand), "UseItem")] public static class ItemStand_UseItem_Patch { public static bool Prefix(ItemStand __instance, Humanoid user, ItemData item) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)user, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_ITEMSTAND); } } } public class SkylaConfig { public static ConfigEntry<float> s_totalSkylaAreaLimit; public static ConfigEntry<float> s_maxSingleSkylaRadius; public static ConfigEntry<int> s_skylaPowerUpTime; public static void SetupConfig(Mod instance) { s_totalSkylaAreaLimit = instance.SyncedConfig("Config", "TotalPlayerAreaLimit", 9600f, "The total area (in m²) that any individual player may have covered by their Skýla (active or otherwise)."); s_maxSingleSkylaRadius = instance.SyncedConfig("Config", "WardMaxRadius", 32f, "The maximum radius (in m) that any single Skýla may have."); s_skylaPowerUpTime = instance.SyncedConfig("Config", "PowerUpTime", 3600, "The time (in seconds) taken for a Skýla to reach full power. Valheim's normal day/night cycle lasts 1800 seconds (30 minutes)"); } public static float TotalAreaLimit() { return s_totalSkylaAreaLimit.Value; } public static float MaxSkylaRadius() { return s_maxSingleSkylaRadius.Value; } public static int PowerUpTimeSecs() { return s_skylaPowerUpTime.Value; } } public class LocalManager { private static ISet<ZDOID> s_localPlayerSkylaSet = new HashSet<ZDOID>(); private static float s_localPlayerSkylaAreaLimit = 0f; private static bool s_hasReceivedInfo = false; public static void RegisterRPC() { ZRoutedRpc.instance.Register<float, ZPackage>("ReceiveServerSkylaData", (Action<long, float, ZPackage>)RPC_ReceiveServerSkylaData); } private static void OutputLocalState() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_004e: Unknown result type (might be due to invalid IL or missing references) Debug.Log((object)"=================================="); Debug.Log((object)"Dumping out local Skyla info:"); float num = 0f; foreach (ZDOID item in s_localPlayerSkylaSet) { float @float = ZDOMan.instance.GetZDO(item).GetFloat("SkylaRadius", 0f); Debug.Log((object)$"ZDOID {item}, Radius: {@float}"); num += (float)Math.PI * @float * @float; } Debug.Log((object)$"Total area used: {num}"); Debug.Log((object)"=================================="); } private static ISet<ZDOID> Decode(ZPackage zp) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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) ISet<ZDOID> set = new HashSet<ZDOID>(); int num = zp.ReadInt(); for (int i = 0; i < num; i++) { ZDOID item = zp.ReadZDOID(); set.Add(item); } return set; } private static float GetLocalPlayerAreaLimit() { return s_localPlayerSkylaAreaLimit; } private static void RPC_ReceiveServerSkylaData(long sender, float maxWardedArea, ZPackage zp) { if (!float.IsNaN(maxWardedArea)) { s_localPlayerSkylaAreaLimit = maxWardedArea; } s_localPlayerSkylaSet = Decode(zp); s_hasReceivedInfo = true; } private static float GetUsedArea() { //IL_0014: 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) //IL_001f: Unknown result type (might be due to invalid IL or missing references) float num = 0f; foreach (ZDOID item in s_localPlayerSkylaSet) { ZDO zDO = ZDOMan.instance.GetZDO(item); float num2 = ((zDO != null) ? zDO.GetFloat("SkylaRadius", 0f) : 0f); num += (float)Math.PI * num2 * num2; } return num; } public static float GetRemainingArea() { return Math.Max(GetLocalPlayerAreaLimit() - GetUsedArea(), 0f); } private static float DistanceToNearestBlockingSkyla(Skyla skyla) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) float val = 9999f; foreach (Skyla s_localSkyla in Skyla.s_localSkylaList) { if (s_localSkyla.GetOwner() != skyla.GetOwner()) { float val2 = Vector3.Distance(((Component)s_localSkyla).transform.position, ((Component)skyla).transform.position) - s_localSkyla.GetRadius(); val = Math.Min(val, val2); } } return Math.Max(val, 0f); } private static float DistanceToNearestNoBuildZone(Skyla skyla) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) float val = 9999f; foreach (Location s_allLocation in Location.s_allLocations) { if (s_allLocation.m_noBuild && s_allLocation.m_exteriorRadius > 0f) { float val2 = Vector3.Distance(((Component)s_allLocation).transform.position, ((Component)skyla).transform.position) - s_allLocation.m_exteriorRadius; val = Math.Min(val, val2); } } return Math.Max(val, 0f); } public static float GetMaxRadiusForSkyla(Skyla skyla) { float remainingArea = GetRemainingArea(); float radius = skyla.GetRadius(); remainingArea += (float)Math.PI * radius * radius; return Math.Min(DistanceToNearestBlockingSkyla(skyla), Math.Min(SkylaConfig.MaxSkylaRadius(), Math.Min(DistanceToNearestNoBuildZone(skyla), (float)Math.Sqrt(remainingArea / (float)Math.PI)))); } private static void Local_RegisterSkyla(ZDO skylaZDO) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer != (Object)null && skylaZDO.GetLong("creator", 0L) == Player.m_localPlayer.GetPlayerID()) { s_localPlayerSkylaSet.Add(skylaZDO.m_uid); } } private static void Local_UnregisterSkyla(ZDO skylaZDO) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (skylaZDO.GetLong("creator", 0L) == Player.m_localPlayer.GetPlayerID()) { s_localPlayerSkylaSet.Remove(skylaZDO.m_uid); } } public static void RemoveSkyla(ZDO skylaZDO) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) Local_UnregisterSkyla(skylaZDO); ZRoutedRpc.instance.InvokeRoutedRPC("UnregisterSkyla", new object[1] { skylaZDO.m_uid }); } public static void AddSkyla(ZDO skylaZDO) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) Local_RegisterSkyla(skylaZDO); ZRoutedRpc.instance.InvokeRoutedRPC("RegisterSkyla", new object[1] { skylaZDO.m_uid }); } public static void RequestInfo(long playerID) { ZRoutedRpc.instance.InvokeRoutedRPC("RequestInfo", new object[1] { playerID }); } } public class ServerManager { private static bool s_initialized = false; private static Dictionary<long, HashSet<ZDO>> s_playerSkylaMap = new Dictionary<long, HashSet<ZDO>>(); private static Dictionary<string, float> s_playerMaxTotalArea = new Dictionary<string, float>(); private static string s_vipPlayerFileName = "skyla_area_overrides.txt"; public static void Initialize() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) List<ZDO> list = new List<ZDO>(); if (!ZNet.instance.IsServer() || s_initialized) { return; } int num = 0; while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(Skyla.s_prefabName, list, ref num)) { } foreach (ZDO item in list) { long @long = item.GetLong("creator", 0L); if (float.IsNaN(item.GetFloat("SkylaRadius", 0f))) { Debug.Log((object)$"Skyla ServerManager :: Fixing NaN Skyla at {item.GetPosition()}"); item.Set("SkylaRadius", 0f); } RegisterSkyla(@long, item); } Debug.Log((object)string.Format("SkylaManager::Initialize - found {0} {1} ZDOs", list.Count, "Skýla")); LoadSpecialPlayerList(); s_initialized = true; } public static void LoadSpecialPlayerList() { Debug.Log((object)"SkylaManager :: Loading Player Override List"); string path = Path.Combine(Paths.ConfigPath, s_vipPlayerFileName); Dictionary<string, float> dictionary = new Dictionary<string, float>(); if (!File.Exists(path)) { return; } try { string[] array = File.ReadAllLines(path); foreach (string text in array) { if (text.StartsWith("//")) { continue; } string[] array2 = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 2) { try { string key = array2[0]; float val = float.Parse(array2[1]); dictionary.Add(key, Math.Max(0f, val)); } catch { } } } } catch { return; } s_playerMaxTotalArea = dictionary; } public static void RegisterRPC() { ZRoutedRpc.instance.Register<ZDOID>("RegisterSkyla", (Action<long, ZDOID>)RPC_RegisterSkyla); ZRoutedRpc.instance.Register<ZDOID>("UnregisterSkyla", (Action<long, ZDOID>)RPC_UnregisterSkyla); ZRoutedRpc.instance.Register<long>("RequestInfo", (Action<long, long>)RPC_RequestInfo); } private static float GetMaxAreaForPlayer(string steamID) { if (s_playerMaxTotalArea.ContainsKey(steamID)) { return s_playerMaxTotalArea[steamID]; } return SkylaConfig.TotalAreaLimit(); } private static string GetSteamIDForPeer(long sender) { ZNetPeer peer = ZNet.instance.GetPeer(sender); string text = "<unknown>"; if (peer != null) { text = peer.m_socket.GetHostName(); Debug.Log((object)("SkylaManager :: Finding SteamID for player " + peer.m_playerName + " :: got " + text)); } if (!text.StartsWith("Steam_")) { return text; } return text.Substring(6); } private static void RPC_RequestInfo(long sender, long playerID) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (s_playerSkylaMap.ContainsKey(playerID)) { _ = s_playerSkylaMap[playerID].Count; } Initialize(); LoadSpecialPlayerList(); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ReceiveServerSkylaData", new object[2] { GetMaxAreaForPlayer(GetSteamIDForPeer(sender)), EncodeWards(playerID) }); if (!s_playerSkylaMap.ContainsKey(playerID)) { return; } foreach (ZDO item in s_playerSkylaMap[playerID]) { ZDOMan.instance.ForceSendZDO(sender, item.m_uid); } } private static ZPackage EncodeWards(long playerID) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); if (s_playerSkylaMap.ContainsKey(playerID)) { Debug.Log((object)string.Format("SkylaManager :: Encoding data of {0} {1} for playerID {2}", s_playerSkylaMap[playerID].Count, "Skýla", playerID)); val.Write(s_playerSkylaMap[playerID].Count); foreach (ZDO item in s_playerSkylaMap[playerID]) { val.Write(item.m_uid); } } else { val.Write(0); } return val; } private static float GetUsedArea(long playerID) { float num = 0f; if (s_playerSkylaMap.ContainsKey(playerID)) { foreach (ZDO item in s_playerSkylaMap[playerID]) { float @float = item.GetFloat("SkylaRadius", 0f); num += (float)Math.PI * @float * @float; } } return num; } private static float GetRemainingAreaBudget(long playerID) { return SkylaConfig.TotalAreaLimit() - GetUsedArea(playerID); } private static void RegisterSkyla(long playerID, ZDO ward) { if (!s_playerSkylaMap.ContainsKey(playerID)) { s_playerSkylaMap.Add(playerID, new HashSet<ZDO>()); } s_playerSkylaMap[playerID].Add(ward); } private static void RPC_RegisterSkyla(long sender, ZDOID ward) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(ward); if (zDO != null) { RegisterSkyla(zDO.GetLong("creator", 0L), zDO); } } private static void UnregisterSkyla(long playerID, ZDO ward) { if (s_playerSkylaMap.ContainsKey(playerID)) { s_playerSkylaMap[playerID].Remove(ward); } } private static void RPC_UnregisterSkyla(long sender, ZDOID ward) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(ward); if (zDO != null) { UnregisterSkyla(zDO.GetLong("creator", 0L), zDO); } } } internal class BeehivePatch { [HarmonyPatch(typeof(Beehive), "Interact")] public static class Beehive_Interact_Patch { public static bool Prefix(Beehive __instance, Humanoid character, bool repeat, bool alt) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)character, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_BEEHIVE); } } } public class PlayerPatch { [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Player_OnSpawned_Patch { public static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { LocalManager.RequestInfo(Player.m_localPlayer.GetPlayerID()); } } } [HarmonyPatch(typeof(Player), "OnRespawn")] public static class Player_OnRespawn_Patch { public static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { LocalManager.RequestInfo(Player.m_localPlayer.GetPlayerID()); } } } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] public static class Player_CheckCanRemovePiece_Patch { public static bool Prefix(Player __instance, Piece piece) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } if ((Object)(object)((Component)piece).gameObject.GetComponent<Vagon>() != (Object)null) { return Skyla.CanUseWagon(((Component)piece).gameObject.GetComponent<Vagon>(), (Character)(object)__instance); } if ((Object)(object)((Component)piece).gameObject.GetComponent<Ship>() != (Object)null) { return Skyla.CanUseShip(((Component)piece).gameObject.GetComponent<Ship>(), (Character)(object)__instance); } if ((Object)(object)((Component)piece).gameObject.GetComponent<Skyla>() != (Object)null) { return ((Component)piece).gameObject.GetComponent<Skyla>().IsPermitted((Character)(object)__instance, Skyla.ActionType.ACTION_REMOVE_SKYLA); } return Skyla.CheckAccess((Character)(object)__instance, ((Component)piece).transform.position, Skyla.ActionType.ACTION_BUILD); } } [HarmonyPatch(typeof(Player), "AutoPickup")] public static class Player_AutoPickup_Patch { public static bool Prefix(Player __instance, float dt) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)__instance, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_AUTO_PICKUP); } } } internal class TerrainHandling { [HarmonyPatch(typeof(Attack), "SpawnOnHitTerrain")] public static class Attack_SpawnOnHitTerrain_Patch { public static bool Prefix(Vector3 hitPoint, Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Skyla.CheckAccess(character, hitPoint, Skyla.ActionType.ACTION_TERRAIN_MODIFICATION); } } } internal class ShipControlsPatch { [HarmonyPatch(typeof(ShipControlls), "Interact")] public static class ShipControlls_Interact_Patch { public static bool Prefix(ShipControlls __instance, Humanoid character, bool repeat, bool alt) { if ((Object)(object)__instance == (Object)null) { return false; } if (!IsCreator(__instance.m_ship, (Player)(object)((character is Player) ? character : null))) { return Skyla.CanUseShip(__instance.m_ship, (Character)(object)character); } return true; } } private static bool IsCreator(Ship v, Player p) { return ((Component)v).gameObject.GetComponent<Piece>().GetCreator() == p.GetPlayerID(); } } internal class VagonPatch { [HarmonyPatch(typeof(Vagon), "Interact")] public static class Vagon_Interact_Patch { public static bool Prefix(Vagon __instance, Humanoid character, bool hold, bool alt) { if ((Object)(object)__instance == (Object)null) { return false; } if (!IsCreator(__instance, (Player)(object)((character is Player) ? character : null))) { return Skyla.CanUseWagon(__instance, (Character)(object)character); } return true; } } private static bool IsCreator(Vagon v, Player p) { return ((Component)v).gameObject.GetComponent<Piece>().GetCreator() == p.GetPlayerID(); } } internal class FireplacePatch { [HarmonyPatch(typeof(Fireplace), "UpdateFireplace")] public static class Fireplace_UpdateFireplace_Patch { public static bool Prefix(Fireplace __instance, ref float __state) { if (__instance.m_nview.IsOwner()) { __state = __instance.m_nview.GetZDO().GetFloat("fuel", 0f); } return true; } public static void Postfix(Fireplace __instance, float __state) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (__instance.m_nview.IsOwner()) { float @float = __instance.m_nview.GetZDO().GetFloat("fuel", 0f); float num = Skyla.FindMaxSkylaPower(((Component)__instance).transform.position); float num2 = __state - @float; float num3 = ((num > 0.99f) ? __instance.m_maxFuel : Math.Min(__instance.m_maxFuel, @float + num2 * num)); __instance.m_nview.GetZDO().Set("fuel", num3); } } } } internal class FermenterPatch { [HarmonyPatch(typeof(Fermenter), "Interact")] public static class Fermenter_Interact_Patch { public static bool Prefix(Fermenter __instance, Humanoid user, bool hold, bool alt) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)user, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_FERMENTER); } } } internal class DoorPatch { [HarmonyPatch(typeof(Door), "Interact")] public static class Door_Interact_Patch { public static bool Prefix(Door __instance, Humanoid character, bool hold, bool alt) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } return Skyla.CheckAccess((Character)(object)character, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_DOOR); } } } internal class ContainerPatch { [HarmonyPatch(typeof(Container), "Interact")] public static class Container_Interact_Patch { public static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } if (!((Character)character).IsPlayer()) { return false; } Player component = ((Component)character).GetComponent<Player>(); Vagon componentInParent = ((Component)__instance).gameObject.GetComponentInParent<Vagon>(); if ((Object)(object)componentInParent != (Object)null) { return Skyla.CanUseWagon(componentInParent, (Character)(object)character); } Ship componentInParent2 = ((Component)__instance).gameObject.GetComponentInParent<Ship>(); if ((Object)(object)componentInParent2 != (Object)null) { return Skyla.CanUseShip(componentInParent2, (Character)(object)character); } if ((Object)(object)((Component)__instance).gameObject.GetComponent<TombStone>() != (Object)null) { return true; } return Skyla.CheckAccess((Character)(object)component, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_USE_CONTAINER); } } } internal class DestructiblePatch { [HarmonyPatch(typeof(Destructible), "RPC_Damage")] public static class Destructible_Damage_Patch { public static bool Prefix(Destructible __instance, long sender, ref HitData hit) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || hit == null) { return false; } if ((Object)(object)((Component)__instance).GetComponent<RandomFlyingBird>() != (Object)null) { return true; } if ((Object)(object)hit.GetAttacker() == (Object)null || !hit.GetAttacker().IsPlayer()) { float num = 1f - Skyla.FindMaxSkylaPower(((Component)__instance).transform.position); if (num > 0f) { hit.ApplyModifier(num); return true; } return false; } return Skyla.CheckAccess(hit.GetAttacker(), ((Component)__instance).transform.position, Skyla.ActionType.ACTION_DAMAGE); } } } internal class PickablePatch { [HarmonyPatch(typeof(Pickable), "Interact")] public static class Pickable_Interact_Patch { public static bool Prefix(Pickable __instance, Humanoid character, bool repeat, bool alt) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } __instance.m_amount += __instance.m_nview.GetZDO().GetInt("HarvestAmountOverride", __instance.m_amount); if (__instance.m_nview.GetZDO().GetBool("ProtectedPickable", false)) { return Skyla.CheckAccess((Character)(object)character, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_PICKABLE); } return true; } } } [HarmonyPatch(typeof(PickableItem), "Interact")] public static class PickableItem_Interact_Patch { public static bool Prefix(PickableItem __instance, Humanoid character, bool repeat, bool alt) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } if (__instance.m_nview.GetZDO().GetBool("ProtectedPickable", false)) { return Skyla.CheckAccess((Character)(object)character, ((Component)__instance).transform.position, Skyla.ActionType.ACTION_PICKABLE); } return true; } } public class WNTPatch { [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] public static class WNT_Damage_Patch { public static bool Prefix(WearNTear __instance, long sender, ref HitData hit) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || hit == null) { return false; } if (!Object.op_Implicit((Object)(object)hit.GetAttacker()) || !hit.GetAttacker().IsPlayer()) { float num = 0f; Skyla component = ((Component)__instance).gameObject.GetComponent<Skyla>(); num = ((!((Object)(object)component != (Object)null)) ? Skyla.FindMaxSkylaPower(((Component)__instance).transform.position) : component.GetSkylaPower()); float num2 = 1f - num; if (num2 > 0.001f) { hit.ApplyModifier(num2); return true; } return false; } if ((Object)(object)((Component)__instance).gameObject.GetComponent<Vagon>() != (Object)null) { return Skyla.CanUseWagon(((Component)__instance).gameObject.GetComponent<Vagon>(), hit.GetAttacker()); } if ((Object)(object)((Component)__instance).gameObject.GetComponent<Ship>() != (Object)null) { return Skyla.CanUseShip(((Component)__instance).gameObject.GetComponent<Ship>(), hit.GetAttacker()); } return Skyla.CheckAccess(hit.GetAttacker(), ((Component)__instance).transform.position, Skyla.ActionType.ACTION_DAMAGE); } } [HarmonyPatch(typeof(WearNTear), "UpdateWear")] public static class WNT_UpdateWear_Patch { public static bool Prefix(WearNTear __instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (Skyla.CheckWeatherProtection(((Component)__instance).transform.position)) { __instance.m_rainTimer = Time.time; } return true; } } } public class Skyla : MonoBehaviour, Hoverable, Interactable { public enum ActionType { ACTION_NONE, ACTION_CONTROL_SKYLA, ACTION_REMOVE_SKYLA, ACTION_DAMAGE, ACTION_BUILD, ACTION_TERRAIN_MODIFICATION, ACTION_USE_PORTAL, ACTION_USE_CONTAINER, ACTION_USE_DOOR, ACTION_USE_SIGN, ACTION_USE_ITEMSTAND, ACTION_USE_FERMENTER, ACTION_USE_BEEHIVE, ACTION_PICKUP_FACTORY_OUTPUT, ACTION_AUTO_PICKUP, ACTION_PICKABLE, ACTION_USE_SHIP, ACTION_USE_WAGON, PROTECTION_WEATHER, PROTECTION_MIST } public enum ChimeType { CHIME_FARMING = 0, CHIME_COOKING = 1, CHIME_STABILITY = 2, CHIME_COMFORT = 4, CHIME_INDUSTRY = 5, CHIME_STORM = 10, CHIME_SNOW = 11, CHIME_SNOWSTORM = 12, CHIME_MISTLANDS_STORM = 13, CHIME_ASHRAIN = 14, CHIME_CLEAR = 15 } [HarmonyPatch(typeof(ZDOMan), "Load")] public class ZDOMan_Load_Patch { public static void Postfix(ZDOMan __instance) { ServerManager.Initialize(); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public class ZNetScene_Awake_Patch { public static void Postfix(ZNetScene __instance) { GameObject prefab = __instance.GetPrefab(s_prefabName); if ((Object)(object)prefab != (Object)null) { s_skylaPrefab = prefab; if ((Object)(object)prefab.GetComponent<Skyla>() == (Object)null) { prefab.AddComponent<Skyla>(); } } AddToHammer(s_skylaPrefab); } } [HarmonyPatch(typeof(ZNet), "Awake")] public static class ZNetAwakePatch { public static void Postfix(ZNet __instance) { ServerManager.RegisterRPC(); LocalManager.RegisterRPC(); } } [HarmonyPatch(typeof(ZNetScene), "Destroy")] private static class ZNetScene_Destroy_Patch { private static bool Prefix(ZNetScene __instance, GameObject go) { Skyla component = go.GetComponent<Skyla>(); if ((Object)(object)component != (Object)null) { LocalManager.RemoveSkyla(component.m_nview.GetZDO()); } return true; } } private static GameObject s_skylaPrefab; private static float s_defaultSkylaRadius = 15f; private const float c_fullLightIntensity = 3f; private const float c_fullRuneIntensity = 4.8f; private const float c_halfHeight = 50f; private const int c_pulseTimeSecs = 4; public static ISet<Skyla> s_localSkylaList = new HashSet<Skyla>(); public static string s_prefabName = "RunicSkyla"; public const string c_skylaName = "Runic Skýla"; public const string c_skylaShortName = "Skýla"; public const string c_permittedName = "Vinir"; private const string c_zdoSkylaPower = "SkylaPower"; private const string c_zdoIsActive = "IsActive"; public const string c_zdoSkylaRadius = "SkylaRadius"; public const string c_zdoPieceCreator = "creator"; public const string c_zdoProtectedItemDrop = "ProtectedItem"; public const string c_zdoProtectedPickable = "ProtectedPickable"; public const string c_zdoHarvestBonus = "HarvestAmountOverride"; public const string c_zdoChimeBitvector = "ChimesData"; public const string c_zdoWeatherMode = "WeatherMode"; private static Dictionary<ActionType, string> s_zdoAccessMap = new Dictionary<ActionType, string> { { ActionType.ACTION_USE_CONTAINER, "public_use_container" }, { ActionType.ACTION_USE_DOOR, "public_use_door" }, { ActionType.ACTION_USE_SIGN, "public_use_sign" }, { ActionType.ACTION_USE_ITEMSTAND, "public_use_itemstand" }, { ActionType.ACTION_USE_BEEHIVE, "public_use_beehive" }, { ActionType.ACTION_USE_FERMENTER, "public_use_fermenter" }, { ActionType.ACTION_PICKUP_FACTORY_OUTPUT, "public_pickup_factory" }, { ActionType.ACTION_PICKABLE, "public_pickable" }, { ActionType.ACTION_USE_SHIP, "public_use_ship" }, { ActionType.ACTION_USE_WAGON, "public_use_wagon" }, { ActionType.PROTECTION_WEATHER, "weather_protection" }, { ActionType.PROTECTION_MIST, "mist_protection" } }; public static Dictionary<ChimeType, PerkConfig.WeatherMode> s_weatherChimeMap = new Dictionary<ChimeType, PerkConfig.WeatherMode> { { ChimeType.CHIME_STORM, PerkConfig.WeatherMode.WEATHER_STORM }, { ChimeType.CHIME_SNOW, PerkConfig.WeatherMode.WEATHER_SNOW }, { ChimeType.CHIME_SNOWSTORM, PerkConfig.WeatherMode.WEATHER_SNOWSTORM }, { ChimeType.CHIME_MISTLANDS_STORM, PerkConfig.WeatherMode.WEATHER_MISTLANDS_STORM }, { ChimeType.CHIME_ASHRAIN, PerkConfig.WeatherMode.WEATHER_ASHRAIN }, { ChimeType.CHIME_CLEAR, PerkConfig.WeatherMode.WEATHER_CLEAR } }; private MeshRenderer m_model; private ZNetView m_nview; private Light m_lightSource; private Piece m_piece; private CircleProjector m_circleProjector; private DateTime m_awakeTime; public float GetSkylaPower() { if (!m_nview.IsValid()) { return 0f; } if (!IsActive()) { return 0f; } return m_nview.GetZDO().GetFloat("SkylaPower", 0f); } public float GetRadius() { if (m_nview.IsValid()) { return m_nview.GetZDO().GetFloat("SkylaRadius", 0f); } return 0f; } public void SetRadius(float radius) { radius = Math.Min(radius, LocalManager.GetMaxRadiusForSkyla(this)); m_nview.GetZDO().Set("SkylaRadius", radius); } private double GetDeltaTime() { DateTime time = ZNet.instance.GetTime(); DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("SkylaTime", time.Ticks)); double totalSeconds = (time - dateTime).TotalSeconds; m_nview.GetZDO().Set("SkylaTime", time.Ticks); return totalSeconds; } public void Start() { m_nview = ((Component)this).GetComponent<ZNetView>(); m_nview.IsValid(); } private void Awake() { m_awakeTime = DateTime.Now; m_piece = ((Component)this).GetComponent<Piece>(); m_lightSource = ((Component)this).GetComponent<Light>(); m_circleProjector = ((Component)this).GetComponentInChildren<CircleProjector>(); if ((Object)(object)m_circleProjector != (Object)null) { ((Component)m_circleProjector).gameObject.SetActive(false); } m_nview = ((Component)this).GetComponent<ZNetView>(); if (!m_nview.IsValid() || m_nview.GetZDO() == null) { return; } s_localSkylaList.Add(this); ((MonoBehaviour)this).InvokeRepeating("UpdateState", 0f, 1f); if (m_nview.GetZDO().GetString("CreatorName", "").Length == 0) { Player player = Player.GetPlayer(m_piece.GetCreator()); if ((Object)(object)player != (Object)null) { m_nview.GetZDO().Set("CreatorName", player.GetPlayerName()); } } m_nview.Register<long>("ToggleEnabled", (Action<long, long>)RPC_ToggleEnabled); m_nview.Register<long>("TogglePermitted", (Action<long, long>)RPC_TogglePermitted); m_nview.Register<int>("AddChime", (Action<long, int>)RPC_AddChime); m_nview.Register<long>("RequestSetup", (Action<long, long>)RPC_RequestSetup); m_nview.Register<bool>("RequestSetupResponse", (Action<long, bool>)RPC_RequestSetupResponse); LocalManager.AddSkyla(m_nview.GetZDO()); } private void OnDestroy() { s_localSkylaList.Remove(this); } public void DropResources() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) foreach (ChimeType value in Enum.GetValues(typeof(ChimeType))) { if (HasChime(value)) { GameObject val = PerkConfig.s_chimePrefabMap[value]; if ((Object)(object)val != (Object)null) { Object.Instantiate<GameObject>(val, ((Component)this).transform.position + Vector3.up, Quaternion.identity); } } } } private void UpdateState() { if (!m_nview.IsValid() || !m_nview.IsOwner()) { return; } float num = Math.Max(0f, Math.Min(5f, (float)GetDeltaTime())); if (IsActive()) { float num2 = Math.Min(1f, GetSkylaPower() + num / (float)SkylaConfig.PowerUpTimeSecs()); if ((Object)(object)Player.m_localPlayer != (Object)null && IsOwner(Player.m_localPlayer.GetPlayerID()) && ((Character)Player.m_localPlayer).InGodMode()) { num2 = 1f; } m_nview.GetZDO().Set("SkylaPower", num2); } } public void Update() { UpdateVFX(); UpdateMarker(); } private void UpdateVFX() { //IL_0029: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00d1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_model == (Object)null) { m_model = ((Component)this).GetComponentInChildren<MeshRenderer>(); if ((Object)(object)m_model == (Object)null) { return; } } Color val = Color.white * 4.8f; val.a = 1f; float num = (float)DateTime.Now.Subtract(m_awakeTime).TotalSeconds; float skylaPower = GetSkylaPower(); float num2 = ((!IsActive()) ? 0f : ((skylaPower < 1f) ? (((float)Math.Cos((double)(num / 4f) * Math.PI * 2.0) * 0.5f + 0.5f) * skylaPower) : 1f)); ((Renderer)m_model).material.SetColor("_EmissionColor", Color.Lerp(Color.black, val, num2)); if ((Object)(object)m_lightSource != (Object)null) { m_lightSource.intensity = 3f * num2; } } public bool ProtectsFromWeather() { if (IsActive()) { return CheckPublicAccess(ActionType.PROTECTION_WEATHER); } return false; } public bool ProtectsFromMist() { if (IsActive()) { return CheckPublicAccess(ActionType.PROTECTION_MIST); } return false; } public void Broadcast() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) ZDOMan.instance.ForceSendZDO(m_nview.GetZDO().m_uid); } public void OnPlaced(long playerID) { Player player = Player.GetPlayer(playerID); if ((Object)(object)player != (Object)null) { m_nview.GetZDO().Set("CreatorName", player.GetPlayerName()); } SetRadius(Math.Min(LocalManager.GetMaxRadiusForSkyla(this), s_defaultSkylaRadius)); LocalManager.AddSkyla(m_nview.GetZDO()); Broadcast(); } private void UpdateMarker() { if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)m_circleProjector != (Object)null) { float radius = GetRadius(); bool active = ((Character)Player.m_localPlayer).InPlaceMode() && m_nview.IsValid() && radius > 0f; m_circleProjector.m_radius = radius; ((Component)m_circleProjector).gameObject.SetActive(active); } } public bool IsActive() { if (m_nview.IsValid()) { return m_nview.GetZDO().GetBool("IsActive", false); } return false; } public void SetActive(bool active) { if (m_nview.IsValid()) { m_nview.GetZDO().Set("IsActive", active); } } public long GetOwner() { return m_piece.GetCreator(); } public bool IsOwner(long playerID) { return m_piece.GetCreator() == playerID; } public string GetOwnerName() { if (m_nview.IsValid()) { return m_nview.GetZDO().GetString("CreatorName", ""); } return ""; } public bool Interact(Humanoid h, bool hold, bool alt) { if (hold) { return false; } if (!((Character)h).IsPlayer()) { return false; } Player val = (Player)(object)((h is Player) ? h : null); if (IsOwner(val.GetPlayerID())) { if (Input.GetKey((KeyCode)304)) { m_nview.InvokeRPC("RequestSetup", new object[1] { ((Player)((h is Player) ? h : null)).GetPlayerID() }); } else { m_nview.InvokeRPC("ToggleEnabled", new object[1] { ((Player)((h is Player) ? h : null)).GetPlayerID() }); } return true; } if (val.m_godMode) { m_nview.InvokeRPC("ToggleEnabled", new object[1] { ((Player)((h is Player) ? h : null)).GetPlayerID() }); return true; } if (!IsActive()) { m_nview.InvokeRPC("TogglePermitted", new object[1] { ((Player)((h is Player) ? h : null)).GetPlayerID() }); return true; } return false; } public bool UseItem(Humanoid user, ItemData item) { if (PerkConfig.s_chimeMap.ContainsKey(item.m_shared.m_name)) { if (!IsOwner(((Player)((user is Player) ? user : null)).GetPlayerID())) { ((Character)user).Message((MessageType)2, "Only the owner may apply chimes", 0, (Sprite)null); return true; } if (IsActive()) { ((Character)user).Message((MessageType)2, "A Skýla must be deactivated to receive a chime", 0, (Sprite)null); return true; } ChimeType chimeType = PerkConfig.s_chimeMap[item.m_shared.m_name]; if (HasChime(chimeType)) { ((Character)user).Message((MessageType)2, "This Skýla already has this chime", 0, (Sprite)null); return true; } m_nview.InvokeRPC("AddChime", new object[1] { (int)chimeType }); ((Character)user).ShowRemovedMessage(item, 1); user.GetInventory().RemoveItem(item.m_shared.m_name, 1, -1, true); return true; } return false; } public static float FindMaxSkylaPower(Vector3 point) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) float num = 0f; foreach (Skyla s_localSkyla in s_localSkylaList) { if (s_localSkyla.IsActive() && s_localSkyla.IsInside(point, 0f)) { num = Math.Max(num, s_localSkyla.GetSkylaPower()); } } return num; } public static bool CanUseWagon(Vagon v, Character user) { return CanUseVehicle(((Component)v).gameObject.GetComponent<Piece>(), (Player)(object)((user is Player) ? user : null), ActionType.ACTION_USE_WAGON); } public static bool CanUseShip(Ship s, Character user) { return CanUseVehicle(((Component)s).gameObject.GetComponent<Piece>(), (Player)(object)((user is Player) ? user : null), ActionType.ACTION_USE_SHIP); } private static bool CanUseVehicle(Piece vehiclePiece, Player user, ActionType action) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) long creator = vehiclePiece.GetCreator(); if (user.m_godMode) { return true; } foreach (Skyla s_localSkyla in s_localSkylaList) { if (s_localSkyla.IsInside(((Component)vehiclePiece).transform.position, 0f) && !s_localSkyla.CheckPublicAccess(action) && s_localSkyla.IsPermitted(creator) && !s_localSkyla.IsPermitted(user.GetPlayerID())) { ((Character)user).Message((MessageType)2, "You are prevented by a Skýla", 0, (Sprite)null); return false; } } return true; } public static bool ChimeApplies(Vector3 point, ChimeType perk) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) foreach (Skyla s_localSkyla in s_localSkylaList) { if (s_localSkyla.IsInside(point, 0f) && s_localSkyla.IsActive() && s_localSkyla.HasChime(perk)) { return true; } } return false; } public static PerkConfig.WeatherMode FindWeatherMode(Vector3 point) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) foreach (Skyla s_localSkyla in s_localSkylaList) { if (s_localSkyla.IsInside(point, 0f, 2f) && s_localSkyla.IsActive()) { PerkConfig.WeatherMode stormChimeWeatherMode = s_localSkyla.GetStormChimeWeatherMode(); if (stormChimeWeatherMode != 0) { return stormChimeWeatherMode; } } } return PerkConfig.WeatherMode.WEATHER_NONE; } public PerkConfig.WeatherMode GetStormChimeWeatherMode() { if (!m_nview.IsValid()) { return PerkConfig.WeatherMode.WEATHER_NONE; } return (PerkConfig.WeatherMode)m_nview.GetZDO().GetInt("WeatherMode", 0); } public void SetStormChimeWeatherMode(PerkConfig.WeatherMode weather) { m_nview.GetZDO().Set("WeatherMode", (int)weather); } public static bool CheckWeatherProtection(Vector3 point) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) foreach (Skyla s_localSkyla in s_localSkylaList) { if (s_localSkyla.IsInside(point, 0f) && s_localSkyla.ProtectsFromWeather()) { return true; } } return false; } public static bool CheckMistProtection(Vector3 point) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) foreach (Skyla s_localSkyla in s_localSkylaList) { if (s_localSkyla.IsInside(point, 0f, s_localSkyla.GetSkylaPower()) && s_localSkyla.ProtectsFromMist()) { return true; } } return false; } public static bool CheckAccess(Character c, Vector3 point, ActionType action) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) float num = 0f; num = action switch { ActionType.ACTION_AUTO_PICKUP => Player.m_localPlayer.m_autoPickupRange * 1.5f, ActionType.ACTION_TERRAIN_MODIFICATION => 3f, _ => 0f, }; foreach (Skyla s_localSkyla in s_localSkylaList) { if (s_localSkyla.IsInside(point, num) && !s_localSkyla.IsPermitted(c, action)) { return false; } } return true; } public void SetPublicAccess(ActionType action, bool allow) { if (s_zdoAccessMap.TryGetValue(action, out var value)) { m_nview.GetZDO().Set(value, allow); } } public bool CheckPublicAccess(ActionType action) { if (s_zdoAccessMap.TryGetValue(action, out var value)) { return m_nview.GetZDO().GetBool(value, action == ActionType.PROTECTION_WEATHER || action == ActionType.PROTECTION_MIST); } return false; } public void AddChime(ChimeType chime) { int @int = m_nview.GetZDO().GetInt("ChimesData", 0); m_nview.GetZDO().Set("ChimesData", @int | (1 << (int)chime)); } public bool HasChime(ChimeType chime) { return (m_nview.GetZDO().GetInt("ChimesData", 0) & (1 << (int)chime)) != 0; } public int NumWeatherChimes() { int @int = m_nview.GetZDO().GetInt("ChimesData", 0); int num = 0; foreach (ChimeType key in s_weatherChimeMap.Keys) { if ((@int & (1 << (int)key)) != 0) { num++; } } return num; } public List<ChimeType> GetWeatherChimes() { List<ChimeType> list = new List<ChimeType>(); int @int = m_nview.GetZDO().GetInt("ChimesData", 0); foreach (ChimeType key in s_weatherChimeMap.Keys) { if ((@int & (1 << (int)key)) != 0) { list.Add(key); } } return list; } public bool IsPermitted(Character c, ActionType action) { if (!IsActive() && action != ActionType.ACTION_REMOVE_SKYLA) { return true; } if ((Object)(object)c == (Object)null || !c.IsPlayer()) { return false; } Player val = (Player)(object)((c is Player) ? c : null); if ((Object)(object)val != (Object)null) { if (val.m_godMode || IsOwner(val.GetPlayerID()) || (OnPermittedList(val) && action != ActionType.ACTION_REMOVE_SKYLA)) { return true; } if (CheckPublicAccess(action)) { return true; } if (action != ActionType.ACTION_AUTO_PICKUP) { ((Character)val).Message((MessageType)2, "You are prevented by a Skýla", 0, (Sprite)null); } } return false; } private bool OnPermittedList(Player p) { return IsPermitted(p.GetPlayerID()); } private bool IsInside(Vector3 point, float grace, float radiusScale = 1f) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (Utils.DistanceXZ(((Component)this).transform.position, point) < GetRadius() * radiusScale + grace) { return Math.Abs(((Component)this).transform.position.y - point.y) < 50f; } return false; } public string GetHoverName() { return "Runic Skýla"; } public string GetHoverText() { StringBuilder stringBuilder = new StringBuilder(256); if (!m_nview.IsValid()) { return ""; } if (IsActive()) { stringBuilder.Append(string.Format("{0} is {1}% charged", "Skýla", (int)(GetSkylaPower() * 100f))); } bool flag = m_piece.GetCreator() == Player.m_localPlayer.GetPlayerID(); if (Player.m_localPlayer.m_godMode || flag) { if (IsActive()) { stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] : Deactivate"); } else { stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] : Activate"); } if (flag) { stringBuilder.Append("\n[<color=yellow><b>Shift + $KEY_Use</b></color>] : Setup"); if (!IsActive()) { stringBuilder.Append("\n[<color=yellow><b>1-8</b></color>] Add Chime"); } } } else if (!IsActive()) { if (OnPermittedList(Player.m_localPlayer)) { stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] : Unpermit"); } else { stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] : Permit"); } } stringBuilder.Append("\nOwner: " + GetOwnerName()); AddUserList(stringBuilder); AddChimeList(stringBuilder); return Localization.instance.Localize(stringBuilder.ToString()); } private void RPC_RequestSetup(long uid, long playerID) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (IsOwner(playerID)) { ZDOMan.instance.ForceSendZDO(uid, m_nview.GetZDO().m_uid); m_nview.GetZDO().SetOwner(uid); m_nview.InvokeRPC(uid, "RequestSetupResponse", new object[1] { true }); } } private void RPC_RequestSetupResponse(long uid, bool allowed) { if (allowed) { SkylaGUI.ToggleGUI(this); } } private void RPC_ToggleEnabled(long uid, long playerID) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (m_nview.IsOwner()) { SetActive(!IsActive()); Broadcast(); Object.Instantiate<GameObject>(IsActive() ? Assets.s_activateFXPrefab : Assets.s_deactivateFXPrefab, ((Component)this).transform.position + Vector3.up * 1.6f, ((Component)this).transform.rotation); } } private void RPC_TogglePermitted(long uid, long playerID) { if (m_nview.IsOwner() && !IsActive()) { if (IsPermitted(playerID)) { RemovePermitted(playerID); } else { AddPermitted(playerID, Player.GetPlayer(playerID).GetPlayerName()); } Broadcast(); } } private void RPC_AddChime(long uid, int chime) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (m_nview.IsOwner()) { AddChime((ChimeType)chime); Broadcast(); if (((Behaviour)this).enabled) { Object.Instantiate<GameObject>(Assets.s_applyBlessingFXPrefab, ((Component)this).transform.position + Vector3.up * 1.6f, ((Component)this).transform.rotation); } } } private List<KeyValuePair<long, string>> GetPermittedPlayers() { List<KeyValuePair<long, string>> list = new List<KeyValuePair<long, string>>(); if (m_nview.IsValid()) { int @int = m_nview.GetZDO().GetInt("permitted", 0); for (int i = 0; i < @int; i++) { long @long = m_nview.GetZDO().GetLong("pu_id" + i, 0L); string @string = m_nview.GetZDO().GetString("pu_name" + i, ""); if (@long != 0L) { list.Add(new KeyValuePair<long, string>(@long, @string)); } } } return list; } private void SetPermittedPlayers(List<KeyValuePair<long, string>> users) { if (m_nview.IsValid()) { m_nview.GetZDO().Set("permitted", users.Count); for (int i = 0; i < users.Count; i++) { KeyValuePair<long, string> keyValuePair = users[i]; m_nview.GetZDO().Set("pu_id" + i, keyValuePair.Key); m_nview.GetZDO().Set("pu_name" + i, keyValuePair.Value); } } } private bool IsPermitted(long playerID) { if (m_piece.GetCreator() == playerID) { return true; } foreach (KeyValuePair<long, string> permittedPlayer in GetPermittedPlayers()) { if (permittedPlayer.Key == playerID) { return true; } } return false; } private void AddPermitted(long playerID, string playerName) { List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers(); foreach (KeyValuePair<long, string> item in permittedPlayers) { if (item.Key == playerID) { return; } } permittedPlayers.Add(new KeyValuePair<long, string>(playerID, playerName)); SetPermittedPlayers(permittedPlayers); } private void RemovePermitted(long playerID) { List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers(); if (permittedPlayers.RemoveAll((KeyValuePair<long, string> x) => x.Key == playerID) > 0) { SetPermittedPlayers(permittedPlayers); } } private void AddUserList(StringBuilder text) { List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers(); if (permittedPlayers.Count == 0) { return; } text.Append("\nVinir: "); for (int i = 0; i < permittedPlayers.Count; i++) { text.Append(permittedPlayers[i].Value); if (i != permittedPlayers.Count - 1) { text.Append(", "); } } } private void AddChimeList(StringBuilder text) { List<string> list = new List<string>(); foreach (ChimeType key in PerkConfig.s_powerNameMap.Keys) { if (HasChime(key)) { list.Add(PerkConfig.s_powerNameMap[key]); } } if (list.Count > 0) { text.Append("\nChimes: " + string.Join(", ", list)); } int num = NumWeatherChimes(); if (num > 0) { text.Append($"\nWeather Chimes: {num}"); } } public static void AddToHammer(GameObject prefab) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return; } PieceTable val = null; Object[] array = Resources.FindObjectsOfTypeAll(typeof(PieceTable)); for (int i = 0; i < array.Length; i++) { PieceTable val2 = (PieceTable)array[i]; if (((Object)((Component)val2).gameObject).name.Contains("_HammerPieceTable")) { val = val2; break; } } component.m_name = "Runic Skýla"; if ((Object)(object)val != (Object)null) { if (!val.m_pieces.Contains(prefab)) { val.m_pieces.Add(prefab); } val.m_pieces.Remove(ZNetScene.instance.GetPrefab("guard_stone").gameObject); } ((Behaviour)ZNetScene.instance.GetPrefab("guard_stone").GetComponent<Piece>()).enabled = false; } } [BepInPlugin("Asbjorn.Skyla", "Skyla", "0.7.2")] public class Mod : BaseUnityPlugin { public const string ModGuid = "Asbjorn.Skyla"; private const string AuthorName = "Asbjorn"; private const string ModName = "Skyla"; private const string ModVer = "0.7.2"; private readonly ConfigSync configSync = new ConfigSync("Skyla") { DisplayName = "Skyla", CurrentVersion = "0.7.2", MinimumRequiredVersion = "0.7.2" }; private Harmony _harmony; private void Awake() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown SkylaConfig.SetupConfig(this); configSync.IsLocked = true; SetupWatcher(); _harmony = new Harmony("Asbjorn.Skyla"); _harmony.PatchAll(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (ZNet.instance.IsServer() && File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { ((BaseUnityPlugin)this).Config.Reload(); } } public ConfigEntry<T> SyncedConfig<T>(string group, string name, T defaultVal, string desc) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, defaultVal, new ConfigDescription(desc, (AcceptableValueBase)null, Array.Empty<object>())); configSync.AddConfigEntry<T>(val).SynchronizedConfig = true; return val; } } } namespace Tyrenheim_Skyla.GUI { public class SkylaGUI { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__45_0; public static UnityAction <>9__45_1; public static UnityAction <>9__45_2; public static UnityAction<float> <>9__45_3; internal void <Init>b__45_0() { PrevWeather(); } internal void <Init>b__45_1() { NextWeather(); } internal void <Init>b__45_2() { HideGUI(); } internal void <Init>b__45_3(float <p0>) { UpdateText(); } } private const string s_GUIprefabName = "SkylaGUI"; private static GameObject s_wardGUI; private static Text s_titleText; private static string s_titleTextName = "AegisRoot/AegisCanvas/Aegis/Title"; private static Slider s_radiusSlider; private static string s_radiusSliderName = "AegisRoot/AegisCanvas/Aegis/Zone/RadiusSegment/RadiusSlider"; private static Text s_radiusText; private static string s_radiusTextName = "AegisRoot/AegisCanvas/Aegis/Zone/RadiusSegment/RadiusText"; private static Text s_limitText; private static string s_limitTextName = "AegisRoot/AegisCanvas/Aegis/Zone/LimitSegment/LimitText"; private static Toggle s_containerToggle; private static string s_containerToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/ContainerToggle"; private static Toggle s_doorToggle; private static string s_doorToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/DoorToggle"; private static Toggle s_signToggle; private static string s_signToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/SignToggle"; private static Toggle s_itemStandToggle; private static string s_itemStandToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/ItemStandToggle"; private static Toggle s_harvestableToggle; private static string s_harvestableToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/HarvestableToggle"; private static Toggle s_fermenterToggle; private static string s_fermenterToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/FermenterToggle"; private static Toggle s_beehiveToggle; private static string s_beehiveToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/BeehiveToggle"; private static Toggle s_productsToggle; private static string s_productsToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/ProductsToggle"; private static Toggle s_cartsToggle; private static string s_cartsToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/CartsToggle"; private static Toggle s_shipsToggle; private static string s_shipsToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/ShipsToggle"; private static Toggle s_weatherProtectionToggle; private static string s_weatherToggleName = "AegisRoot/AegisCanvas/Aegis/Protections/WeatherProtectionToggle"; private static GameObject s_stormChimePanel; private static string s_stormChimePanelName = "AegisRoot/AegisCanvas/StormChime"; private static Text s_stormChimeText; private static string s_stormChimeTextName = "AegisRoot/AegisCanvas/StormChime/Weather/bkg/Text"; private static Button s_stormChimePrevButton; private static string s_stormChimePrevButtonName = "AegisRoot/AegisCanvas/StormChime/Weather/Left"; private static Button s_stormChimeNextButton; private static string s_stormChimeNextButtonName = "AegisRoot/AegisCanvas/StormChime/Weather/Right"; private static int s_weatherModeIndex = 0; private static List<PerkConfig.WeatherMode> s_availableWeatherModes = new List<PerkConfig.WeatherMode>(); private static Button s_doneButton; private static string s_doneButtonName = "AegisRoot/AegisCanvas/Aegis/Done_Button_Panel/Done"; private static Skyla s_activeWard; public static void Init() { //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Expected O, but got Unknown //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Expected O, but got Unknown //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Expected O, but got Unknown GameObject[] s_prefabs = Assets.s_prefabs; foreach (GameObject val in s_prefabs) { val.SetActive(false); if (((Object)val).name == "SkylaGUI") { s_wardGUI = Object.Instantiate<GameObject>(val); break; } } Object.DontDestroyOnLoad((Object)(object)s_wardGUI); s_wardGUI.SetActive(false); s_titleText = ((Component)s_wardGUI.transform.Find(s_titleTextName)).gameObject.GetComponent<Text>(); s_radiusSlider = ((Component)s_wardGUI.transform.Find(s_radiusSliderName)).gameObject.GetComponent<Slider>(); s_radiusText = ((Component)s_wardGUI.transform.Find(s_radiusTextName)).gameObject.GetComponent<Text>(); s_limitText = ((Component)s_wardGUI.transform.Find(s_limitTextName)).gameObject.GetComponent<Text>(); s_containerToggle = ((Component)s_wardGUI.transform.Find(s_containerToggleName)).gameObject.GetComponent<Toggle>(); s_doorToggle = ((Component)s_wardGUI.transform.Find(s_doorToggleName)).gameObject.GetComponent<Toggle>(); s_signToggle = ((Component)s_wardGUI.transform.Find(s_signToggleName)).gameObject.GetComponent<Toggle>(); s_itemStandToggle = ((Component)s_wardGUI.transform.Find(s_itemStandToggleName)).gameObject.GetComponent<Toggle>(); s_harvestableToggle = ((Component)s_wardGUI.transform.Find(s_harvestableToggleName)).gameObject.GetComponent<Toggle>(); s_fermenterToggle = ((Component)s_wardGUI.transform.Find(s_fermenterToggleName)).gameObject.GetComponent<Toggle>(); s_beehiveToggle = ((Component)s_wardGUI.transform.Find(s_beehiveToggleName)).gameObject.GetComponent<Toggle>(); s_productsToggle = ((Component)s_wardGUI.transform.Find(s_productsToggleName)).gameObject.GetComponent<Toggle>(); s_cartsToggle = ((Component)s_wardGUI.transform.Find(s_cartsToggleName)).gameObject.GetComponent<Toggle>(); s_shipsToggle = ((Component)s_wardGUI.transform.Find(s_shipsToggleName)).gameObject.GetComponent<Toggle>(); s_weatherProtectionToggle = ((Component)s_wardGUI.transform.Find(s_weatherToggleName)).gameObject.GetComponent<Toggle>(); s_stormChimePanel = ((Component)s_wardGUI.transform.Find(s_stormChimePanelName)).gameObject; s_stormChimeText = ((Component)s_wardGUI.transform.Find(s_stormChimeTextName)).gameObject.GetComponent<Text>(); s_stormChimePrevButton = ((Component)s_wardGUI.transform.Find(s_stormChimePrevButtonName)).gameObject.GetComponent<Button>(); s_stormChimeNextButton = ((Component)s_wardGUI.transform.Find(s_stormChimeNextButtonName)).gameObject.GetComponent<Button>(); ButtonClickedEvent onClick = s_stormChimePrevButton.onClick; object obj = <>c.<>9__45_0; if (obj == null) { UnityAction val2 = delegate { PrevWeather(); }; <>c.<>9__45_0 = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ButtonClickedEvent onClick2 = s_stormChimeNextButton.onClick; object obj2 = <>c.<>9__45_1; if (obj2 == null) { UnityAction val3 = delegate { NextWeather(); }; <>c.<>9__45_1 = val3; obj2 = (object)val3; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); s_doneButton = ((Component)s_wardGUI.transform.Find(s_doneButtonName)).gameObject.GetComponent<Button>(); ButtonClickedEvent onClick3 = s_doneButton.onClick; object obj3 = <>c.<>9__45_2; if (obj3 == null) { UnityAction val4 = delegate { HideGUI(); }; <>c.<>9__45_2 = val4; obj3 = (object)val4; } ((UnityEvent)onClick3).AddListener((UnityAction)obj3); ((UnityEvent<float>)(object)s_radiusSlider.onValueChanged).AddListener((UnityAction<float>)delegate { UpdateText(); }); } public static void ToggleGUI(Skyla ward) { if (s_wardGUI.activeSelf) { HideGUI(); } else { ShowGUI(ward); } } private static void EnableMouseEtc(bool enable) { if (enable) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; ((Behaviour)GameCamera.instance).enabled = false; ((Behaviour)((Component)Player.m_localPlayer).GetComponent<PlayerController>()).enabled = false; } else { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; ((Behaviour)GameCamera.instance).enabled = true; ((Behaviour)((Component)Player.m_localPlayer).GetComponent<PlayerController>()).enabled = true; } } private static void UpdateText() { s_radiusSlider.SetValueWithoutNotify(Math.Min(s_radiusSlider.value, LocalManager.GetMaxRadiusForSkyla(s_activeWard))); s_radiusText.text = $"{s_radiusSlider.value:0.0} m"; float remainingArea = LocalManager.GetRemainingArea(); float radius = s_activeWard.GetRadius(); float num = (float)Math.PI * radius * radius; float value = s_radiusSlider.value; float num2 = (float)Math.PI * value * value; float num3 = remainingArea + num - num2; s_limitText.text = $"{num3:0,0.0} m²"; } private static void SetupWeatherOptions() { List<Skyla.ChimeType> weatherChimes = s_activeWard.GetWeatherChimes(); s_availableWeatherModes.Clear(); s_weatherModeIndex = 0; s_availableWeatherModes.Add(PerkConfig.WeatherMode.WEATHER_NONE); PerkConfig.WeatherMode stormChimeWeatherMode = s_activeWard.GetStormChimeWeatherMode(); foreach (Skyla.ChimeType item in weatherChimes) { PerkConfig.WeatherMode weatherMode = Skyla.s_weatherChimeMap[item]; s_availableWeatherModes.Add(weatherMode); if (weatherMode == stormChimeWeatherMode) { s_weatherModeIndex = s_availableWeatherModes.Count - 1; } } } private static void UpdateStormChimeWeather() { if (PerkConfig.s_weatherNameMap.TryGetValue(s_availableWeatherModes[s_weatherModeIndex], out var value)) { s_stormChimeText.text = value; } } private static void NextWeather() { s_weatherModeIndex++; if (s_weatherModeIndex >= s_availableWeatherModes.Count) { s_weatherModeIndex = 0; } UpdateStormChimeWeather(); } private static void PrevWeather() { s_weatherModeIndex--; if (s_weatherModeIndex < 0) { s_weatherModeIndex = s_availableWeatherModes.Count - 1; } UpdateStormChimeWeather(); } private static void ShowGUI(Skyla ward) { s_activeWard = ward; s_radiusSlider.SetValueWithoutNotify(ward.GetRadius()); s_titleText.text = string.Format("{0} Configuration", "Skýla"); s_radiusSlider.maxValue = SkylaConfig.MaxSkylaRadius(); s_containerToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_CONTAINER)); s_doorToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_DOOR)); s_signToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_SIGN)); s_itemStandToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_ITEMSTAND)); s_harvestableToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_PICKABLE)); s_fermenterToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_FERMENTER)); s_beehiveToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_BEEHIVE)); s_productsToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_PICKUP_FACTORY_OUTPUT)); s_cartsToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_WAGON)); s_shipsToggle.SetIsOnWithoutNotify(!ward.CheckPublicAccess(Skyla.ActionType.ACTION_USE_SHIP)); s_weatherProtectionToggle.SetIsOnWithoutNotify(ward.CheckPublicAccess(Skyla.ActionType.PROTECTION_WEATHER)); s_stormChimePanel.SetActive(ward.NumWeatherChimes() > 0); SetupWeatherOptions(); UpdateStormChimeWeather(); UpdateText(); s_wardGUI.SetActive(true); EnableMouseEtc(enable: true); } private static void HideGUI() { if (Object.op_Implicit((Object)(object)s_activeWard)) { s_activeWard.SetRadius(s_radiusSlider.value); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_CONTAINER, !s_containerToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_DOOR, !s_doorToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_SIGN, !s_signToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_ITEMSTAND, !s_itemStandToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_PICKABLE, !s_harvestableToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_FERMENTER, !s_fermenterToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_BEEHIVE, !s_beehiveToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_PICKUP_FACTORY_OUTPUT, !s_productsToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_WAGON, !s_cartsToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.ACTION_USE_SHIP, !s_shipsToggle.isOn); s_activeWard.SetPublicAccess(Skyla.ActionType.PROTECTION_WEATHER, s_weatherProtectionToggle.isOn); s_activeWard.SetStormChimeWeatherMode(s_availableWeatherModes[s_weatherModeIndex]); s_activeWard.Broadcast(); } s_wardGUI.SetActive(false); s_activeWard = null; EnableMouseEtc(enable: false); } } } namespace Tyrenheim_Skyla.Patches { internal class Humanoid_Patch { [HarmonyPatch(typeof(Humanoid), "Pickup")] public static class Humanoid_Pickup_Patch { public static bool Prefix(Humanoid __instance, GameObject go, bool autoequip, bool autoPickupDelay, ref bool __result) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return false; } if ((Object)(object)go == (Object)null) { return true; } ZNetView component = go.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("ProtectedItem", false)) { __result = Skyla.CheckAccess((Character)(object)__instance, go.transform.position, Skyla.ActionType.ACTION_PICKUP_FACTORY_OUTPUT); return __result; } return true; } } } } 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; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = (from p in ZNet.instance.GetPeers() where adminList.Contains(p.m_rpc.GetSocket().GetHostName()) select p).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return