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 WorldControl v3.0.5
plugins/WorldControl.dll
Decompiled a week 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using WorldControl.Compat; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("WorldControl")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("3.0.5.0")] [assembly: AssemblyInformationalVersion("3.0.5+df839a2fcf8ee6e01fd4c0ffd524be9bb9d379db")] [assembly: AssemblyProduct("WorldControl")] [assembly: AssemblyTitle("WorldControl")] [assembly: AssemblyVersion("3.0.5.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WorldControl { [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInPlugin("dezzycode.valheim.windcontrol", "World Control", "3.0.5")] [BepInDependency("com.jotunn.jotunn", "2.30.0")] public sealed class Plugin : BaseUnityPlugin { private struct EitrAttackContextState { public int Depth; public bool Secondary; public bool Changed; } private struct EitrReloadCostState { public Attack Attack; public float Value; public bool Changed; } private struct EitrRepairCostState { public Attack Attack; public float Value; public bool Changed; } [HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[] { typeof(Character), typeof(bool) })] private static class EitrAttackContextPatch { private static void Prefix(Humanoid __instance, bool __1, ref EitrAttackContextState __state) { __state = new EitrAttackContextState { Depth = eitrAttackContextDepth, Secondary = eitrAttackContextSecondary, Changed = false }; if (CanScaleLocalEitr((Character)(object)((__instance is Player) ? __instance : null))) { eitrAttackContextDepth++; eitrAttackContextSecondary = __1; __state.Changed = true; } } private static Exception Finalizer(Exception __exception, ref EitrAttackContextState __state) { RestoreEitrAttackContext(ref __state); return __exception; } } [HarmonyPatch(typeof(Attack), "GetAttackEitr", new Type[] { })] private static class EitrAttackCostPatch { private static void Postfix(Attack __instance, Humanoid ___m_character, ref float __result) { if (CanScaleLocalEitr((Character)(object)___m_character) && !(__result <= 0f)) { bool flag; if (eitrAttackContextDepth <= 0) { flag = __instance == eitrActiveAttack && eitrActiveAttackSecondary; } else { flag = eitrAttackContextSecondary; eitrActiveAttack = __instance; eitrActiveAttackSecondary = flag; } float num = (flag ? instance.playerRules.SecondaryEitr : instance.playerRules.PrimaryEitr); if (num != 1f) { __result *= num; } } } } [HarmonyPatch(typeof(ItemData), "GetDrawEitrDrain")] private static class EitrDrawCostPatch { private static void Postfix(ItemData __instance, ref float __result) { Plugin instance = Plugin.instance; Player localPlayer = Player.m_localPlayer; if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && !((Object)(object)localPlayer == (Object)null) && __instance != null && !(__result <= 0f)) { float drawEitr = instance.playerRules.DrawEitr; if (drawEitr != 1f && ((Humanoid)localPlayer).GetCurrentWeapon() == __instance) { __result *= drawEitr; } } } } [HarmonyPatch(typeof(Player), "UpdateWeaponLoading", new Type[] { typeof(ItemData), typeof(float) })] private static class EitrReloadCostPatch { private static void Prefix(Player __instance, ItemData __0, ref EitrReloadCostState __state) { __state = ScaleReloadEitrTemporarily(__instance, __0); } private static Exception Finalizer(Exception __exception, ref EitrReloadCostState __state) { RestoreReloadEitr(ref __state); return __exception; } } [HarmonyPatch(typeof(Player), "Repair", new Type[] { typeof(ItemData), typeof(Piece) })] private static class EitrRepairCostPatch { private static void Prefix(Player __instance, ItemData __0, ref EitrRepairCostState __state) { __state = ScaleRepairEitrTemporarily(__instance, __0); } private static Exception Finalizer(Exception __exception, ref EitrRepairCostState __state) { RestoreRepairEitr(ref __state); return __exception; } } private struct RegenTickState { public float Stamina; public float Eitr; public bool Changed; } [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] private static class PlayerRegenCalculationPatch { private static void Prefix(Player __instance, ref RegenTickState __state) { __state = default(RegenTickState); Plugin instance = Plugin.instance; if ((Object)(object)instance == (Object)null || !instance.playerVitalsSynced || (Object)(object)__instance == (Object)null || __instance != Player.m_localPlayer) { return; } float staminaRegen = instance.playerVitals.StaminaRegen; float eitrRegen = instance.playerVitals.EitrRegen; if (staminaRegen != 1f || eitrRegen != 1f) { __state.Stamina = __instance.m_staminaRegen; __state.Eitr = __instance.m_eiterRegen; __state.Changed = true; if (staminaRegen != 1f) { __instance.m_staminaRegen = __state.Stamina * staminaRegen; } if (eitrRegen != 1f) { __instance.m_eiterRegen = __state.Eitr * eitrRegen; } } } private static Exception Finalizer(Exception __exception, Player __instance, ref RegenTickState __state) { RestoreRegenTick(__instance, ref __state); return __exception; } } [HarmonyPatch(typeof(EnvMan), "FixedUpdate")] private static class EnvironmentPatch { private static void Prefix(EnvMan __instance) { Plugin instance = Plugin.instance; if ((Object)(object)instance == (Object)null || instance.session == null || !instance.session.Synced || instance.session.State.Revision == 0L) { return; } if ((Object)(object)instance.controlledEnvironment != (Object)(object)__instance) { instance.RestoreEnvironment(); instance.controlledEnvironment = __instance; instance.savedWeather = __instance.m_debugEnv; instance.savedTimeEnabled = __instance.m_debugTimeOfDay; instance.savedTime = __instance.m_debugTime; instance.savedWindEnabled = __instance.m_debugWind; instance.savedWindAngle = __instance.m_debugWindAngle; instance.savedWindStrength = __instance.m_debugWindIntensity; instance.controlledEnvironmentRevision = -1L; } long revision = instance.session.State.Revision; if (instance.controlledEnvironmentRevision != revision) { Request settings = instance.session.State.Settings; __instance.m_debugEnv = settings.Weather; if (settings.WindOn) { __instance.SetDebugWind(settings.Angle, settings.Strength); } else { __instance.ResetDebugWind(); } if (settings.TimeMode == 1) { instance.ownedTime = true; __instance.m_debugTimeOfDay = false; } else if (instance.ownedTime) { __instance.m_debugTimeOfDay = false; instance.ownedTime = false; } instance.controlledEnvironmentRevision = revision; } } } [HarmonyPatch(typeof(EnvMan), "RescaleDayFraction")] private static class HeldDayTargetPatch { private static void Postfix(EnvMan __instance, ref float __result) { Plugin instance = Plugin.instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.controlledEnvironment == (Object)(object)__instance && instance.session != null && instance.session.Synced && instance.session.State.Settings.TimeMode == 1) { __result = instance.session.State.Settings.Hour / 24f; } } } internal struct BannedPlayer { public string Id; public string Name; } [HarmonyPatch(typeof(Plugin), "PlayerRule")] private static class PlayerRuleFiveMaxPatch { private static void Postfix(float value, ref bool __result) { __result = !float.IsNaN(value) && !float.IsInfinity(value) && value >= 0f && value <= 5f; } } [HarmonyPatch(typeof(Plugin), "ValidPlayerRules")] private static class PlayerRulesBuffOnlyValidationPatch { [HarmonyPriority(0)] private static void Postfix(PlayerResourceRules r, ref bool __result) { if (__result) { __result = BuffOnlyPlayerRules(r); } } } private sealed class AttackBaseline { public float AttackAdrenaline; } private sealed class ShieldBaseline { public float Block; public float Parry; } [HarmonyPatch(typeof(Player), "GetBuildStamina")] private static class PlayerRulesHomeStaminaPatch { private static void Postfix(Player __instance, ref float __result) { Plugin instance = Plugin.instance; if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { __result *= instance.playerRules.HomeStamina; } } } private sealed class PlayerLine { public GameObject Row; public TMP_Text Name; public TMP_Text Where; public Button Bring; public Button Visit; public Button Kick; public Button Ban; public Button Admin; public TMP_Text AdminText; } private sealed class BannedLine { public GameObject Row; public TMP_Text Name; public TMP_Text Id; public Button Unban; } [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] private static class PlayerVitalMaximumPatch { private static void Postfix(Player __instance, ref float __0, ref float __1, ref float __2) { Plugin instance = Plugin.instance; if (!((Object)(object)instance == (Object)null) && instance.playerVitalsSynced && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { __0 *= instance.playerVitals.MaxHealth; __1 *= instance.playerVitals.MaxStamina; __2 *= instance.playerVitals.MaxEitr; } } } [HarmonyPatch(typeof(Plugin), "EndSession")] private static class PlayerVitalsSessionEndPatch { private static void Prefix(Plugin __instance) { if ((Object)(object)__instance != (Object)null) { __instance.RestorePlayerVitalsLocal(); } } } [HarmonyPatch(typeof(Plugin), "ValidVitalMax")] private static class PlayerVitalsMaxValidationPatch { private static void Postfix(float value, ref bool __result) { __result = !float.IsNaN(value) && !float.IsInfinity(value) && value >= 1f && value <= 5f; } } [HarmonyPatch(typeof(Plugin), "ValidVitalRegen")] private static class PlayerVitalsRegenValidationPatch { private static void Postfix(float value, ref bool __result) { __result = !float.IsNaN(value) && !float.IsInfinity(value) && value >= 1f && value <= 5f; } } [HarmonyPatch(typeof(RandEventSystem), "UpdateRandomEvent")] private static class EventPausePatch { private static bool Prefix() { if (!((Object)(object)instance == (Object)null) && instance.session != null && instance.session.Server) { return !instance.session.State.Settings.EventsPaused; } return true; } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] private static class SessionEndPatch { private static void Prefix(ZNet __instance) { if ((Object)(object)instance != (Object)null && instance.network == __instance) { instance.EndSession(); } } } private struct RainWetState { public bool Original; public bool Changed; } [HarmonyPatch(typeof(WearNTear), "IsWet")] private static class RainDamageWearPatch { private static void Prefix(WearNTear __instance, ref RainWetState __state) { __state = default(RainWetState); Plugin instance = Plugin.instance; if ((Object)(object)instance == (Object)null || instance.session == null || !instance.session.Synced || !instance.session.State.Settings.NoRainDamage || (Object)(object)__instance == (Object)null || !TryGetRainWetField()) { return; } try { ref bool reference = ref rainWetField.Invoke(__instance); __state.Original = reference; __state.Changed = true; reference = false; } catch { } } private static Exception Finalizer(Exception __exception, WearNTear __instance, ref RainWetState __state) { RestoreRainWet(__instance, ref __state); return __exception; } } [HarmonyPatch(typeof(Plugin), "Remember")] private static class RainDamageRememberPatch { [HarmonyPriority(0)] private static void Postfix(Plugin __instance) { if ((Object)(object)__instance != (Object)null) { __instance.RememberRainDamageSetting(); } } } [HarmonyPatch(typeof(Plugin), "Recall")] private static class RainDamageRecallPatch { [HarmonyPriority(0)] private static void Postfix(Plugin __instance) { if ((Object)(object)__instance != (Object)null) { __instance.RecallRainDamageSetting(); } } } private struct StaminaAttackContextState { public int Depth; public bool Secondary; public bool Changed; } private struct StaminaReloadState { public Attack Attack; public float Value; public bool Changed; } private struct BlockStaminaState { public float Normal; public float Perfect; public bool Changed; } [HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[] { typeof(Character), typeof(bool) })] private static class StaminaAttackContextPatch { private static void Prefix(Humanoid __instance, bool __1, ref StaminaAttackContextState __state) { __state = new StaminaAttackContextState { Depth = staminaAttackContextDepth, Secondary = staminaAttackContextSecondary, Changed = false }; if (CanScaleLocalStamina((Character)(object)((__instance is Player) ? __instance : null))) { staminaAttackContextDepth++; staminaAttackContextSecondary = __1; __state.Changed = true; } } private static Exception Finalizer(Exception __exception, ref StaminaAttackContextState __state) { RestoreStaminaAttackContext(ref __state); return __exception; } } [HarmonyPatch(typeof(Attack), "GetAttackStamina", new Type[] { })] private static class StaminaAttackCostPatch { private static void Postfix(Attack __instance, Humanoid ___m_character, ref float __result) { Plugin instance = Plugin.instance; if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && CanScaleLocalStamina((Character)(object)___m_character) && !(__result <= 0f) && (__instance == null || !__instance.m_isHomeItem)) { bool flag; if (staminaAttackContextDepth <= 0) { flag = __instance == staminaActiveAttack && staminaActiveAttackSecondary; } else { flag = staminaAttackContextSecondary; staminaActiveAttack = __instance; staminaActiveAttackSecondary = flag; } float num = (flag ? instance.playerRules.SecondaryStamina : instance.playerRules.PrimaryStamina); if (num != 1f) { __result *= num; } } } } [HarmonyPatch(typeof(ItemData), "GetDrawStaminaDrain")] private static class StaminaDrawCostPatch { private static void Postfix(ItemData __instance, ref float __result) { Plugin instance = Plugin.instance; Player localPlayer = Player.m_localPlayer; if (!((Object)(object)instance == (Object)null) && instance.playerRulesSynced && !((Object)(object)localPlayer == (Object)null) && __instance != null && !(__result <= 0f)) { float drawStamina = instance.playerRules.DrawStamina; if (drawStamina != 1f && ((Humanoid)localPlayer).GetCurrentWeapon() == __instance) { __result *= drawStamina; } } } } [HarmonyPatch(typeof(Player), "UpdateWeaponLoading", new Type[] { typeof(ItemData), typeof(float) })] private static class StaminaReloadCostPatch { private static void Prefix(Player __instance, ItemData __0, ref StaminaReloadState __state) { __state = default(StaminaReloadState); if (CanScaleLocalStamina((Character)(object)__instance) && __0 != null && __0.m_shared != null && __0.m_shared.m_attack != null) { float reloadStamina = instance.playerRules.ReloadStamina; if (reloadStamina != 1f) { Attack val = (__state.Attack = __0.m_shared.m_attack); __state.Value = val.m_reloadStaminaDrain; __state.Changed = true; val.m_reloadStaminaDrain = __state.Value * reloadStamina; } } } private static Exception Finalizer(Exception __exception, ref StaminaReloadState __state) { RestoreStaminaReload(ref __state); return __exception; } } [HarmonyPatch(typeof(Humanoid), "BlockAttack", new Type[] { typeof(HitData), typeof(Character) })] private static class BlockStaminaCostPatch { private static void Prefix(Humanoid __instance, ref BlockStaminaState __state) { __state = default(BlockStaminaState); if (CanScaleLocalStamina((Character)(object)((__instance is Player) ? __instance : null))) { float block = instance.playerRules.Block; if (block != 1f) { __state.Normal = __instance.m_blockStaminaDrain; __state.Perfect = __instance.m_perfectBlockStaminaDrain; __state.Changed = true; __instance.m_blockStaminaDrain = __state.Normal * block; __instance.m_perfectBlockStaminaDrain = __state.Perfect * block; } } } private static Exception Finalizer(Exception __exception, Humanoid __instance, ref BlockStaminaState __state) { RestoreBlockStamina(__instance, ref __state); return __exception; } } private sealed class TerrainOpSnapshot { private readonly TerrainOp op; private readonly float level; private readonly float raise; private readonly float smooth; private readonly float paint; public TerrainOpSnapshot(TerrainOp value) { op = value; Settings settings = value.m_settings; level = settings.m_levelRadius; raise = settings.m_raiseRadius; smooth = settings.m_smoothRadius; paint = settings.m_paintRadius; } public void Restore() { if (!((Object)(object)op == (Object)null) && op.m_settings != null) { op.m_settings.m_levelRadius = level; op.m_settings.m_raiseRadius = raise; op.m_settings.m_smoothRadius = smooth; op.m_settings.m_paintRadius = paint; } } } private sealed class TerrainModifierSnapshot { private readonly TerrainModifier modifier; private readonly float level; private readonly float smooth; public TerrainModifierSnapshot(TerrainModifier value) { modifier = value; level = value.m_levelRadius; smooth = value.m_smoothRadius; } public void Restore() { if (!((Object)(object)modifier == (Object)null)) { modifier.m_levelRadius = level; modifier.m_smoothRadius = smooth; } } } private sealed class PlacementRadiusScope { public readonly HashSet<int> Seen = new HashSet<int>(); public readonly List<TerrainOpSnapshot> Ops = new List<TerrainOpSnapshot>(); public readonly List<TerrainModifierSnapshot> Modifiers = new List<TerrainModifierSnapshot>(); public void Restore() { foreach (TerrainOpSnapshot op in Ops) { op.Restore(); } foreach (TerrainModifierSnapshot modifier in Modifiers) { modifier.Restore(); } } } [HarmonyPatch] private static class TerrainPlacementPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "TryPlacePiece") && !(methodInfo.ReturnType != typeof(bool))) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Piece)) { yield return methodInfo; } } } } [HarmonyPriority(800)] private static bool Prefix(Player __instance, Piece piece, ref bool __result) { RestoreTerrainRadiusScope(); Plugin instance = Plugin.instance; if ((Object)(object)instance == (Object)null || instance.terrainEnabled == null || !instance.terrainEnabled.Value || !instance.CanEdit || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)piece == (Object)null) { return true; } if (instance.IsTerrainRampPiece(piece)) { __result = instance.ApplyRamp(__instance); return false; } if (instance.IsTerrainRevertPiece(piece)) { __result = instance.ApplyRevert(__instance); return false; } if (instance.terrainToolRadiusEnabled == null || !instance.terrainToolRadiusEnabled.Value) { return true; } TerrainToolKind terrainToolKind = GetTerrainToolKind(((Humanoid)__instance).GetCurrentWeapon()); if (terrainToolKind == TerrainToolKind.None) { return true; } float configuredTerrainRadius = instance.GetConfiguredTerrainRadius(terrainToolKind); PlacementRadiusScope placementRadiusScope = new PlacementRadiusScope(); try { ScaleTerrainComponents(((Component)piece).gameObject, configuredTerrainRadius, placementRadiusScope); Piece val = null; try { val = __instance.GetSelectedPiece(); } catch { } if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)piece) { ScaleTerrainComponents(((Component)val).gameObject, configuredTerrainRadius, placementRadiusScope); } if (placementRadiusScope.Ops.Count == 0 && placementRadiusScope.Modifiers.Count == 0) { placementRadiusScope.Restore(); return true; } terrainActiveRadiusScope = placementRadiusScope; } catch { placementRadiusScope.Restore(); throw; } return true; } private static Exception Finalizer(Exception __exception) { RestoreTerrainRadiusScope(); return __exception; } } [HarmonyPatch] private static class TerrainGridMovementPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "SetControls") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); foreach (ParameterInfo parameterInfo in parameters) { if (parameterInfo.Name == "movedir" && parameterInfo.ParameterType == typeof(Vector3)) { yield return methodInfo; break; } } } } private static void Prefix(Player __instance, ref Vector3 movedir) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.instance; if ((Object)(object)instance == (Object)null || instance.terrainEnabled == null || !instance.terrainEnabled.Value || instance.terrainGridMovement == null || !instance.terrainGridMovement.Value || !instance.CanEdit || instance.windowOpen || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !IsTerrainPickaxe(((Humanoid)__instance).GetCurrentWeapon()) || instance.terrainFlattenHold == null || !ShortcutHeld(instance.terrainFlattenHold.Value)) { return; } Vector2 val = new Vector2(movedir.x, movedir.z); float num = Mathf.Clamp01(((Vector2)(ref val)).magnitude); if (!(num < 0.001f)) { Vector3 val2 = ((Character)__instance).GetLookDir(); val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.001f) { val2 = ((Component)__instance).transform.forward; val2.y = 0f; } ((Vector3)(ref val2)).Normalize(); Vector3 val3 = Vector3.Cross(Vector3.up, val2); Vector3 normalized = ((Vector3)(ref val3)).normalized; Vector3 val4 = val2 * movedir.z + normalized * movedir.x; val4.y = 0f; if (!(((Vector3)(ref val4)).sqrMagnitude < 0.001f)) { ((Vector3)(ref val4)).Normalize(); float num2 = Mathf.Round(Mathf.Atan2(val4.x, val4.z) * 57.29578f / 45f) * 45f * ((float)Math.PI / 180f); Vector3 val5 = new Vector3(Mathf.Sin(num2), 0f, Mathf.Cos(num2)) * num; movedir.x = Vector3.Dot(val5, normalized); movedir.z = Vector3.Dot(val5, val2); movedir.y = 0f; } } } } [HarmonyPatch(typeof(Plugin), "CreateTerrainActionPiece")] private static class TerrainActionPieceUsagePatch { [HarmonyPriority(0)] private static void Postfix(PieceTable table, GameObject __result) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)table == (Object)null || (Object)(object)__result == (Object)null) { return; } Piece component = __result.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return; } int num = FindHoeGroundIndex(table); if (num >= 0 && num < table.m_pieces.Count && (Object)(object)table.m_pieces[num] != (Object)null) { Piece component2 = table.m_pieces[num].GetComponent<Piece>(); if ((Object)(object)component2 != (Object)null) { component.m_category = component2.m_category; component.m_usage = (UsageTagFlags)(((int)component2.m_usage == 0) ? 1 : ((int)component2.m_usage)); return; } } if ((int)component.m_usage == 0) { component.m_usage = (UsageTagFlags)1; } } } private sealed class SearchEntry { public int Page; public int Mode; public string Section; public RectTransform Row; public TMP_Text Title; public TMP_Text Description; } private sealed class FoundLine { public GameObject Row; public TMP_Text Title; public TMP_Text Where; public SearchEntry Entry; } [HarmonyPatch(typeof(ZCursor), "set_LockState")] private static class PointerLockGuard { [HarmonyPriority(0)] private static bool Prefix(ref CursorLockMode value) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 if (!OwnsPointer) { return true; } if (value) { instance.preventedCursorLocks++; } value = (CursorLockMode)0; return (int)Cursor.lockState > 0; } } [HarmonyPatch(typeof(ZCursor), "Hide")] private static class PointerVisibilityGuard { private static bool Prefix() { return !OwnsPointer; } } [HarmonyPatch(typeof(Menu), "Update")] private static class EscapePatch { private static bool Prefix() { return !BlockInput; } } private static int eitrAttackContextDepth; private static bool eitrAttackContextSecondary; private static Attack eitrActiveAttack; private static bool eitrActiveAttackSecondary; private EnvMan controlledEnvironment; private string savedWeather; private float savedTime; private float savedWindAngle; private float savedWindStrength; private bool savedTimeEnabled; private bool savedWindEnabled; private bool ownedTime; private long controlledEnvironmentRevision = -1L; private const string ModerateRpc = "DezzyCode.WorldControl.Moderate.v1"; private const string ModerationRpc = "DezzyCode.WorldControl.Moderation.v1"; private const int ModerationLimit = 4096; private ConfigEntry<string> bannedNames; private readonly Dictionary<ZRpc, float> moderationEdits = new Dictionary<ZRpc, float>(); private static FieldInfo adminListField; private static FieldInfo bannedListField; private static MethodInfo kickMethod; private static MethodInfo banMethod; private static MethodInfo unbanMethod; private static MethodInfo sendAdminListMethod; private static MethodInfo listAdd; private static MethodInfo listRemove; private static MethodInfo listGet; private static bool moderationReflected; private static bool moderationUsable; private readonly HashSet<ZDOID> moderationOnline = new HashSet<ZDOID>(); private readonly HashSet<ZDOID> moderationAdmins = new HashSet<ZDOID>(); private readonly List<BannedPlayer> moderationBanned = new List<BannedPlayer>(); private bool moderationKnown; private float nextModerationQuery; private const float GoWidth = 110f; private const float PlayerReductionMin = 0f; private const float PlayerReductionMax = 1f; private const float PlayerBoostMin = 1f; private const float PlayerBoostMax = 5f; private const float ConfirmWidth = 560f; private const float ConfirmHeight = 240f; private GameObject confirmOverlay; private TMP_Text confirmTitle; private TMP_Text confirmQuestion; private TMP_Text confirmYesText; private Action confirmed; private const int PlayerRulesWireVersion = 1; private const string PlayerRulesRequestRpc = "DezzyCode.WorldControl.PlayerRules.Request.v1"; private const string PlayerRulesStateRpc = "DezzyCode.WorldControl.PlayerRules.State.v1"; private const float PlayerRuleMin = 0f; private const float PlayerRuleMax = 3f; private readonly HashSet<ZRpc> playerRulesRegistered = new HashSet<ZRpc>(); private readonly Dictionary<ZRpc, float> playerRulesRequests = new Dictionary<ZRpc, float>(); private readonly Dictionary<ZRpc, float> playerRulesEdits = new Dictionary<ZRpc, float>(); private readonly List<ZRpc> playerRulesStale = new List<ZRpc>(); private ConfigEntry<string> playerRulesStored; private bool playerRulesConfigReady; private bool playerRulesLoadedForServer; private bool playerRulesSynced; private bool playerRulesDraftDirty; private long playerRulesRevision; private float nextPlayerRulesQuery; private ZNet playerRulesNetwork; private PlayerResourceRules playerRules = PlayerResourceRules.Vanilla; private PlayerResourceRules playerRulesDraft = PlayerResourceRules.Vanilla; private int playerPageMode = 4; private Player playerRulesAppliedPlayer; private readonly Dictionary<string, float> playerFieldBaselines = new Dictionary<string, float>(); private ObjectDB playerRulesObjectDb; private long playerRulesAppliedRevision = -1L; private readonly Dictionary<Attack, AttackBaseline> attackBaselines = new Dictionary<Attack, AttackBaseline>(); private readonly Dictionary<Projectile, float> projectileBaselines = new Dictionary<Projectile, float>(); private readonly Dictionary<SharedData, ShieldBaseline> shieldBaselines = new Dictionary<SharedData, ShieldBaseline>(); private readonly List<PlayerLine> playerLines = new List<PlayerLine>(); private readonly List<BannedLine> bannedLines = new List<BannedLine>(); private Transform playerList; private RectTransform onlineHeading; private RectTransform bannedHeading; private GameObject noneBanned; private GameObject oldServer; private const float SubTabWidth = 130f; private const float SubTabHeight = 38f; private const float ValueResetWidth = 230f; private const int ValueSteps = 20; private readonly List<GameObject>[] valueGroups = new List<GameObject>[4] { new List<GameObject>(), new List<GameObject>(), new List<GameObject>(), new List<GameObject>() }; private static readonly int[] ValueModes = new int[4] { 4, 1, 2, 3 }; private static readonly string[] ValueTabKeys = new string[4] { "values.vitals", "values.stamina", "values.eitr", "values.adrenaline" }; private const int PlayerVitalsWireVersion = 2; private const string PlayerVitalsRequestRpc = "DezzyCode.WorldControl.PlayerVitals.Request.v1"; private const string PlayerVitalsStateRpc = "DezzyCode.WorldControl.PlayerVitals.State.v1"; private const float VitalMaxMin = 0.1f; private const float VitalMaxMax = 3f; private const float VitalRegenMin = 0f; private const float VitalRegenMax = 3f; private readonly HashSet<ZRpc> playerVitalsRegistered = new HashSet<ZRpc>(); private readonly Dictionary<ZRpc, float> playerVitalsRequests = new Dictionary<ZRpc, float>(); private readonly Dictionary<ZRpc, float> playerVitalsEdits = new Dictionary<ZRpc, float>(); private readonly List<ZRpc> playerVitalsStale = new List<ZRpc>(); private ConfigEntry<string> playerVitalsStored; private bool playerVitalsConfigReady; private bool playerVitalsLoadedForServer; private bool playerVitalsSynced; private bool playerVitalsDraftDirty; private long playerVitalsRevision; private long playerVitalsAppliedRevision = -1L; private float nextPlayerVitalsQuery; private float nextPlayerVitalsMaintenance; private ZNet playerVitalsNetwork; private PlayerVitalRules playerVitals = PlayerVitalRules.Vanilla; private PlayerVitalRules playerVitalsDraft = PlayerVitalRules.Vanilla; private Player playerVitalsAppliedPlayer; private bool playerVitalsUpdateFoodWarned; private static MethodInfo PlayerUpdateFoodMethod; private static bool playerUpdateFoodResolved; private const float VitalBoostMin = 1f; private const float VitalBoostMax = 5f; public const string PluginGuid = "dezzycode.valheim.windcontrol"; private const string RequestRpc = "DezzyCode.WorldControl.Request.v3"; private const string StateRpc = "DezzyCode.WorldControl.State.v3"; private const string TeleportRpc = "DezzyCode.WorldControl.Teleport.v1"; private const string SayRpc = "DezzyCode.WorldControl.Say.v1"; private static Plugin instance; private Harmony harmony; private ZNet network; private Session session; private readonly HashSet<ZRpc> registered = new HashSet<ZRpc>(); private readonly HashSet<ZRpc> participants = new HashSet<ZRpc>(); private readonly List<ZRpc> stale = new List<ZRpc>(); private readonly Dictionary<ZRpc, ZNetPeer> peersByRpc = new Dictionary<ZRpc, ZNetPeer>(); private readonly Dictionary<ZRpc, float> edits = new Dictionary<ZRpc, float>(); private readonly Dictionary<ZRpc, float> queries = new Dictionary<ZRpc, float>(); private InitialSync initialSync = new InitialSync(); private ZRpc serverConnection; private bool openWhenSynced; private float nextManualQuery; private float nextPeerMaintenance; private int knownPeerCount = -1; private ConfigEntry<KeyCode> toggleKey; private ConfigEntry<string> language; private readonly ConfigEntry<string>[] presets = new ConfigEntry<string>[3]; private readonly ConfigEntry<string>[] places = new ConfigEntry<string>[3]; private ConfigEntry<string> stored; private bool recalled; private string builtFor = "Auto"; private bool windowOpen; private int blockThroughFrame = -1; private string statusKey = "status.checking"; private Request draft = Protocol.Defaults; private static FieldRef<RandEventSystem, RandomEvent> randomEventField; private static bool randomEventTried; private static FieldRef<WearNTear, bool> rainWetField; private static bool rainWetFieldTried; private float nextPlayerRulesMaintenance; private float nextPlayerVitalsTickOptimized; private static int staminaAttackContextDepth; private static bool staminaAttackContextSecondary; private static Attack staminaActiveAttack; private static bool staminaActiveAttackSecondary; private ConfigEntry<bool> terrainEnabled; private ConfigEntry<float> terrainFlattenSize; private ConfigEntry<float> terrainFlattenSmoothness; private ConfigEntry<TerrainFlattenShape> terrainFlattenShape; private ConfigEntry<TerrainGroundTexture> terrainGroundTexture; private ConfigEntry<KeyboardShortcut> terrainFlattenHold; private ConfigEntry<bool> terrainGridMovement; private ConfigEntry<bool> terrainToolRadiusEnabled; private ConfigEntry<float> terrainHoeRadius; private ConfigEntry<float> terrainCultivatorRadius; private ConfigEntry<KeyboardShortcut> terrainRadiusIncrease; private ConfigEntry<KeyboardShortcut> terrainRadiusDecrease; private ConfigEntry<float> terrainRampThickness; private ConfigEntry<float> terrainRevertRadius; private bool terrainHolding; private Vector3 terrainLastCenter = new Vector3(100000f, 100000f, 100000f); private float terrainLastSize = -1f; private float terrainLastSmooth = -1f; private float terrainLastApply = -10f; private TerrainFlattenShape terrainLastShape; private TerrainGroundTexture terrainLastTexture; private bool terrainBackendWarned; private GameObject terrainPreviewRoot; private LineRenderer flattenPreview; private LineRenderer radiusPreview; private LineRenderer rampOutlinePreview; private LineRenderer rampCenterPreview; private LineRenderer revertPreview; private Material flattenPreviewMaterial; private Material radiusPreviewMaterial; private Material rampPreviewMaterial; private Material revertPreviewMaterial; private PieceTable terrainHoeTable; private GameObject terrainRampPrefab; private GameObject terrainRevertPrefab; private Player terrainPiecesTaughtTo; private static FieldRef<Player, HashSet<string>> terrainKnownRecipes; private static bool terrainKnownRecipesTried; private Texture2D terrainRampIconTexture; private Texture2D terrainRevertIconTexture; private Sprite terrainRampIcon; private Sprite terrainRevertIcon; private static MethodInfo terrainUpdatePiecesMethod; private static FieldInfo terrainHmapField; private static FieldInfo terrainLevelDeltaField; private static FieldInfo terrainSmoothDeltaField; private static FieldInfo terrainModifiedHeightField; private static FieldInfo terrainPaintMaskField; private static FieldInfo terrainModifiedPaintField; private static FieldInfo terrainNviewField; private static MethodInfo terrainSaveMethod; private static PlacementRadiusScope terrainActiveRadiusScope; private static readonly RaycastHit[] TerrainRaycastBuffer = (RaycastHit[])(object)new RaycastHit[256]; private static readonly HashSet<TerrainComp> TerrainCompilerBuffer = new HashSet<TerrainComp>(); private static readonly object[] TerrainSaveArguments = new object[1] { false }; private static bool terrainFastAccessTried; private static FieldRef<TerrainComp, Heightmap> terrainHmapFastRef; private static FieldRef<TerrainComp, float[]> terrainLevelDeltaFastRef; private static FieldRef<TerrainComp, float[]> terrainSmoothDeltaFastRef; private static FieldRef<TerrainComp, bool[]> terrainModifiedHeightFastRef; private static FieldRef<TerrainComp, Color[]> terrainPaintMaskFastRef; private static FieldRef<TerrainComp, bool[]> terrainModifiedPaintFastRef; private static FieldRef<TerrainComp, ZNetView> terrainNviewFastRef; private static Action<TerrainComp, bool> terrainSaveFast; private float terrainNextPreviewUpdate; private float terrainNextPieceCheck; private bool terrainPieceTextReady; private int terrainPieceTextVersion = -1; private const float CompassSize = 280f; private const float CompassRing = 104f; private const float CompassLabels = 127f; private static Sprite compassRing; private static Sprite compassDot; private static readonly string[] CompassKeys = new string[8] { "wind.n", "wind.ne", "wind.e", "wind.se", "wind.s", "wind.sw", "wind.w", "wind.nw" }; internal const float PanelWidth = 1020f; internal const float PanelHeight = 810f; private const float SidebarLeft = 18f; private const float SidebarWidth = 196f; private const float TabStep = 48f; private const float TabHeight = 44f; private const float ContentLeft = 228f; private const float ContentTop = 118f; private const float ContentBottom = 86f; private const float RowHeight = 48f; private const float ControlMargin = 16f; private const float ControlGap = 8f; private const float ButtonHeight = 34f; private const float SliderWidth = 250f; private const float ValueWidth = 76f; private const float RowWidth = 754f; private static readonly Color TextWhite = Color.white; private static readonly Color TextQuiet = new Color(0.68f, 0.66f, 0.6f); private static readonly Color TextHint = new Color(0.84f, 0.78f, 0.6f); private static readonly Color TextIdle = new Color(0.85f, 0.83f, 0.78f); private static readonly Color StripeLight = new Color(1f, 1f, 1f, 0.035f); private static readonly Color StripeDark = new Color(0f, 0f, 0f, 0.12f); private Transform rowList; private int rowIndex; private const float PixelsPerNotch = 75f; private const float FallbackSensitivity = 1500f; private readonly List<ScrollRect> scrollViews = new List<ScrollRect>(); private static Type scrollModuleType; private static PropertyInfo scrollDeltaPerTick; private const int MostFound = 40; private readonly List<SearchEntry> searchIndex = new List<SearchEntry>(); private readonly List<FoundLine> foundLines = new List<FoundLine>(); private readonly List<SearchEntry> found = new List<SearchEntry>(); private TMP_InputField searchField; private string searchQuery = ""; private Transform foundList; private TMP_Text foundNone; private bool allPagesBuilt; private int buildingPage = -1; private int buildingMode = -1; private string buildingSection = ""; private RectTransform scrollTarget; private Image fadeImage; private Color fadeColour; private float fadeUntil; private const string LogoFile = "WorldControl_logo.png"; private const float LogoTop = 10f; private const float LogoHeight = 76f; private const float LogoMostWidth = 380f; private static Sprite logo; private static bool logoMissing; private bool statusOneLine; private static TMP_FontAsset sansFont; private static TMP_FontAsset serifFont; private static Material sansEdged; private static Material serifEdged; private static TextMeshProUGUI measureText; private const int PageOverview = 0; private const int PageTime = 1; private const int PageWeather = 2; private const int PageWind = 3; private const int PageEvents = 4; private const int PagePresets = 5; private const int PagePlayers = 6; private const int PagePlaces = 7; private const int PageSay = 8; private const int PagePlayerValues = 9; private const int PageTerrain = 10; private const int PageSearch = 11; private const int PageCount = 12; private static readonly string[] TabKeys = new string[11] { "tab.overview", "tab.time", "tab.weather", "tab.wind", "tab.events", "tab.presets", "tab.players", "tab.places", "tab.say", "tab.values", "tab.terrain" }; private const float SearchHeight = 32f; private const float SearchGap = 8f; private const float SearchWidth = 260f; private const float ListTop = 158f; private const float PageHeight = 566f; private GameObject panel; private readonly GameObject[] pages = (GameObject[])(object)new GameObject[12]; private readonly bool[] pageBuilt = new bool[12]; private readonly Button[] tabButtons = (Button[])(object)new Button[12]; private TMP_InputField _message; private TMP_InputField _placeName; private readonly List<TMP_InputField> typingFields = new List<TMP_InputField>(); private static List<string> eventNames; private readonly List<Action> frameRefresh = new List<Action>(); private readonly List<Action>[] pageRefresh = NewPageRefresh(); private List<Action> refresh; private TMP_Text clockText; private TMP_Text worldClockText; private TMP_Text statusText; private Button applyButton; private Button resetButton; private bool uiInputBlocked; private bool controlsDirty; private int preventedCursorLocks; private int recoveredCursorLocks; private int tab; private float nextUiRequest; private float nextUiRefresh; private static readonly Dictionary<string, string> EventTitles = new Dictionary<string, string>(); private static readonly Biome[] SingleBiomes; private static readonly List<PlayerInfo> PlayerBuffer; private static int playersCachedFrame; private static readonly CultureInfo Culture; private bool HasState { get { if (session == null || !session.Synced || (Object)(object)network == (Object)null) { return false; } if (session.Server) { return true; } ZNetPeer serverPeer = network.GetServerPeer(); if (serverPeer != null && serverConnection != null && serverPeer.m_rpc == serverConnection) { return serverConnection.IsConnected(); } return false; } } private bool CanEdit { get { if (HasState) { if (!session.Server) { return session.State.CanEdit; } return true; } return false; } } private static Color Orange => GUIManager.Instance.ValheimOrange; private static Color Beige => GUIManager.Instance.ValheimBeige; private bool Searching => searchQuery.Length > 0; private int Shown { get { if (!Searching) { return tab; } return 11; } } private static TMP_FontAsset Sans { get { if ((Object)(object)sansFont == (Object)null) { sansFont = GUIManager.Instance.TMP_AveriaSansLibre; } if ((Object)(object)sansFont == (Object)null) { sansFont = Cache.GetPrefab<TMP_FontAsset>("Valheim-AveriaSansLibre"); } return sansFont; } } private static TMP_FontAsset Serif { get { if ((Object)(object)serifFont == (Object)null) { serifFont = Cache.GetPrefab<TMP_FontAsset>("Valheim-AveriaSerifLibre"); } if (!((Object)(object)serifFont != (Object)null)) { return Sans; } return serifFont; } } private static bool BlockInput { get { if ((Object)(object)instance != (Object)null) { if (!instance.windowOpen) { return Time.frameCount <= instance.blockThroughFrame; } return true; } return false; } } private static bool OwnsPointer { get { if ((Object)(object)instance != (Object)null && instance.windowOpen) { return Application.isFocused; } return false; } } private static bool CanScaleLocalEitr(Character character) { Plugin plugin = instance; if ((Object)(object)plugin != (Object)null && plugin.playerRulesSynced && (Object)(object)character != (Object)null) { return (object)character == Player.m_localPlayer; } return false; } private static EitrReloadCostState ScaleReloadEitrTemporarily(Player player, ItemData weapon) { EitrReloadCostState result = default(EitrReloadCostState); if (!CanScaleLocalEitr((Character)(object)player) || weapon == null || weapon.m_shared == null || weapon.m_shared.m_attack == null) { return result; } float reloadEitr = instance.playerRules.ReloadEitr; if (reloadEitr == 1f) { return result; } Attack val = (result.Attack = weapon.m_shared.m_attack); result.Value = val.m_reloadEitrDrain; result.Changed = true; val.m_reloadEitrDrain = result.Value * reloadEitr; return result; } private static void RestoreReloadEitr(ref EitrReloadCostState state) { if (state.Changed) { if (state.Attack != null) { state.Attack.m_reloadEitrDrain = state.Value; } state.Changed = false; } } private static EitrRepairCostState ScaleRepairEitrTemporarily(Player player, ItemData tool) { EitrRepairCostState result = default(EitrRepairCostState); if (!CanScaleLocalEitr((Character)(object)player) || tool == null || tool.m_shared == null || tool.m_shared.m_attack == null) { return result; } float primaryEitr = instance.playerRules.PrimaryEitr; if (primaryEitr == 1f) { return result; } Attack val = (result.Attack = tool.m_shared.m_attack); result.Value = val.m_attackEitr; result.Changed = true; val.m_attackEitr = result.Value * primaryEitr; return result; } private static void RestoreRepairEitr(ref EitrRepairCostState state) { if (state.Changed) { if (state.Attack != null) { state.Attack.m_attackEitr = state.Value; } state.Changed = false; } } private static void RestoreEitrAttackContext(ref EitrAttackContextState state) { if (state.Changed) { eitrAttackContextDepth = state.Depth; eitrAttackContextSecondary = state.Secondary; state.Changed = false; } } private static void RestoreRegenTick(Player player, ref RegenTickState state) { if (state.Changed) { if ((Object)(object)player != (Object)null) { player.m_staminaRegen = state.Stamina; player.m_eiterRegen = state.Eitr; } state.Changed = false; } } private void RestoreEnvironment() { if ((Object)(object)controlledEnvironment != (Object)null) { controlledEnvironment.m_debugEnv = savedWeather; controlledEnvironment.m_debugTimeOfDay = savedTimeEnabled; controlledEnvironment.m_debugTime = savedTime; if (savedWindEnabled) { controlledEnvironment.SetDebugWind(savedWindAngle, savedWindStrength); } else { controlledEnvironment.ResetDebugWind(); } } controlledEnvironment = null; ownedTime = false; controlledEnvironmentRevision = -1L; } private void BindModerationConfig() { bannedNames = ((BaseUnityPlugin)this).Config.Bind<string>("Server - Moderation", "Banned names", "", "Written by the World Control server: the names of players it banned, id|name;id|name. The ban itself is in the game's bannedlist.txt."); } private bool ReflectModeration() { if (moderationReflected) { return moderationUsable; } moderationReflected = true; try { adminListField = AccessTools.Field(typeof(ZNet), "m_adminList"); bannedListField = AccessTools.Field(typeof(ZNet), "m_bannedList"); kickMethod = AccessTools.Method(typeof(ZNet), "InternalKick", new Type[1] { typeof(ZNetPeer) }, (Type[])null); banMethod = AccessTools.Method(typeof(ZNet), "InternalBan", new Type[2] { typeof(ZRpc), typeof(string) }, (Type[])null); unbanMethod = AccessTools.Method(typeof(ZNet), "InternalUnban", new Type[2] { typeof(ZRpc), typeof(string) }, (Type[])null); sendAdminListMethod = AccessTools.Method(typeof(ZNet), "SendAdminList", (Type[])null, (Type[])null); Type type = ((adminListField != null) ? adminListField.FieldType : null); listAdd = ((type != null) ? AccessTools.Method(type, "Add", new Type[1] { typeof(string) }, (Type[])null) : null); listRemove = ((type != null) ? AccessTools.Method(type, "Remove", new Type[1] { typeof(string) }, (Type[])null) : null); listGet = ((type != null) ? AccessTools.Method(type, "GetList", (Type[])null, (Type[])null) : null); moderationUsable = adminListField != null && bannedListField != null && kickMethod != null && banMethod != null && unbanMethod != null && listAdd != null && listRemove != null && listGet != null; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Moderation is not available: " + ex.Message)); moderationUsable = false; } if (!moderationUsable) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Moderation is not available: this game version lacks a kick, ban or admin list member it needs."); } return moderationUsable; } private List<string> GameList(FieldInfo field) { object value = field.GetValue(network); if (value == null) { return null; } return listGet.Invoke(value, null) as List<string>; } private void OnModerate(ZRpc rpc, ZPackage package) { ZNetPeer val = ReadyPeer(rpc); if (session == null || !session.Server || val == null || package == null || package.Size() > 256) { return; } ModerationKind moderationKind; long user; uint id; string text; try { moderationKind = (ModerationKind)package.ReadByte(); user = package.ReadLong(); id = package.ReadUInt(); text = package.ReadString(); } catch (Exception) { return; } if (text == null || text.Length > 96 || (moderationEdits.TryGetValue(rpc, out var value) && Time.unscaledTime < value)) { return; } moderationEdits[rpc] = Time.unscaledTime + 0.4f; if (IsAdmin(rpc)) { if (moderationKind != ModerationKind.Query) { Moderate(moderationKind, user, id, text, val); } SendModeration(rpc); } } private void Moderate(ModerationKind kind, long user, uint id, string target, ZNetPeer asker) { if (!ReflectModeration()) { return; } string text = ((asker != null) ? asker.m_playerName : (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "host")); if (kind == ModerationKind.Unban) { if (!string.IsNullOrEmpty(target)) { unbanMethod.Invoke(network, new object[2] { null, target }); ForgetBannedName(target); ((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " unbanned " + target + ".")); BroadcastModeration(); } return; } ZNetPeer val = PeerFor(user, id); if (val == null || val.m_rpc == null || (asker != null && val == asker)) { return; } string hostName = val.m_rpc.GetSocket().GetHostName(); if (string.IsNullOrEmpty(hostName)) { return; } switch (kind) { case ModerationKind.Kick: kickMethod.Invoke(network, new object[1] { val }); ((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " kicked " + val.m_playerName + ".")); break; case ModerationKind.Ban: banMethod.Invoke(network, new object[2] { null, hostName }); RememberBannedName(hostName, val.m_playerName); kickMethod.Invoke(network, new object[1] { val }); ((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " banned " + val.m_playerName + " (" + hostName + ").")); break; case ModerationKind.MakeAdmin: listAdd.Invoke(adminListField.GetValue(network), new object[1] { hostName }); AdminListChanged(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " made " + val.m_playerName + " an admin.")); break; case ModerationKind.RemoveAdmin: { object value = adminListField.GetValue(network); foreach (string item in new List<string>(GameList(adminListField) ?? new List<string>())) { if (SameId(item, hostName)) { listRemove.Invoke(value, new object[1] { item }); } } AdminListChanged(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " removed the admin rights of " + val.m_playerName + ".")); break; } } BroadcastModeration(); } private static bool SameId(string entry, string host) { if (string.IsNullOrEmpty(entry)) { return false; } if (!(entry == host) && !entry.EndsWith("_" + host, StringComparison.Ordinal)) { return host.EndsWith("_" + entry, StringComparison.Ordinal); } return true; } private void AdminListChanged(ZNetPeer peer) { try { sendAdminListMethod?.Invoke(network, null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Cannot send the admin list: " + ex.GetBaseException().Message)); } if (peer != null && peer.m_rpc != null && peer.m_rpc.IsConnected() && participants.Contains(peer.m_rpc)) { SendState(peer.m_rpc); SendModeration(peer.m_rpc); } } private void RememberBannedName(string id, string name) { Dictionary<string, string> dictionary = BannedNames(); dictionary[id] = (name ?? "").Replace("|", " ").Replace(";", " "); SaveBannedNames(dictionary); } private void ForgetBannedName(string id) { Dictionary<string, string> dictionary = BannedNames(); if (dictionary.Remove(id)) { SaveBannedNames(dictionary); } } private Dictionary<string, string> BannedNames() { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); if (bannedNames == null || string.IsNullOrEmpty(bannedNames.Value)) { return dictionary; } string[] array = bannedNames.Value.Split(new char[1] { ';' }); foreach (string text in array) { int num = text.IndexOf('|'); if (num > 0) { dictionary[text.Substring(0, num)] = text.Substring(num + 1); } } return dictionary; } private void SaveBannedNames(Dictionary<string, string> names) { if (bannedNames == null) { return; } List<string> list = new List<string>(); foreach (KeyValuePair<string, string> name in names) { list.Add(name.Key + "|" + name.Value); } bannedNames.Value = string.Join(";", list.ToArray()); } private ZPackage ModerationPackage(ZRpc to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); List<ZNetPeer> peers = network.GetPeers(); List<ZNetPeer> list = new List<ZNetPeer>(); foreach (ZNetPeer item in peers) { if (item != null && item.IsReady() && item.m_rpc != null) { list.Add(item); } } val.Write(list.Count); foreach (ZNetPeer item2 in list) { val.Write(((ZDOID)(ref item2.m_characterID)).UserID); val.Write(((ZDOID)(ref item2.m_characterID)).ID); val.Write(network.IsAdmin(item2.m_rpc.GetSocket().GetHostName())); } List<string> list2 = GameList(bannedListField) ?? new List<string>(); Dictionary<string, string> dictionary = BannedNames(); int num = Mathf.Min(list2.Count, 100); val.Write(num); for (int i = 0; i < num; i++) { string text = list2[i] ?? ""; val.Write(text); val.Write(dictionary.TryGetValue(text, out var value) ? value : ""); } return val; } private void SendModeration(ZRpc rpc) { if (session != null && session.Server && rpc != null && rpc.IsConnected() && ReflectModeration()) { ZPackage val = ModerationPackage(rpc); if (val.Size() <= 4096) { rpc.Invoke("DezzyCode.WorldControl.Moderation.v1", new object[1] { val }); } } } private void BroadcastModeration() { if (session == null || !session.Server) { return; } foreach (ZNetPeer peer in network.GetPeers()) { if (peer != null && peer.IsReady() && peer.m_rpc != null && peer.m_rpc.IsConnected() && participants.Contains(peer.m_rpc) && IsAdmin(peer.m_rpc)) { SendModeration(peer.m_rpc); } } if ((Object)(object)Player.m_localPlayer != (Object)null && ReflectModeration()) { ReadModeration(ModerationPackage(null)); } } private void OnModeration(ZRpc rpc, ZPackage package) { if (session == null || session.Server || package == null || package.Size() > 4096 || (Object)(object)network == (Object)null) { return; } ZNetPeer serverPeer = network.GetServerPeer(); if (serverPeer == null || serverPeer.m_rpc != rpc) { return; } try { ReadModeration(package); } catch (Exception) { } } private void ReadModeration(ZPackage package) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) package.SetPos(0); int num = package.ReadInt(); if (num < 0 || num > 256) { return; } moderationOnline.Clear(); moderationAdmins.Clear(); ZDOID item = default(ZDOID); for (int i = 0; i < num; i++) { ((ZDOID)(ref item))..ctor(package.ReadLong(), package.ReadUInt()); bool num2 = package.ReadBool(); moderationOnline.Add(item); if (num2) { moderationAdmins.Add(item); } } int num3 = package.ReadInt(); if (num3 >= 0 && num3 <= 100) { moderationBanned.Clear(); for (int j = 0; j < num3; j++) { moderationBanned.Add(new BannedPlayer { Id = package.ReadString(), Name = package.ReadString() }); } moderationKnown = true; controlsDirty = true; } } private void QueryModeration() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (session == null || Time.unscaledTime < nextModerationQuery) { return; } nextModerationQuery = Time.unscaledTime + 3f; if (session.Server) { if (ReflectModeration()) { ReadModeration(ModerationPackage(null)); } } else { SendModerate(ModerationKind.Query, ZDOID.None, ""); } } private void SendModerate(ModerationKind kind, ZDOID target, string id) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (!CanEdit) { return; } if (session.Server) { Moderate(kind, ((ZDOID)(ref target)).UserID, ((ZDOID)(ref target)).ID, id, null); return; } ZNetPeer serverPeer = network.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady() && serverPeer.m_rpc != null && serverPeer.m_rpc.IsConnected()) { ZPackage val = new ZPackage(); val.Write((byte)kind); val.Write(((ZDOID)(ref target)).UserID); val.Write(((ZDOID)(ref target)).ID); val.Write(id ?? ""); serverPeer.m_rpc.Invoke("DezzyCode.WorldControl.Moderate.v1", new object[1] { val }); } } private void ResetModeration() { moderationOnline.Clear(); moderationAdmins.Clear(); moderationBanned.Clear(); moderationKnown = false; nextModerationQuery = 0f; moderationEdits.Clear(); } private void BuildOverview(Transform list) { Hint(Words.T("overview.hint")); Section(Words.T("section.server")); OverviewRow("overview.time", 1, delegate { Request settings = session.State.Settings; return (settings.TimeMode != 1) ? Words.T("time.natural") : Words.T("overview.time.held", UiOptions.Clock(settings.Hour / 24f)); }); OverviewRow("overview.weather", 2, () => UiOptions.WeatherName(session.State.Settings.Weather)); OverviewRow("overview.wind", 3, delegate { Request settings = session.State.Settings; return (!settings.WindOn) ? Words.T("wind.natural") : Words.T("presets.wind", CompassName(WindFrom(settings.Angle)), (settings.Strength * 100f).ToString("0")); }); OverviewRow("overview.rain", 2, () => Words.T(session.State.Settings.NoRainDamage ? "switch.off" : "switch.on")); OverviewRow("overview.event", 4, delegate { RandomEvent val = Running(); string text = ((val != null && !string.IsNullOrEmpty(val.m_name)) ? Words.T("events.running", Told(val.m_name) + " " + UiOptions.Countdown(val.m_duration - val.m_time)) : Words.T("events.none")); return (!session.State.Settings.EventsPaused) ? text : (text + " · " + Words.T("overview.events.paused")); }); OverviewRow("overview.players", 6, delegate { //IL_0013: Unknown result type (might be due to invalid IL or missing references) List<PlayerInfo> list2 = Players(); List<string> list3 = new List<string>(); for (int i = 0; i < list2.Count && i < 6; i++) { list3.Add(list2[i].m_name); } string text = string.Join(", ", list3.ToArray()) + ((list2.Count > 6) ? ", …" : ""); return Words.T("players.count", list2.Count.ToString()) + ((list2.Count > 0) ? (" · " + text) : ""); }); OverviewRow("overview.values", 9, () => Words.T((playerRulesSynced && playerVitalsSynced) ? ((playerRules.Equals(PlayerResourceRules.Vanilla) && playerVitals.Equals(PlayerVitalRules.Vanilla)) ? "overview.values.vanilla" : "overview.values.changed") : "values.status.waiting")); TMP_Text titleText; TMP_Text pendingText; RectTransform row = Row(Words.T("overview.pending"), "", Total(new float[1] { 230f }), out titleText, out pendingText); Button apply = RowButtons(row, new float[1] { 230f }, new string[1] { Words.T("btn.apply") }, new Action[1] { delegate { Submit(ActionKind.All); SubmitAllPlayerDrafts(); } })[0]; refresh.Add(delegate { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) string text = PendingChanges(); pendingText.text = (string.IsNullOrEmpty(text) ? Words.T("overview.pending.none") : text); ((Graphic)pendingText).color = (string.IsNullOrEmpty(text) ? TextQuiet : Orange); ((Selectable)apply).interactable = CanAct() && !string.IsNullOrEmpty(text); }); Section(Words.T("section.local")); OverviewRow("overview.terrain", 10, () => Words.T((terrainEnabled != null && terrainEnabled.Value) ? "switch.on" : "switch.off")); OverviewRow("overview.places", 7, delegate { int num = 0; for (int i = 0; i < places.Length; i++) { if (Stored(i, out var _)) { num++; } } return Words.T("overview.places.count", num.ToString(), places.Length.ToString()); }); } private void OverviewRow(string key, int page, Func<string> now) { TMP_Text titleText; TMP_Text text; RectTransform row = Row(Words.T(key), "", 110f, out titleText, out text); RowButtons(row, new float[1] { 110f }, new string[1] { Words.T("overview.go") }, new Action[1] { delegate { EndSearch(); tab = page; } }); refresh.Add(delegate { text.text = now(); }); } private string PendingChanges() { Request settings = session.State.Settings; List<string> list = new List<string>(); if (draft.TimeMode != settings.TimeMode || (draft.TimeMode != 0 && !Mathf.Approximately(draft.Hour, settings.Hour))) { list.Add(Words.T("tab.time")); } if ((draft.Weather ?? "") != (settings.Weather ?? "") || draft.NoRainDamage != settings.NoRainDamage) { list.Add(Words.T("tab.weather")); } if (draft.WindOn != settings.WindOn || (draft.WindOn && (!Mathf.Approximately(draft.Angle, settings.Angle) || !Mathf.Approximately(draft.Strength, settings.Strength)))) { list.Add(Words.T("tab.wind")); } if (draft.EventsPaused != settings.EventsPaused) { list.Add(Words.T("tab.events")); } if (playerRulesDraftDirty || playerVitalsDraftDirty) { list.Add(Words.T("tab.values")); } if (list.Count != 0) { return Words.T("overview.pending.some", string.Join(", ", list.ToArray())); } return ""; } private static bool InRange(float value, float min, float max) { if (!float.IsNaN(value) && !float.IsInfinity(value) && value >= min) { return value <= max; } return false; } private static bool BuffOnlyPlayerRules(PlayerResourceRules r) { if (!InRange(r.Run, 0f, 1f) || !InRange(r.Jump, 0f, 1f) || !InRange(r.Dodge, 0f, 1f) || !InRange(r.Swim, 0f, 1f) || !InRange(r.Sneak, 0f, 1f) || !InRange(r.Encumbered, 0f, 1f) || !InRange(r.Block, 0f, 1f) || !InRange(r.Grapple, 0f, 1f) || !InRange(r.PrimaryStamina, 0f, 1f) || !InRange(r.SecondaryStamina, 0f, 1f) || !InRange(r.DrawStamina, 0f, 1f) || !InRange(r.ReloadStamina, 0f, 1f) || !InRange(r.HomeStamina, 0f, 1f) || !InRange(r.PrimaryEitr, 0f, 1f) || !InRange(r.SecondaryEitr, 0f, 1f) || !InRange(r.DrawEitr, 0f, 1f) || !InRange(r.ReloadEitr, 0f, 1f)) { return false; } if (!InRange(r.PrimaryAdrenaline, 1f, 5f) || !InRange(r.SecondaryAdrenaline, 1f, 5f) || !InRange(r.ProjectileAdrenaline, 1f, 5f) || !InRange(r.BlockAdrenaline, 1f, 5f) || !InRange(r.ParryAdrenaline, 1f, 5f) || !InRange(r.PerfectDodgeAdrenaline, 1f, 5f) || !InRange(r.StaggerAdrenaline, 1f, 5f) || !InRange(r.GuardianAdrenaline, 1f, 5f)) { return false; } if (InRange(r.MissAdrenaline, 0f, 1f)) { return InRange(r.DamageAdrenaline, 0f, 1f); } return false; } private void ShowPlayerResetConfirmation() { Confirm("values.confirm.title", "values.confirm.question", "values.confirm.yes", ResetAllPlayerDrafts); } private void ShowWorldResetConfirmation() { Confirm("reset.confirm.title", "reset.confirm.question", "reset.confirm.yes", delegate { Submit(ActionKind.Reset); }); } private void Confirm(string titleKey, string questionKey, string yesKey, Action yes) { ConfirmText(Words.T(titleKey), Words.T(questionKey), Words.T(yesKey), yes); } private void ConfirmText(string title, string question, string yesText, Action yes) { if (!((Object)(object)panel == (Object)null)) { if ((Object)(object)confirmOverlay == (Object)null) { BuildConfirmation(); BetrValheim.Dress(confirmOverlay); } confirmTitle.text = title; confirmQuestion.text = question; if ((Object)(object)confirmYesText != (Object)null) { confirmYesText.text = yesText; } confirmed = yes; confirmOverlay.transform.SetAsLastSibling(); confirmOverlay.SetActive(true); } } private void BuildConfirmation() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Confirmation", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(panel.transform, false); val.layer = 5; Place(val, 0f, 0f, 0f, 810f); Image component = val.GetComponent<Image>(); ((Graphic)component).color = new Color(0f, 0f, 0f, 0.58f); ((Graphic)component).raycastTarget = true; GameObject val2 = GUIManager.Instance.CreateWoodpanel(val.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 560f, 240f, false); ((Object)val2).name = "ConfirmationBox"; confirmTitle = Txt("", val2.transform, 22, bold: true, Orange); Place(((Component)confirmTitle).gameObject, 28f, 28f, 22f, 56f); confirmQuestion = Txt("", val2.transform, 15, bold: false, TextWhite); confirmQuestion.alignment = (TextAlignmentOptions)257; Place(((Component)confirmQuestion).gameObject, 28f, 28f, 64f, 168f); float num = 244f; Button val3 = NewButton(val2.transform, "", num, 40f, delegate { Action action = confirmed; HideConfirmation(); action?.Invoke(); }); Place(((Component)val3).gameObject, 28f, 532f - num, 178f, 218f); confirmYesText = ((Component)val3).GetComponentInChildren<TMP_Text>(); Place(((Component)NewButton(val2.transform, Words.T("values.confirm.cancel"), num, 40f, HideConfirmation)).gameObject, 532f - num, 28f, 178f, 218f); confirmOverlay = val; val.SetActive(false); } private void HideConfirmation() { confirmed = null; if ((Object)(object)confirmOverlay != (Object)null) { confirmOverlay.SetActive(false); } } private void EnsurePlayerRulesConfig() { if (!playerRulesConfigReady) { playerRulesConfigReady = true; playerRulesStored = ((BaseUnityPlugin)this).Config.Bind<string>("Server - Player Rules", "State", "", "Written by the World Control server. Server-authoritative stamina, eitr and adrenaline multipliers."); } } private static bool PlayerRule(float value) { if (!float.IsNaN(value) && !float.IsInfinity(value) && value >= 0f) { return value <= 3f; } return false; } private static bool ValidPlayerRules(PlayerResourceRules r) { if (PlayerRule(r.Run) && PlayerRule(r.Jump) && PlayerRule(r.Dodge) && PlayerRule(r.Swim) && PlayerRule(r.Sneak) && PlayerRule(r.Encumbered) && PlayerRule(r.Block) && PlayerRule(r.Grapple) && PlayerRule(r.PrimaryStamina) && PlayerRule(r.SecondaryStamina) && PlayerRule(r.DrawStamina) && PlayerRule(r.ReloadStamina) && PlayerRule(r.HomeStamina) && PlayerRule(r.PrimaryEitr) && PlayerRule(r.SecondaryEitr) && PlayerRule(r.DrawEitr) && PlayerRule(r.ReloadEitr) && PlayerRule(r.PrimaryAdrenaline) && PlayerRule(r.SecondaryAdrenaline) && PlayerRule(r.ProjectileAdrenaline) && PlayerRule(r.BlockAdrenaline) && PlayerRule(r.ParryAdrenaline) && PlayerRule(r.PerfectDodgeAdrenaline) && PlayerRule(r.StaggerAdrenaline) && PlayerRule(r.MissAdrenaline) && PlayerRule(r.DamageAdrenaline)) { return PlayerRule(r.GuardianAdrenaline); } return false; } private static void WritePlayerRules(BinaryWriter w, PlayerResourceRules r) { w.Write(r.Run); w.Write(r.Jump); w.Write(r.Dodge); w.Write(r.Swim); w.Write(r.Sneak); w.Write(r.Encumbered); w.Write(r.Block); w.Write(r.Grapple); w.Write(r.PrimaryStamina); w.Write(r.SecondaryStamina); w.Write(r.DrawStamina); w.Write(r.ReloadStamina); w.Write(r.HomeStamina); w.Write(r.PrimaryEitr); w.Write(r.SecondaryEitr); w.Write(r.DrawEitr); w.Write(r.ReloadEitr); w.Write(r.PrimaryAdrenaline); w.Write(r.SecondaryAdrenaline); w.Write(r.ProjectileAdrenaline); w.Write(r.BlockAdrenaline); w.Write(r.ParryAdrenaline); w.Write(r.PerfectDodgeAdrenaline); w.Write(r.StaggerAdrenaline); w.Write(r.MissAdrenaline); w.Write(r.DamageAdrenaline); w.Write(r.GuardianAdrenaline); } private static PlayerResourceRules ReadPlayerRules(BinaryReader r) { return new PlayerResourceRules { Run = r.ReadSingle(), Jump = r.ReadSingle(), Dodge = r.ReadSingle(), Swim = r.ReadSingle(), Sneak = r.ReadSingle(), Encumbered = r.ReadSingle(), Block = r.ReadSingle(), Grapple = r.ReadSingle(), PrimaryStamina = r.ReadSingle(), SecondaryStamina = r.ReadSingle(), DrawStamina = r.ReadSingle(), ReloadStamina = r.ReadSingle(), HomeStamina = r.ReadSingle(), PrimaryEitr = r.ReadSingle(), SecondaryEitr = r.ReadSingle(), DrawEitr = r.ReadSingle(), ReloadEitr = r.ReadSingle(), PrimaryAdrenaline = r.ReadSingle(), SecondaryAdrenaline = r.ReadSingle(), ProjectileAdrenaline = r.ReadSingle(), BlockAdrenaline = r.ReadSingle(), ParryAdrenaline = r.ReadSingle(), PerfectDodgeAdrenaline = r.ReadSingle(), StaggerAdrenaline = r.ReadSingle(), MissAdrenaline = r.ReadSingle(), DamageAdrenaline = r.ReadSingle(), GuardianAdrenaline = r.ReadSingle() }; } private static byte[] EncodePlayerRulesRequest(bool apply, PlayerResourceRules rules) { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(1); binaryWriter.Write(apply ? ((byte)1) : ((byte)0)); if (apply) { WritePlayerRules(binaryWriter, rules); } return memoryStream.ToArray(); } private static bool DecodePlayerRulesRequest(byte[] bytes, out bool apply, out PlayerResourceRules rules) { apply = false; rules = PlayerResourceRules.Vanilla; if (bytes == null || bytes.Length > 256) { return false; } try { using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes)); if (binaryReader.ReadInt32() != 1) { return false; } byte b = binaryReader.ReadByte(); if (b > 1) { return false; } apply = b == 1; if (apply) { rules = ReadPlayerRules(binaryReader); } return binaryReader.BaseStream.Position == binaryReader.BaseStream.Length && (!apply || ValidPlayerRules(rules)); } catch (Exception ex) when (ex is IOException || ex is EndOfStreamException || ex is ArgumentException) { return false; } } private static byte[] EncodePlayerRulesState(long revision, PlayerResourceRules rules) { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(1); binaryWriter.Write(revision); WritePlayerRules(binaryWriter, rules); return memoryStream.ToArray(); } private static bool DecodePlayerRulesState(byte[] bytes, out long revision, out PlayerResourceRules rules) { revision = 0L; rules = PlayerResourceRules.Vanilla; if (bytes == null || bytes.Length > 256) { return false; } try { using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes)); if (binaryReader.ReadInt32() != 1) { return false; } revision = binaryReader.ReadInt64(); rules = ReadPlayerRules(binaryReader); return binaryReader.BaseStream.Position == binaryReader.BaseStream.Length && revision >= 0 && ValidPlayerRules(rules); } catch (Exception ex) when (ex is IOException || ex is EndOfStreamException || ex is ArgumentException) { return false; } } private void LoadPlayerRules() { EnsurePlayerRulesConfig(); playerRules = PlayerResourceRules.Vanilla; playerRulesRevision = 1L; string text = ((playerRulesStored != null) ? playerRulesStored.Value : ""); if (string.IsNullOrEmpty(text)) { return; } try { if (DecodePlayerRulesState(Convert.FromBase64String(text), out var revision, out var rules)) { playerRules = rules; playerRulesRevision = Math.Max(1L, revision); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not read stored player rules: " + ex.Message)); } } private void SavePlayerRules() { EnsurePlayerRulesConfig(); if (playerRulesStored != null) { playerRulesStored.Value = Convert.ToBase64String(EncodePlayerRulesState(playerRulesRevision, playerRules)); } } private void ResetPlayerRulesNetwork() { foreach (ZRpc item in playerRulesRegistered) { try { item.Unregister("DezzyCode.WorldControl.PlayerRules.Request.v1"); item.Unregister("DezzyCode.WorldControl.PlayerRules.State.v1"); } catch { } } playerRulesRegistered.Clear(); playerRulesRequests.Clear(); playerRulesEdits.Clear(); playerRulesNetwork = network; playerRulesLoadedForServer = false; nextPlayerRulesQuery = 0f; playerRulesSynced = session != null && session.Server; playerRulesRevision = 0L; if (session == null || !session.Server) { playerRules = PlayerResourceRules.Vanilla; } playerRulesDraft = playerRules; playerRulesDraftDirty = false; RestorePlayerRuleTuning(); } private void PlayerRulesTick() { //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown EnsurePlayerRulesConfig(); if (playerRulesNetwork != network) { ResetPlayerRulesNetwork(); } if ((Object)(object)network == (Object)null || session == null) { return; } if (session.Server && !playerRulesLoadedForServer) { playerRulesLoadedForServer = true; LoadPlayerRules(); playerRulesSynced = true; playerRulesDraft = playerRules; } foreach (ZNetPeer peer in network.GetPeers()) { if (peer != null && peer.m_rpc != null && playerRulesRegistered.Add(peer.m_rpc)) { peer.m_rpc.Register<ZPackage>("DezzyCode.WorldControl.PlayerRules.Request.v1", (Action<ZRpc, ZPackage>)OnPlayerRulesRequest); peer.m_rpc.Register<ZPackage>("DezzyCode.WorldControl.PlayerRules.State.v1", (Action<ZRpc, ZPackage>)OnPlayerRulesState); if (session.Server && peer.IsReady() && peer.m_rpc.IsConnected()) { SendPlayerRulesState(peer.m_rpc); } } } playerRulesStale.Clear(); foreach (ZRpc item in playerRulesRegistered) { if (item == null || !item.IsConnected()) { playerRulesStale.Add(item); } } foreach (ZRpc item2 in playerRulesStale) { playerRulesRegistered.Remove(item2); playerRulesRequests.Remove(item2); playerRulesEdits.Remove(item2); try { item2.Unregister("DezzyCode.WorldControl.PlayerRules.Request.v1"); item2.Unregister("DezzyCode.WorldControl.PlayerRules.State.v1"); } catch { } } if (!session.Server && !playerRulesSynced && Time.unscaledTime >= nextPlayerRulesQuery) { ZNetPeer serverPeer = network.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady() && serverPeer.m_rpc != null && serverPeer.m_rpc.IsConnected()) { nextPlayerRulesQuery = Time.unscaledTime + 1f; serverPeer.m_rpc.Invoke("DezzyCode.WorldControl.PlayerRules.Request.v1", new object[1] { (object)new ZPackage(EncodePlayerRulesRequest(apply: false, PlayerResourceRules.Vanilla)) }); } } if (playerRulesSynced) { ApplyPlayerRuleTuning(); } } private void OnPlayerRulesRequest(ZRpc rpc, ZPackage package) { ZNetPeer val = ReadyPeer(rpc); if (session == null || !session.Server || rpc == null || val == null || package == null || package.Size() > 256 || !DecodePlayerRulesRequest(package.GetArray(), out var apply, out var rules)) { return; } Dictionary<ZRpc, float> dictionary = (apply ? playerRulesEdits : playerRulesRequests); if (!dictionary.TryGetValue(rpc, out var value) || !(Time.unscaledTime < value)) { dictionary[rpc] = Time.unscaledTime + (apply ? 0.35f : 0.75f); if (apply && IsAdmin(rpc)) { playerRules = rules; playerRulesRevision = Math.Max(1L, playerRulesRevision + 1); SavePlayerRules(); playerRulesDraft = playerRules; playerRulesDraftDirty = false; BroadcastPlayerRules(); controlsDirty = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Player resource rules changed by admin " + val.m_playerName + ".")); } else { SendPlayerRulesState(rpc); } } } private void OnPlayerRulesState(ZRpc rpc, ZPackage package) { if (session != null && !session.Server && rpc != null && package != null && package.Size() <= 256 && serverConnection != null && rpc == serverConnection && DecodePlayerRulesState(package.GetArray(), out var revision, out var rules) && (!playerRulesSynced || revision >= playerRulesRevision)) { playerRulesRevision = revision; playerRules = rules; playerRulesSynced = true; if (!playerRulesDraftDirty) { playerRulesDraft = rules; } controlsDirty = true; } } private void SendPlayerRulesState(ZRpc rpc) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (rpc != null && rpc.IsConnected()) { rpc.Invoke("DezzyCode.WorldControl.PlayerRules.State.v1", new object[1] { (object)new ZPackage(EncodePlayerRulesState(playerRulesRevision, playerRules)) }); } } private void BroadcastPlayerRules() { foreach (ZNetPeer peer in network.GetPeers()) { if (peer != null && peer.IsReady() && peer.m_rpc != null && peer.m_rpc.IsConnected() && playerRulesRegistered.Contains(peer.m_rpc)) { SendPlayerRulesState(peer.m_rpc); } } ApplyPlayerRuleTuning(); } private void SubmitPlayerRules() { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown if (!CanEdit || !ValidPlayerRules(playerRulesDraft)) { return; } if (session != null && session.Server) { playerRules = playerRulesDraft; playerRulesRevision = Math.Max(1L, playerRulesRevision + 1); playerRulesSynced = true; playerRulesDraftDirty = false; SavePlayerRules(); BroadcastPlayerRules(); controlsDirty = true; } else { ZNetPeer val = (((Object)(object)network != (Object)null) ? network.GetServerPeer() : null); if (val != null && val.IsReady() && val.m_rpc != null && val.m_rpc.IsConnected()) { val.m_rpc.Invoke("DezzyCode.WorldControl.PlayerRules.Request.v1", new object[1] { (object)new ZPackage(EncodePlayerRulesRequest(apply: true, playerRulesDraft)) }); } } } private static FieldInfo PlayerRuleField(string name) { Type type = typeof(Player); while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(float)) { return field; } type = type.BaseType; } return null; } private void ApplyPlayerFloat(Player player, string fieldName, float multiplier) { FieldInfo fieldInfo = PlayerRuleField(fieldName); if (fieldInfo == null || (Object)(object)player == (Object)null) { return; } if (!playerFieldBaselines.TryGetValue(fieldName, out var value)) { try { value = (float)fieldInfo.GetValue(player); playerFieldBaselines[fieldName] = value; } catch { return; } } try { fieldInfo.SetValue(player, value * multiplier); } catch { } } private void ApplyPlayerRuleTuning() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { bool flag = playerRulesAppliedPlayer != localPlayer; bool flag2 = playerRulesObjectDb != ObjectDB.instance; if (flag) { RestorePlayerFields(); playerRulesAppliedPlayer = localPlayer; playerFieldBaselines.Clear(); playerRulesAppliedRevision = -1L; } if (flag2) { RestoreItemRules(); playerRulesObjectDb = ObjectDB.instance; attackBaselines.Clear(); projectileBaselines.Clear(); shieldBaselines.Clear(); playerRulesAppliedRevision = -1L; } if (playerRulesAppliedRevision != playerRulesRevision || flag || flag2) { ApplyPlayerFloat(localPlayer, "m_runStaminaDrain", playerRules.Run); ApplyPlayerFloat(localPlayer, "m_jumpStaminaUsage", playerRules.Jump); ApplyPlayerFloat(localPlayer, "m_dodgeStaminaUsage", playerRules.Dodge); ApplyPlayerFloat(localPlayer, "m_swimStaminaDrainMinSkill", playerRules.Swim); ApplyPlayerFloat(localPlayer, "m_swimStaminaDrainMaxSkill", playerRules.Swim); ApplyPlayerFloat(localPlayer, "m_sneakStaminaDrain", playerRules.Sneak); ApplyPlayerFloat(localPlayer, "m_encumberedStaminaDrain", playerRules.Encumbered); ApplyPlayerFloat(localPlayer, "m_grapplingStaminaDrain", playerRules.Grapple); ApplyPlayerFloat(localPlayer, "m_perfectDodgeAdrenaline", playerRules.PerfectDodgeAdrenaline); ApplyPlayerFloat(localPlayer, "m_staggerEnemyAdrenaline", playerRules.StaggerAdrenaline); ApplyPlayerFloat(localPlayer, "m_attackMissAdrenaline", playerRules.MissAdrenaline); ApplyPlayerFloat(localPlayer, "m_nonBlockDamageAdrenaline", playerRules.DamageAdrenaline); ApplyPlayerFloat(localPlayer, "m_adrenalineGuardianPower", playerRules.GuardianAdrenaline); TuneItemRules(); playerRulesAppliedRevision = playerRulesRevision; } } } private void TuneItemRules() { ObjectDB val = ObjectDB.instance; if ((Object)(object)val == (Object)null || val.m_items == null) { return; } foreach (GameObject item in val.m_items) { if (!((Object)(object)item == (Object)null)) { ItemDrop component = item.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null) { SharedData shared = component.m_itemData.m_shared; TuneAttack(shared.m_attack, primary: true); TuneAttack(shared.m_secondaryAttack, primary: false); TuneShield(shared); } } } } private void TuneAttack(Attack attack, bool primary) { if (attack == null) { return; } if (!attackBaselines.TryGetValue(attack, out var value)) { value = new AttackBaseline { AttackAdrenaline = attack.m_attackAdrenaline }; attackBaselines[attack] = value; } float num = (primary ? playerRules.PrimaryAdrenaline : playerRules.SecondaryAdrenaline); attack.m_attackAdrenaline = value.AttackAdrenaline * num; if (!((Object)(object)attack.m_attackProjectile != (Object)null)) { return; } Projectile component = attack.m_attackProjectile.GetComponent<Projectile>(); if ((Object)(object)component != (Object)null) { if (!projectileBaselines.TryGetValue(component, out var value2)) { value2 = component.m_adrenaline; projectileBaselines[component] = value2; } component.m_adrenaline = value2 * playerRules.ProjectileAdrenaline; } } private void TuneShield(SharedData shared) { if (shared != null) { if (!shieldBaselines.TryGetValue(shared, out var value)) { value = new ShieldBaseline { Block = shared.m_blockAdrenaline, Parry = shared.m_perfectBlockAdrenaline }; shieldBaselines[shared] = value; } shared.m_blockAdrenaline = value.Block * playerRules.BlockAdrenaline; shared.m_perfectBlockAdrenaline = value.Parry * playerRules.ParryAdrenaline; } } private void RestorePlayerFields() { Player val = playerRulesAppliedPlayer; if ((Object)(object)val == (Object)null) { return; } foreach (KeyValuePair<string, float> playerFieldBaseline in playerFieldBaselines) { FieldInfo fieldInfo = PlayerRuleField(playerFieldBaseline.Key); if (!(fieldInfo == null)) { try { fieldInfo.SetValue(val, playerFieldBaseline.Value); } catch { } } } } private void RestoreItemRules() { foreach (KeyValuePair<Attack, AttackBaseline> attackBaseline in attackBaselines) { Attack key = attackBaseline.Key; AttackBaseline value = attackBaseline.Value; if (key != null && value != null) { key.m_attackAdrenaline = value.AttackAdrenaline; } } foreach (KeyValuePair<Projectile, float> projectileBaseline in projectileBaselines) { if ((Object)(object)projectileBaseline.Key != (Object)null) { projectileBaseline.Key.m_adrenaline = projectileBaseline.Value; } } foreach (KeyValuePair<SharedData, ShieldBaseline> shieldBaseline in shieldBaselines) { if (shieldBaseline.Key != null && shieldBaseline.Value != null) { shieldBaseline.Key.m_blockAdrenaline = shieldBaseline.Value.Block; shieldBaseline.Key.m_perfectBlockAdrenaline = shieldBaseline.Value.Parry; } } } private void RestorePlayerRuleTuning() { RestorePlayerFields(); RestoreItemRules(); playerRulesAppliedPlayer = null; playerFieldBaselines.Clear(); playerRulesObjectDb = null; attackBaselines.Clear(); projectileBaselines.Clear(); shieldBaselines.Clear(); playerRulesAppliedRevision = -1L; } private void BuildPlayers(Transform list) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown TMP_Text header = Hint(""); playerList = list; oldServer = ((Component)Hint(Words.T("moderation.old")).transform.parent).gameObject; Section(Words.T("players.online")); onlineHeading = (RectTransform)list.GetChild(list.childCount - 1); Section(Words.T("players.banned")); bannedHeading = (RectTransform)list.GetChild(list.childCount - 1); noneBanned = ((Component)Hint(Words.T("players.banned.none")).transform.parent).gameObject; refresh.Add(delegate { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) QueryModeration(); List<PlayerInfo> list2 = Players(); header.text = Words.T("players.count", list2.Count.ToString()) + " · " + Words.T("players.note"); bool flag = moderationKnown; if (oldServer.activeSelf == flag) { oldServer.SetActive(!flag); } while (playerLines.Count < list2.Count) { playerLines.Add(NewPlayerLine()); } for (int i = 0; i < playerLines.Count; i++) { PlayerLine playerLine = playerLines[i]; bool flag2 = i < list2.Count; if (playerLine.Row.activeSelf != flag2) { playerLine.Row.SetActive(flag2); } if (flag2) { PlayerInfo val = list2[i]; bool flag3 = Yourself(val); bool flag4 = moderationAdmins.Contains(val.m_characterID); playerLine.Name.text = (flag3 ? (val.m_name + " " + Words.T("players.you")) : val.m_name) + (flag4 ? (" · " + Words.T("players.admin")) : ""); ((Graphic)playerLine.Name).color = (flag4 ? Orange : TextWhite); playerLine.Where.text = Distance(val, flag3); bool flag5 = !flag3 && CanAct(); ((Selectable)playerLine.Bring).interactable = flag5; ((Selectable)playerLine.Visit).interactable = flag5; bool interactable = flag5 && flag && moderationOnline.Contains(val.m_characterID); ((Selectable)playerLine.Kick).interactable = interactable; ((Selectable)playerLine.Ban).interactable = interactable; ((Selectable)playerLine.Admin).interactable = interactable; if ((Object)(object)playerLine.AdminText != (Object)null) { playerLine.AdminText.text = Words.T(flag4 ? "players.admin.remove" : "players.admin.make"); ((Graphic)playerLine.AdminText).color = (flag4 ? Orange : Beige); } } } int num = (flag ? moderationBanned.Count : 0); if (noneBanned.activeSelf != (flag && num == 0)) { noneBanned.SetActive(flag && num == 0); } while (bannedLines.Count < num) { bannedLines.Add(NewBannedLine()); } for (int j = 0; j < bannedLines.Count; j++) { BannedLine bannedLine = bannedLines[j]; bool flag6 = j < num; if (bannedLine.Row.activeSelf != flag6) { bannedLine.Row.SetActive(flag6); } if (flag6) { BannedPlayer bannedPlayer = moderationBanned[j]; bannedLine.Name.text = (string.IsNullOrEmpty(bannedPlayer.Name) ? bannedPlayer.Id : bannedPlayer.Name); bannedLine.Id.text = (string.IsNullOrEmpty(bannedPlayer.Name) ? "" : bannedPlayer.Id); ((Selectable)bannedLine.Unban).interactable = CanAct(); } } }); } private PlayerLine NewPlayerLine() { Transform val = rowList; int num = rowIndex; int index = playerLines.Count; rowList = playerList; rowIndex = index; float[] widths = new float[5] { 84f, 64f, 78f, 78f, 128f }; PlayerLine playerLine = new PlayerLine(); RectTransform val2 = Row("", "", Total(widths), out playerLine.Name, out playerLine.Where); Button[] array = RowButtons(val2, widths, new string[5] { Words.T("players.bring"), Words.T("players.goto"), Words.T("players.kick"), Words.T("players.ban"), "" }, new Action[5] { delegate { Fetch(index, ActionKind.Bring); }, delegate { Fetch(index, ActionKind.Goto); }, delegate { AskModeration(index, ModerationKind.Kick); }, delegate { AskModeration(index, ModerationKind.Ban); }, delegate { AskModeration(index, ModerationKind.MakeAdmin); } }); playerLine.Row = ((Component)val2).gameObject; playerLine.Bring = array[0]; playerLine.Visit = array[1]; playerLine.Kick = array[2]; playerLine.Ban = array[3]; playerLine.Admin = array[4]; playerLine.AdminText = ((Component)playerLine.Admin).GetComponentInChildren<TMP_Text>(); ((Transform)val2).SetSiblingIndex(((Transform)onlineHeading).GetSiblingIndex() + 1 + index); rowList = val; rowIndex = num; BetrValheim.Dress(((Component)val2).gameObject); return playerLine; } private BannedLine NewBannedLine() { Transform val = rowList; int num = rowIndex; int index = bannedLines.Count; rowList = playerList; rowIndex = index; BannedLine bannedLine = new BannedLine(); RectTransform val2 = Row("", "", 120f, out bannedLine.Name, out bannedLine.Id); bannedLine.Unban = RowButtons(val2, new float[1] { 120f }, new string[1] { Words.T("players.unban") }, new Action[1] { delegate { AskUnban(index); } })[0]; bannedLine.Row = ((Component)val2).gameObject; ((Transform)val2).SetSiblingIndex(((Transform)bannedHeading).GetSiblingIndex() + 1 + index); rowList = val; rowIndex = num; BetrValheim.Dress(((Component)val2).gameObject); return bannedLine; } private void AskModeration(int index, ModerationKind kind) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result