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 ValheimSeasons v1.3.0
ValheimSeasons.dll
Decompiled 12 hours 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.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.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 ValheimSeasons { internal static class Compat { private static MethodInfo _getCurrentDay; private static MethodInfo _getEnv; private static MethodInfo _getServerPeerId; private static bool _init; private static void Init() { if (!_init) { _init = true; _getCurrentDay = AccessTools.Method(typeof(EnvMan), "GetCurrentDay", Type.EmptyTypes, (Type[])null); _getEnv = AccessTools.Method(typeof(EnvMan), "GetEnv", new Type[1] { typeof(string) }, (Type[])null); _getServerPeerId = AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", Type.EmptyTypes, (Type[])null); } } internal static int CurrentDay() { Init(); EnvMan instance = EnvMan.instance; if ((Object)(object)instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return 0; } try { if (_getCurrentDay != null) { return (int)_getCurrentDay.Invoke(instance, null); } } catch { } double num = Math.Max(1.0, instance.m_dayLengthSec); return (int)(ZNet.instance.GetTimeSeconds() / num); } internal static EnvSetup GetEnv(string name) { Init(); EnvMan instance = EnvMan.instance; if ((Object)(object)instance == (Object)null) { return null; } try { if (_getEnv != null) { object? obj = _getEnv.Invoke(instance, new object[1] { name }); return (EnvSetup)((obj is EnvSetup) ? obj : null); } } catch { } if (AccessTools.Field(typeof(EnvMan), "m_environments")?.GetValue(instance) is List<EnvSetup> list) { foreach (EnvSetup item in list) { if (item != null && item.m_name == name) { return item; } } } return null; } internal static void ForceWeatherReroll() { EnvMan instance = EnvMan.instance; if ((Object)(object)instance == (Object)null) { return; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(EnvMan), "m_environmentPeriod"); if (!(fieldInfo == null)) { fieldInfo.SetValue(instance, Convert.ChangeType(-1, fieldInfo.FieldType)); } } catch { } } internal static long ServerPeerId() { Init(); try { if (_getServerPeerId != null && ZRoutedRpc.instance != null) { return (long)_getServerPeerId.Invoke(ZRoutedRpc.instance, null); } } catch { } ZNet instance = ZNet.instance; return ((instance != null) ? instance.GetServerPeer() : null)?.m_uid ?? ZDOMan.GetSessionID(); } } internal class CreatureRule { public string Key; public float Dmg = 1f; public float Spd = 1f; public float Hp = 1f; public float Spawn = 1f; public bool DayOnly; } internal static class CreatureSeasons { private class Speeds { public float[] Values; } private static string _src; private static List<CreatureRule> _rules = new List<CreatureRule>(); private static readonly Dictionary<string, CreatureRule> _byName = new Dictionary<string, CreatureRule>(); private static readonly Dictionary<int, string> _prefabOf = new Dictionary<int, string>(); private static readonly ConditionalWeakTable<Character, Speeds> _orig = new ConditionalWeakTable<Character, Speeds>(); private static readonly HashSet<Character> _touched = new HashSet<Character>(); private static FieldInfo[] _speedFields; private static float _timer; private static FieldInfo[] SpeedFields { get { if (_speedFields != null) { return _speedFields; } List<FieldInfo> list = new List<FieldInfo>(); string[] array = new string[7] { "m_speed", "m_walkSpeed", "m_runSpeed", "m_crouchSpeed", "m_swimSpeed", "m_flySlowSpeed", "m_flyFastSpeed" }; foreach (string text in array) { FieldInfo fieldInfo = AccessTools.Field(typeof(Character), text); if (fieldInfo != null && fieldInfo.FieldType == typeof(float)) { list.Add(fieldInfo); } } return _speedFields = list.ToArray(); } } internal static string Source(Season s) { SeasonMechanics r = Mech.R; return s switch { Season.Spring => r.CreatureSpring, Season.Summer => r.CreatureSummer, Season.Fall => r.CreatureFall, _ => r.CreatureWinter, }; } internal static List<CreatureRule> Rules() { string text = ((Mech.On && Mech.R.CreatureSeasons) ? (Source(Mech.S) ?? "") : ""); if (text == _src) { return _rules; } _src = text; _rules = Parse(text); _byName.Clear(); return _rules; } internal static List<CreatureRule> Parse(string src) { List<CreatureRule> list = new List<CreatureRule>(); string[] array = (src ?? "").Split(','); foreach (string text in array) { int num = text.IndexOf(':'); if (num <= 0) { continue; } CreatureRule creatureRule = new CreatureRule { Key = text.Substring(0, num).Trim().ToLowerInvariant() }; if (creatureRule.Key.Length == 0) { continue; } string[] array2 = text.Substring(num + 1).Split(new char[3] { ' ', ';', '|' }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < array2.Length; j++) { string text2 = array2[j].Trim().ToLowerInvariant(); float v; if (text2 == "dia" || text2 == "day") { creatureRule.DayOnly = true; } else if (Tok(text2, "dano", out v) || Tok(text2, "dmg", out v)) { creatureRule.Dmg = Mathf.Clamp(v, 0.1f, 10f); } else if (Tok(text2, "vel", out v) || Tok(text2, "spd", out v)) { creatureRule.Spd = Mathf.Clamp(v, 0.1f, 5f); } else if (Tok(text2, "vida", out v) || Tok(text2, "hp", out v)) { creatureRule.Hp = Mathf.Clamp(v, 0.1f, 10f); } else if (Tok(text2, "spawn", out v)) { creatureRule.Spawn = Mathf.Clamp(v, 0f, 20f); } } list.Add(creatureRule); } return list; } private static bool Tok(string t, string prefix, out float v) { v = 0f; if (!t.StartsWith(prefix)) { return false; } return float.TryParse(t.Substring(prefix.Length).TrimStart('=', 'x', ':'), NumberStyles.Float, CultureInfo.InvariantCulture, out v); } internal static CreatureRule Find(string prefab) { List<CreatureRule> list = Rules(); if (list.Count == 0 || string.IsNullOrEmpty(prefab)) { return null; } string text = prefab.ToLowerInvariant(); if (_byName.TryGetValue(text, out var value)) { return value; } CreatureRule creatureRule = null; foreach (CreatureRule item in list) { if (text.Contains(item.Key) && (creatureRule == null || item.Key.Length > creatureRule.Key.Length)) { creatureRule = item; } } if (_byName.Count > 512) { _byName.Clear(); } _byName[text] = creatureRule; return creatureRule; } internal static string PrefabName(GameObject go) { int instanceID = ((Object)go).GetInstanceID(); if (_prefabOf.TryGetValue(instanceID, out var value)) { return value; } string name = ((Object)go).name; int num = name.IndexOf('('); name = ((num > 0) ? name.Substring(0, num) : name).Trim(); if (_prefabOf.Count > 4096) { _prefabOf.Clear(); } return _prefabOf[instanceID] = name; } internal static CreatureRule RuleFor(Character c) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c == (Object)null || !Mech.On || !Mech.R.CreatureSeasons) { return null; } try { if (c.IsPlayer() || c.IsBoss() || c.IsTamed()) { return null; } CreatureRule creatureRule = Find(PrefabName(((Component)c).gameObject)); if (creatureRule == null) { return null; } if (WorldGenerator.instance != null && SeasonBiomes.Excluded(WorldGenerator.instance.GetBiome(((Component)c).transform.position))) { return null; } if (creatureRule.DayOnly && SeasonPhase.IsNight()) { return null; } return creatureRule; } catch { return null; } } internal static string SpawnString() { StringBuilder stringBuilder = new StringBuilder(); foreach (CreatureRule item in Rules()) { if (!Mathf.Approximately(item.Spawn, 1f)) { if (stringBuilder.Length > 0) { stringBuilder.Append(','); } stringBuilder.Append(item.Key).Append("*:").Append(item.Spawn.ToString(CultureInfo.InvariantCulture)); } } return stringBuilder.ToString(); } internal static void Tick(float dt) { _timer += dt; if (_timer < 2f) { return; } _timer = 0f; if ((Object)(object)ZNet.instance == (Object)null || (_touched.Count == 0 && !AnySpeedRule())) { return; } List<Character> allCharacters = Character.GetAllCharacters(); for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if ((Object)(object)val == (Object)null) { continue; } float num = RuleFor(val)?.Spd ?? 1f; Speeds value; bool flag = _orig.TryGetValue(val, out value); bool flag2 = Mathf.Approximately(num, 1f); if (!flag && flag2) { continue; } if (!flag) { value = new Speeds { Values = new float[SpeedFields.Length] }; for (int j = 0; j < SpeedFields.Length; j++) { value.Values[j] = (float)SpeedFields[j].GetValue(val); } _orig.Add(val, value); _touched.Add(val); } for (int k = 0; k < SpeedFields.Length; k++) { SpeedFields[k].SetValue(val, value.Values[k] * num); } if (flag2) { _orig.Remove(val); _touched.Remove(val); } } if (_touched.Count > 256) { _touched.RemoveWhere((Character x) => (Object)(object)x == (Object)null); } } private static bool AnySpeedRule() { foreach (CreatureRule item in Rules()) { if (!Mathf.Approximately(item.Spd, 1f)) { return true; } } return false; } internal static void Reset() { foreach (Character item in _touched) { if (!((Object)(object)item == (Object)null) && _orig.TryGetValue(item, out var value)) { for (int i = 0; i < SpeedFields.Length; i++) { SpeedFields[i].SetValue(item, value.Values[i]); } _orig.Remove(item); } } _touched.Clear(); _src = null; _byName.Clear(); _prefabOf.Clear(); } } [HarmonyPatch] internal static class Character_Damage_Season_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Character), "Damage", new Type[1] { typeof(HitData) }, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static void Prefix(Character __instance, HitData hit) { if (hit != null && Mech.On && Mech.R.CreatureSeasons) { float num = 1f; CreatureRule creatureRule = CreatureSeasons.RuleFor(hit.GetAttacker()); if (creatureRule != null) { num *= creatureRule.Dmg; } CreatureRule creatureRule2 = CreatureSeasons.RuleFor(__instance); if (creatureRule2 != null && creatureRule2.Hp > 0f) { num /= creatureRule2.Hp; } if (!Mathf.Approximately(num, 1f)) { ((DamageTypes)(ref hit.m_damage)).Modify(num); } } } } [HarmonyPatch] internal static class CharacterDrop_GenerateDropList_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(CharacterDrop), "GenerateDropList", (Type[])null, (Type[])null); } private static bool TamedFall(Character ch, out float mult) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) mult = 1f; try { if ((Object)(object)ch == (Object)null || !Mech.On || Mech.S != Season.Fall || ch.IsPlayer() || !ch.IsTamed()) { return false; } mult = Mathf.Clamp(Mech.R.TamedFallDrop, 1f, 10f); if (mult <= 1.001f) { return false; } return WorldGenerator.instance == null || !SeasonBiomes.Excluded(WorldGenerator.instance.GetBiome(((Component)ch).transform.position)); } catch { return false; } } private static bool Prepare() { return TargetMethod() != null; } private static void Postfix(CharacterDrop __instance, object __result) { if (!(__result is List<KeyValuePair<GameObject, int>> { Count: not 0 } list) || !TamedFall(((Component)__instance).GetComponent<Character>(), out var mult)) { return; } for (int i = 0; i < list.Count; i++) { if ((Object)(object)list[i].Key != (Object)null) { list[i] = new KeyValuePair<GameObject, int>(list[i].Key, Mathf.Max(1, Mathf.RoundToInt((float)list[i].Value * mult))); } } } } internal static class CropCalendar { internal enum State { NotCrop, Good, Off, Winter } private static readonly FieldInfo PlantTimeKey = AccessTools.Field(typeof(ZDOVars), "s_plantTime"); private static readonly Dictionary<Plant, double> _lastCheck = new Dictionary<Plant, double>(); private static readonly int PauseKey = StringExtensionMethods.GetStableHashCode("ValheimSeasons_pauseAt"); private static int _pruneCount; private static string _calCache; private static Dictionary<string, HashSet<Season>> _cal; internal static string CropKey(Plant p) { if ((Object)(object)p == (Object)null) { return null; } string text = ((Object)p).name.ToLowerInvariant(); if (!text.Contains("sapling_")) { return null; } foreach (KeyValuePair<string, HashSet<Season>> item in Calendar()) { if (text.Contains(item.Key)) { return item.Key; } } return null; } internal static Dictionary<string, HashSet<Season>> Calendar() { string text = Mech.R.CropSeasons ?? ""; if (_cal != null && _calCache == text) { return _cal; } _calCache = text; _cal = new Dictionary<string, HashSet<Season>>(); string[] array = text.Split(','); foreach (string text2 in array) { int num = text2.IndexOf(':'); if (num <= 0) { continue; } HashSet<Season> hashSet = new HashSet<Season>(); string[] array2 = text2.Substring(num + 1).Split('+'); for (int j = 0; j < array2.Length; j++) { switch (array2[j].Trim().ToLowerInvariant()) { case "spring": case "primavera": hashSet.Add(Season.Spring); break; case "summer": case "verao": case "verão": hashSet.Add(Season.Summer); break; case "outono": case "fall": hashSet.Add(Season.Fall); break; case "winter": case "inverno": hashSet.Add(Season.Winter); break; } } _cal[text2.Substring(0, num).Trim().ToLowerInvariant()] = hashSet; } return _cal; } internal static bool SeasonalAt(Vector3 pos) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) try { return WorldGenerator.instance == null || !SeasonBiomes.Excluded(WorldGenerator.instance.GetBiome(pos)); } catch { return true; } } internal static bool WinterFrozen(Vector3 pos) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (Mech.On && Mech.R.CropCalendar && Mech.S == Season.Winter) { return SeasonalAt(pos); } return false; } internal static State StateOf(Plant p, out string key) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) key = CropKey(p); if ((Object)(object)p == (Object)null || !Mech.On || !Mech.R.CropCalendar) { return State.NotCrop; } if (Mech.S == Season.Winter) { if (!SeasonalAt(((Component)p).transform.position)) { return State.NotCrop; } return State.Winter; } if (key == null) { return State.NotCrop; } if (!Calendar()[key].Contains(Mech.S)) { return State.Off; } return State.Good; } internal static float GrowMultiplier(Plant p) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || !SeasonalAt(((Component)p).transform.position)) { return 1f; } string key; State state = StateOf(p, out key); if (state == State.NotCrop) { return SeasonClient.GrowMultiplier(); } SeasonMechanics r = Mech.R; float num = state switch { State.Good => r.CropGoodSeason, State.Off => r.CropOffSeason, _ => 1f, }; if (Mech.S == Season.Spring && PlantedEarlySpring(p)) { num *= r.EarlySpringBonus; } return Mathf.Max(0.05f, num); } private static bool PlantedEarlySpring(Plant p) { try { if (!SeasonClient.HasState || SeasonClient.State.Forced || (Object)(object)EnvMan.instance == (Object)null) { return false; } ZNetView component = ((Component)p).GetComponent<ZNetView>(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val == null || PlantTimeKey == null) { return false; } long num = val.GetLong((int)PlantTimeKey.GetValue(null), 0L); if (num <= 0) { return false; } double num2 = Math.Max(1.0, EnvMan.instance.m_dayLengthSec); int num3 = (int)(new TimeSpan(num).TotalSeconds / num2); int num4 = Math.Max(1, SeasonClient.Rules.DaysPerSeason); int num5 = SeasonClient.State.Day - (num4 - 1 - SeasonClient.State.DaysLeft); return num3 >= num5 && num3 < num5 + Math.Max(1, Mech.R.EarlySpringDays); } catch { return false; } } internal static void PauseTick(Plant p) { ZNetView component = ((Component)p).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || (Object)(object)ZNet.instance == (Object)null || PlantTimeKey == null) { return; } double timeSeconds = ZNet.instance.GetTimeSeconds(); ZDO zDO = component.GetZDO(); if (++_pruneCount > 500) { _pruneCount = 0; Prune(); } if (StateOf(p, out var _) != State.Winter) { _lastCheck[p] = timeSeconds; if (zDO.GetLong(PauseKey, 0L) > 0) { zDO.Set(PauseKey, -1L); } return; } int num = (int)PlantTimeKey.GetValue(null); long num2 = zDO.GetLong(num, 0L); if (num2 <= 0) { return; } double totalSeconds = new TimeSpan(num2).TotalSeconds; if (!_lastCheck.TryGetValue(p, out var value)) { long num3 = zDO.GetLong(PauseKey, 0L); value = ((num3 > 0) ? new TimeSpan(num3).TotalSeconds : ((num3 >= 0) ? WinterStartSeconds(timeSeconds) : timeSeconds)); if (value < totalSeconds) { value = totalSeconds; } } _lastCheck[p] = timeSeconds; double num4 = timeSeconds - value; if (num4 <= 0.0) { zDO.Set(PauseKey, TimeSpan.FromSeconds(timeSeconds).Ticks); return; } zDO.Set(num, num2 + TimeSpan.FromSeconds(num4).Ticks); zDO.Set(PauseKey, TimeSpan.FromSeconds(timeSeconds).Ticks); } private static double WinterStartSeconds(double now) { if (!SeasonClient.HasState || SeasonClient.State.Forced || SeasonClient.State.Season != Season.Winter || (Object)(object)EnvMan.instance == (Object)null) { return now; } int num = Math.Max(1, SeasonClient.Rules.DaysPerSeason); double num2 = (double)(SeasonClient.State.Day - (num - 1 - SeasonClient.State.DaysLeft)) * Math.Max(1.0, EnvMan.instance.m_dayLengthSec); if (!(num2 > 0.0) || !(num2 < now)) { return now; } return num2; } private static void Prune() { List<Plant> list = null; foreach (KeyValuePair<Plant, double> item in _lastCheck) { if ((Object)(object)item.Key == (Object)null) { List<Plant> obj = list ?? new List<Plant>(); list = obj; obj.Add(item.Key); } } if (list == null) { return; } foreach (Plant item2 in list) { _lastCheck.Remove(item2); } } internal static void Reset() { _lastCheck.Clear(); _pruneCount = 0; } internal static string Hover(Plant p) { string key; return StateOf(p, out key) switch { State.Good => "<color=#9be564>Estação boa: cresce mais rápido</color>", State.Off => "<color=#e5c364>Fora de época: cresce devagar</color>", State.Winter => "<color=#9fd3ff>Congelada: nada cresce no inverno (volta na primavera)</color>", _ => null, }; } } [HarmonyPatch] internal static class Plant_SUpdate_Patch { private static readonly FieldRef<Plant, float> UpdateTime = UpdateTimeRef(); private static FieldRef<Plant, float> UpdateTimeRef() { try { return AccessTools.FieldRefAccess<Plant, float>("m_updateTime"); } catch { return null; } } private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Plant), "SUpdate", (Type[])null, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static void Prefix(Plant __instance, float __0) { if (UpdateTime == null || !(__0 <= UpdateTime.Invoke(__instance))) { CropCalendar.PauseTick(__instance); } } } [HarmonyPatch] internal static class Player_TryPlacePiece_Winter_Patch { private static readonly FieldInfo Ghost = AccessTools.Field(typeof(Player), "m_placementGhost"); private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Player), "TryPlacePiece", (Type[])null, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static bool Prefix(Player __instance, Piece __0, ref bool __result) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)__0 == (Object)null || (Object)(object)((Component)__0).GetComponent<Plant>() == (Object)null) { return true; } object? obj = Ghost?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!CropCalendar.WinterFrozen(((Object)(object)val != (Object)null) ? val.transform.position : ((Component)__instance).transform.position)) { return true; } ((Character)__instance).Message((MessageType)2, "O chão está congelado: não dá pra plantar no inverno", 0, (Sprite)null, false); __result = false; return false; } } [HarmonyPatch] internal static class Plant_GetHoverText_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Plant), "GetHoverText", (Type[])null, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static void Postfix(Plant __instance, ref string __result) { string text = CropCalendar.Hover(__instance); if (text != null) { __result = __result + "\n" + text; } } } internal static class FrozenWater { private class Template { public GameObject Go; public string Name; public float Radius; public float Offset; public float ScaleMin = 1f; public float ScaleMax = 1f; } private struct Rng { private uint _s; public Rng(int seed) { _s = (uint)(seed ^ -1640531527); if (_s == 0) { _s = 1u; } } public float Next01() { _s ^= _s << 13; _s ^= _s >> 17; _s ^= _s << 5; return (float)(_s & 0xFFFFFF) / 16777216f; } public float Range(float a, float b) { return a + (b - a) * Next01(); } } private static readonly Dictionary<WaterVolume, List<GameObject>> _zones = new Dictionary<WaterVolume, List<GameObject>>(); private static readonly List<Collider> _colliders = new List<Collider>(); private static bool _frozen; private static float _timer; private static float _density = -1f; private static Material _iceMat; private static bool _iceIsFallback; private static bool _warnedIce; private static float _lastIceScan = -999f; private static Texture2D _iceTex; private static FieldInfo _surfaceField; private static MethodInfo _isAshlands; private static Func<float, float, bool> _isAshlandsFast; private static bool _reflected; private const int BaseFloesPerZone = 7; private static readonly Queue<WaterVolume> _queue = new Queue<WaterVolume>(); private static bool _decided; private static string _lastMode = "auto"; private static List<Template> _templates; private static string _templatesKey; private static GameObject _templateRoot; private static readonly Stopwatch _sw = new Stopwatch(); private static readonly Queue<GameObject> _trash = new Queue<GameObject>(); private const float Thickness = 0.8f; private const float Freeboard = 0.15f; private static readonly List<Ship> _ships = new List<Ship>(); internal static bool Frozen => _frozen; private static float Density => Mathf.Clamp(SeasonClient.Rules.Mech.IceFloes, 0f, 4f); internal static bool Wanted { get { if (SeasonClient.Active && SeasonClient.Rules.FreezeWater && SeasonClient.Current == Season.Winter && (Object)(object)ZoneSystem.instance != (Object)null && WorldGenerator.instance != null) { return Density > 0f; } return false; } } internal static void Tick(float dt) { PumpTrash(); Pump(); _timer += dt; if (_timer < 1f) { return; } _timer = 0f; if (!SeasonClient.Active || (Object)(object)ZoneSystem.instance == (Object)null) { return; } bool wanted = Wanted; if (wanted && _frozen && (!Mathf.Approximately(_density, Density) || TemplatesKey() != _templatesKey)) { MeltAll(); FreezeAll(); return; } string obj = (SeasonClient.Testing ? ("teste:" + SeasonClient.Current) : (SeasonClient.State.Forced ? ("admin:" + SeasonClient.Current) : "auto")); bool flag = obj != _lastMode; _lastMode = obj; bool flag2 = !_decided || flag || !SeasonClient.Rules.SwapAtNight || SeasonClient.Testing || SeasonPhase.IsNight(); _decided = true; if (wanted && !_frozen && flag2) { FreezeAll(); } else if (!wanted && _frozen && flag2) { MeltAll(); } else if (_frozen) { Cleanup(); } } internal static void Shutdown() { MeltAll(); while (_trash.Count > 0) { GameObject val = _trash.Dequeue(); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } _decided = false; _lastMode = "auto"; _ships.Clear(); } private static void Pump() { if (_queue.Count == 0) { return; } if (!_frozen) { _queue.Clear(); return; } float num = Mathf.Max(0.5f, Plugin.FrameBudgetMs.Value * 0.5f); _sw.Restart(); int count = _colliders.Count; int num2 = 0; while (_queue.Count > 0 && _sw.Elapsed.TotalMilliseconds < (double)num) { WaterVolume val = _queue.Dequeue(); if ((Object)(object)val != (Object)null) { num2 += Add(val); } } if (_colliders.Count > count && _ships.Count > 0) { List<Collider> range = _colliders.GetRange(count, _colliders.Count - count); _ships.RemoveAll((Ship s) => (Object)(object)s == (Object)null); foreach (Ship ship in _ships) { IgnoreShip(ship, range); } } if (_queue.Count == 0 && num2 > 0 && Plugin.DumpMaterials.Value) { Plugin.Log.LogInfo((object)$"Placas de gelo: {CountAll()} no total."); } } private static int CountAll() { int num = 0; foreach (KeyValuePair<WaterVolume, List<GameObject>> zone in _zones) { num += zone.Value.Count; } return num; } private static void FreezeAll() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) _frozen = true; _density = Density; Templates(); _queue.Clear(); List<WaterVolume> list = new List<WaterVolume>(Object.FindObjectsByType<WaterVolume>((FindObjectsSortMode)0)); Vector3 c = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform.position : (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero)); list.Sort(delegate(WaterVolume a, WaterVolume b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)a).transform.position - c; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = ((Component)b).transform.position - c; return sqrMagnitude.CompareTo(((Vector3)(ref val)).sqrMagnitude); }); foreach (WaterVolume item in list) { _queue.Enqueue(item); } Plugin.Log.LogInfo((object)($"Inverno: placas de gelo em {list.Count} zona(s) de água " + ((_templates.Count > 0) ? ("(do jogo: " + string.Join(", ", _templates.ConvertAll((Template t) => t.Name)) + ")") : "(geradas)"))); } internal static void MeltAll() { _frozen = false; _queue.Clear(); foreach (KeyValuePair<WaterVolume, List<GameObject>> zone in _zones) { foreach (GameObject item in zone.Value) { if ((Object)(object)item != (Object)null) { _trash.Enqueue(item); } } } _zones.Clear(); _colliders.Clear(); } private static void PumpTrash() { for (int i = 0; i < 40; i++) { if (_trash.Count <= 0) { break; } GameObject val = _trash.Dequeue(); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } } private static void Cleanup() { List<WaterVolume> list = null; foreach (KeyValuePair<WaterVolume, List<GameObject>> zone in _zones) { if ((Object)(object)zone.Key == (Object)null) { List<WaterVolume> obj = list ?? new List<WaterVolume>(); list = obj; obj.Add(zone.Key); } } if (list == null) { return; } foreach (WaterVolume item in list) { _zones.Remove(item); } _colliders.RemoveAll((Collider c) => (Object)(object)c == (Object)null); } internal static void OnWaterVolumeCreated(WaterVolume wv) { if (_frozen && !((Object)(object)wv == (Object)null) && !_zones.ContainsKey(wv)) { _queue.Enqueue(wv); } } private static int Add(WaterVolume wv) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)wv == (Object)null || _zones.ContainsKey(wv)) { return 0; } Reflect(); object? obj = _surfaceField?.GetValue(wv); Renderer val = (Renderer)(((obj is Renderer) ? obj : null) ?? ((Component)wv).GetComponentInChildren<MeshRenderer>()); Bounds val2 = (Bounds)(((Object)(object)val != (Object)null) ? val.bounds : new Bounds(((Component)wv).transform.position, new Vector3(64f, 1f, 64f))); float waterLevel = ZoneSystem.instance.m_waterLevel; List<GameObject> list = new List<GameObject>(); _zones[wv] = list; int x = Mathf.FloorToInt((((Bounds)(ref val2)).center.x + 32f) / 64f); int z = Mathf.FloorToInt((((Bounds)(ref val2)).center.z + 32f) / 64f); Rng rng = new Rng(Hash(x, z)); float num = 7f * Density; int num2 = Mathf.FloorToInt(num) + ((rng.Next01() < num - Mathf.Floor(num)) ? 1 : 0); float num3 = Mathf.Max(4f, ((Bounds)(ref val2)).extents.x - 4f); float num4 = Mathf.Max(4f, ((Bounds)(ref val2)).extents.z - 4f); List<Template> list2 = Templates(); for (int i = 0; i < num2; i++) { float num5 = rng.Next01() * rng.Next01(); float num6 = ((Bounds)(ref val2)).center.x + rng.Range(0f - num3, num3); float num7 = ((Bounds)(ref val2)).center.z + rng.Range(0f - num4, num4); float num8 = rng.Next01(); float rot = rng.Next01() * 360f; int seed = (int)(rng.Next01() * 2.1474836E+09f); if (list2.Count > 0) { Template template = list2[Mathf.Min(list2.Count - 1, (int)(num8 * (float)list2.Count))]; float num9 = Mathf.Lerp(template.ScaleMin, template.ScaleMax, num5); float r = template.Radius * num9; if (GoodSpot(num6, num7, r, waterLevel) && !TooClose(list, num6, num7, r)) { list.Add(SpawnTemplate(wv, template, new Vector3(num6, waterLevel, num7), rot, num9, seed)); } } else { float num10 = Mathf.Lerp(2.2f, 7.5f, num5); int sides = 6 + (int)(num8 * 3f); if (GoodSpot(num6, num7, num10, waterLevel) && !TooClose(list, num6, num7, num10)) { list.Add(MakeFloe(wv, new Vector3(num6, waterLevel, num7), num10, sides, rot, seed)); } } } return list.Count; } private static bool GoodSpot(float x, float z, float r, float level) { if (IsExcludedSea(x, z)) { return false; } WorldGenerator instance = WorldGenerator.instance; float num = level - 1.5f; if (instance.GetHeight(x, z) > num) { return false; } for (int i = 0; i < 4; i++) { float num2 = (float)i * (float)Math.PI * 0.5f; if (instance.GetHeight(x + Mathf.Cos(num2) * r, z + Mathf.Sin(num2) * r) > num) { return false; } } return true; } private static bool TooClose(List<GameObject> list, float x, float z, float r) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject item in list) { if (!((Object)(object)item == (Object)null)) { Floe component = item.GetComponent<Floe>(); float num = r + (((Object)(object)component != (Object)null) ? component.Radius : 4f) + 1f; Vector3 position = item.transform.position; if ((position.x - x) * (position.x - x) + (position.z - z) * (position.z - z) < num * num) { return true; } } } return false; } private static GameObject MakeFloe(WaterVolume wv, Vector3 pos, float radius, int sides, float rot, int seed) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ValheimSeasons_IceFloe"); val.transform.SetParent(((Component)wv).transform, true); val.transform.SetPositionAndRotation(pos, Quaternion.Euler(0f, rot, 0f)); int num = LayerMask.NameToLayer("static_solid"); val.layer = ((num >= 0) ? num : 0); Mesh sharedMesh = BuildMesh(radius, sides, seed); Rigidbody val2 = val.AddComponent<Rigidbody>(); val2.isKinematic = true; val2.useGravity = false; val2.interpolation = (RigidbodyInterpolation)1; MeshCollider val3 = val.AddComponent<MeshCollider>(); val3.sharedMesh = sharedMesh; val3.convex = true; _colliders.Add((Collider)(object)val3); if (!Plugin.Headless) { val.AddComponent<MeshFilter>().sharedMesh = sharedMesh; MeshRenderer obj = val.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = IceMaterial(); ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)obj).receiveShadows = true; } val.AddComponent<Floe>().Init(wv, radius, val2, seed, 0f, procedural: true); return val; } private static string TemplatesKey() { return (SeasonClient.Rules.Mech.IceFloePrefabs ?? "auto").Trim().ToLowerInvariant(); } private static List<Template> Templates() { string text = TemplatesKey(); if (_templates != null && text == _templatesKey) { return _templates; } ClearTemplates(); _templatesKey = text; _templates = new List<Template>(); try { object obj; switch (text) { case "gerado": case "none": return _templates; default: if (text.Length != 0) { obj = SeasonMechanics.ParseList(text); break; } goto case "auto"; case "auto": obj = null; break; } List<string> list = (List<string>)obj; if (!(AccessTools.Field(typeof(ZoneSystem), "m_vegetation")?.GetValue(ZoneSystem.instance) is IEnumerable enumerable)) { return _templates; } HashSet<string> hashSet = new HashSet<string>(); int num = 64; foreach (object item in enumerable) { if (item == null) { continue; } Traverse val = Traverse.Create(item); GameObject value = val.Field("m_prefab").GetValue<GameObject>(); if ((Object)(object)value == (Object)null || !hashSet.Add(((Object)value).name)) { continue; } string text2 = ((Object)value).name.ToLowerInvariant(); bool flag; if (list != null) { flag = false; foreach (string item2 in list) { if (text2.Contains(item2)) { flag = true; break; } } } else { bool value2 = val.Field("m_enable").GetValue<bool>(); int num2 = Convert.ToInt32(val.Field("m_biome").GetValue()); bool value3 = val.Field("m_snapToWater").GetValue<bool>(); flag = value2 && value3 && (num2 & num) != 0; } if (flag) { Template template = BuildTemplate(value); if (template != null) { template.Offset = val.Field("m_groundOffset").GetValue<float>(); template.ScaleMin = Mathf.Max(0.1f, val.Field("m_scaleMin").GetValue<float>()); template.ScaleMax = Mathf.Max(template.ScaleMin, val.Field("m_scaleMax").GetValue<float>()); _templates.Add(template); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Não achei as placas de gelo do jogo: " + ex.Message)); } if (_templates.Count == 0) { Plugin.Log.LogInfo((object)("Placas de gelo do jogo não encontradas (IceFloePrefabs = " + text + "): usando as geradas.")); } return _templates; } private static void ClearTemplates() { if (_templates != null) { foreach (Template template in _templates) { if ((Object)(object)template.Go != (Object)null) { Object.Destroy((Object)(object)template.Go); } } } _templates = null; } private static Template BuildTemplate(GameObject prefab) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: 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_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_templateRoot == (Object)null) { _templateRoot = new GameObject("ValheimSeasons_FloeTemplates"); _templateRoot.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_templateRoot); } HashSet<Renderer> hashSet = null; LODGroup componentInChildren = prefab.GetComponentInChildren<LODGroup>(true); if ((Object)(object)componentInChildren != (Object)null) { LOD[] lODs = componentInChildren.GetLODs(); if (lODs.Length != 0) { hashSet = new HashSet<Renderer>(); Renderer[] renderers = lODs[0].renderers; foreach (Renderer val in renderers) { if ((Object)(object)val != (Object)null) { hashSet.Add(val); } } } } GameObject val2 = new GameObject("ValheimSeasons_IceFloe_" + ((Object)prefab).name); val2.transform.SetParent(_templateRoot.transform, false); val2.layer = prefab.layer; if (CopyParts(prefab.transform, val2.transform, hashSet) == 0) { Object.Destroy((Object)(object)val2); return null; } bool any = false; Bounds bb = default(Bounds); Matrix4x4 worldToLocalMatrix = val2.transform.worldToLocalMatrix; MeshFilter[] componentsInChildren = val2.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val3 in componentsInChildren) { if ((Object)(object)val3.sharedMesh != (Object)null) { Encap(ref bb, ref any, val3.sharedMesh.bounds, worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix); } } MeshCollider[] componentsInChildren2 = val2.GetComponentsInChildren<MeshCollider>(true); foreach (MeshCollider val4 in componentsInChildren2) { if ((Object)(object)val4.sharedMesh != (Object)null) { Encap(ref bb, ref any, val4.sharedMesh.bounds, worldToLocalMatrix * ((Component)val4).transform.localToWorldMatrix); } } BoxCollider[] componentsInChildren3 = val2.GetComponentsInChildren<BoxCollider>(true); foreach (BoxCollider val5 in componentsInChildren3) { Encap(ref bb, ref any, new Bounds(val5.center, val5.size), worldToLocalMatrix * ((Component)val5).transform.localToWorldMatrix); } float num = (any ? Mathf.Max(new float[3] { ((Bounds)(ref bb)).extents.x, ((Bounds)(ref bb)).extents.z, 1f }) : 4f); return new Template { Go = val2, Name = ((Object)prefab).name, Radius = Mathf.Min(num, 30f) }; } private static void Encap(ref Bounds bb, ref bool any, Bounds local, Matrix4x4 m) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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) Vector3 center = ((Bounds)(ref local)).center; Vector3 extents = ((Bounds)(ref local)).extents; for (int i = 0; i < 8; i++) { Vector3 val = ((Matrix4x4)(ref m)).MultiplyPoint3x4(center + new Vector3(((i & 1) == 0) ? (0f - extents.x) : extents.x, ((i & 2) == 0) ? (0f - extents.y) : extents.y, ((i & 4) == 0) ? (0f - extents.z) : extents.z)); if (!any) { bb = new Bounds(val, Vector3.zero); any = true; } else { ((Bounds)(ref bb)).Encapsulate(val); } } } private static int CopyParts(Transform src, Transform dst, HashSet<Renderer> allowed) { //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_01bd: Unknown result type (might be due to invalid IL or missing references) int num = 0; GameObject gameObject = ((Component)dst).gameObject; MeshFilter component = ((Component)src).GetComponent<MeshFilter>(); MeshRenderer component2 = ((Component)src).GetComponent<MeshRenderer>(); if (!Plugin.Headless && (Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null && (Object)(object)component2 != (Object)null && ((Renderer)component2).enabled && (allowed == null || allowed.Contains((Renderer)(object)component2))) { gameObject.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh; MeshRenderer obj = gameObject.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterials = ((Renderer)component2).sharedMaterials; ((Renderer)obj).shadowCastingMode = ((Renderer)component2).shadowCastingMode; ((Renderer)obj).receiveShadows = ((Renderer)component2).receiveShadows; num++; } Collider[] components = ((Component)src).GetComponents<Collider>(); foreach (Collider val in components) { if ((Object)(object)val == (Object)null || val.isTrigger || !val.enabled) { continue; } Collider val2 = val; MeshCollider val3 = (MeshCollider)(object)((val2 is MeshCollider) ? val2 : null); if (val3 == null) { BoxCollider val4 = (BoxCollider)(object)((val2 is BoxCollider) ? val2 : null); if (val4 == null) { SphereCollider val5 = (SphereCollider)(object)((val2 is SphereCollider) ? val2 : null); if (val5 == null) { CapsuleCollider val6 = (CapsuleCollider)(object)((val2 is CapsuleCollider) ? val2 : null); if (val6 != null) { CapsuleCollider obj2 = gameObject.AddComponent<CapsuleCollider>(); obj2.center = val6.center; obj2.radius = val6.radius; obj2.height = val6.height; obj2.direction = val6.direction; ((Collider)obj2).sharedMaterial = ((Collider)val6).sharedMaterial; num++; } } else { SphereCollider obj3 = gameObject.AddComponent<SphereCollider>(); obj3.center = val5.center; obj3.radius = val5.radius; ((Collider)obj3).sharedMaterial = ((Collider)val5).sharedMaterial; num++; } } else { BoxCollider obj4 = gameObject.AddComponent<BoxCollider>(); obj4.center = val4.center; obj4.size = val4.size; ((Collider)obj4).sharedMaterial = ((Collider)val4).sharedMaterial; num++; } } else if ((Object)(object)val3.sharedMesh != (Object)null) { MeshCollider obj5 = gameObject.AddComponent<MeshCollider>(); obj5.sharedMesh = val3.sharedMesh; obj5.convex = true; ((Collider)obj5).sharedMaterial = ((Collider)val3).sharedMaterial; num++; } } foreach (Transform item in src) { Transform val7 = item; if (((Component)val7).gameObject.activeSelf) { GameObject val8 = new GameObject(((Object)val7).name); val8.layer = ((Component)val7).gameObject.layer; val8.transform.SetParent(dst, false); val8.transform.localPosition = val7.localPosition; val8.transform.localRotation = val7.localRotation; val8.transform.localScale = val7.localScale; int num2 = CopyParts(val7, val8.transform, allowed); if (num2 == 0) { Object.Destroy((Object)(object)val8); } num += num2; } } return num; } private static GameObject SpawnTemplate(WaterVolume wv, Template t, Vector3 pos, float rot, float scale, int seed) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(t.Go, pos + Vector3.up * t.Offset, Quaternion.Euler(0f, rot, 0f), ((Component)wv).transform); ((Object)val).name = "ValheimSeasons_IceFloe"; Vector3 lossyScale = ((Component)wv).transform.lossyScale; val.transform.localScale = new Vector3(scale / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.x)), scale / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.y)), scale / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.z))); Rigidbody val2 = val.AddComponent<Rigidbody>(); val2.isKinematic = true; val2.useGravity = false; val2.interpolation = (RigidbodyInterpolation)1; Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true); foreach (Collider item in componentsInChildren) { _colliders.Add(item); } val.AddComponent<Floe>().Init(wv, t.Radius * scale, val2, seed, t.Offset, procedural: false); val.SetActive(true); return val; } private static Mesh BuildMesh(float radius, int sides, int seed) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0268: 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) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Expected O, but got Unknown Rng rng = new Rng(seed); Vector3[] array = (Vector3[])(object)new Vector3[sides]; for (int i = 0; i < sides; i++) { float num = ((float)i + rng.Range(-0.25f, 0.25f)) / (float)sides * (float)Math.PI * 2f; float num2 = radius * rng.Range(0.78f, 1f); array[i] = new Vector3(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2); } float num3 = 0.15f; float num4 = -0.65f; float num5 = 0.125f; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(rng.Next01() * 8f, rng.Next01() * 8f); List<Vector3> list = new List<Vector3>(); List<Vector2> list2 = new List<Vector2>(); List<int> list3 = new List<int>(); int count = list.Count; list.Add(new Vector3(0f, num3, 0f)); list2.Add(val); for (int j = 0; j < sides; j++) { Vector3 val2 = array[j] * 0.94f; val2.y = num3; list.Add(val2); list2.Add(new Vector2(val2.x, val2.z) * num5 + val); } for (int k = 0; k < sides; k++) { list3.Add(count); list3.Add(count + 1 + (k + 1) % sides); list3.Add(count + 1 + k); } for (int l = 0; l < sides; l++) { int num6 = (l + 1) % sides; Vector3 a = array[l] * 0.94f; Vector3 a2 = array[num6] * 0.94f; a.y = (a2.y = num3); Vector3 b = array[l]; Vector3 b2 = array[num6]; b.y = (b2.y = num3 - 0.12f); Quad(list, list2, list3, a, a2, b2, b, num5, val); } for (int m = 0; m < sides; m++) { int num7 = (m + 1) % sides; Vector3 a3 = array[m]; Vector3 a4 = array[num7]; a3.y = (a4.y = num3 - 0.12f); Vector3 b3 = array[m] * 0.9f; Vector3 b4 = array[num7] * 0.9f; b3.y = (b4.y = num4); Quad(list, list2, list3, a3, a4, b4, b3, num5, val); } count = list.Count; list.Add(new Vector3(0f, num4, 0f)); list2.Add(val); for (int n = 0; n < sides; n++) { Vector3 val3 = array[n] * 0.9f; val3.y = num4; list.Add(val3); list2.Add(new Vector2(val3.x, val3.z) * num5 + val); } for (int num8 = 0; num8 < sides; num8++) { list3.Add(count); list3.Add(count + 1 + num8); list3.Add(count + 1 + (num8 + 1) % sides); } Mesh val4 = new Mesh { name = "valheimseasons_floe" }; val4.SetVertices(list); val4.SetUVs(0, list2); val4.SetTriangles(list3, 0); val4.RecalculateNormals(); val4.RecalculateTangents(); val4.RecalculateBounds(); return val4; } private static void Quad(List<Vector3> v, List<Vector2> uv, List<int> tri, Vector3 a0, Vector3 a1, Vector3 b1, Vector3 b0, float s, Vector2 off) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) int count = v.Count; v.Add(a0); v.Add(a1); v.Add(b1); v.Add(b0); Vector3 val = a1 - a0; float magnitude = ((Vector3)(ref val)).magnitude; float num = Mathf.Abs(a0.y - b0.y); val = a0 - b0; float num2 = num + ((Vector3)(ref val)).magnitude * 0.5f; Vector2 val2 = off + new Vector2(a0.x, a0.z) * s; uv.Add(val2); uv.Add(val2 + new Vector2(magnitude * s, 0f)); uv.Add(val2 + new Vector2(magnitude * s, (0f - num2) * s)); uv.Add(val2 + new Vector2(0f, (0f - num2) * s)); tri.Add(count); tri.Add(count + 1); tri.Add(count + 2); tri.Add(count); tri.Add(count + 2); tri.Add(count + 3); } internal static void OnShip(Ship ship) { if (!((Object)(object)ship == (Object)null)) { if (!_ships.Contains(ship)) { _ships.Add(ship); } IgnoreShip(ship, _colliders); } } private static void IgnoreShip(Ship ship, List<Collider> floes) { if ((Object)(object)ship == (Object)null || floes.Count == 0) { return; } Collider[] componentsInChildren = ((Component)ship).GetComponentsInChildren<Collider>(true); foreach (Collider flo in floes) { if ((Object)(object)flo == (Object)null) { continue; } Collider[] array = componentsInChildren; foreach (Collider val in array) { if ((Object)(object)val != (Object)null && !val.isTrigger) { Physics.IgnoreCollision(val, flo, true); } } } } private static void Reflect() { if (_reflected) { return; } _reflected = true; _surfaceField = AccessTools.Field(typeof(WaterVolume), "m_waterSurface"); _isAshlands = AccessTools.Method(typeof(WorldGenerator), "IsAshlands", new Type[2] { typeof(float), typeof(float) }, (Type[])null); if (!(_isAshlands != null) || !_isAshlands.IsStatic || !(_isAshlands.ReturnType == typeof(bool))) { return; } try { _isAshlandsFast = (Func<float, float, bool>)Delegate.CreateDelegate(typeof(Func<float, float, bool>), _isAshlands); } catch { _isAshlandsFast = null; } } internal static bool IsExcludedSea(float x, float z) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 Reflect(); try { if (WorldGenerator.instance != null && (int)WorldGenerator.instance.GetBiome(x, z, 0.02f, false) == 64) { return true; } if (_isAshlandsFast != null) { return _isAshlandsFast(x, z); } if (_isAshlands != null) { return (bool)_isAshlands.Invoke(_isAshlands.IsStatic ? null : WorldGenerator.instance, new object[2] { x, z }); } if (WorldGenerator.instance != null) { return (int)WorldGenerator.instance.GetBiome(x, z, 0.02f, false) == 32; } } catch { } return false; } private static int Hash(int x, int z) { int num = (x * 73856093) ^ (z * 19349663) ^ 0x2F6B1A3D; int num2 = (num ^ (num >> 13)) * 1540483477; return num2 ^ (num2 >> 15); } private static Material IceMaterial() { //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_00cd: Expected O, but got Unknown //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown //IL_0277: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_iceMat != (Object)null && (!_iceIsFallback || Time.time - _lastIceScan < 30f)) { return _iceMat; } _lastIceScan = Time.time; string text = (Plugin.IceMaterial.Value ?? "").Trim(); if (text.Length == 0) { text = "ice"; } if (!text.Equals("gerado", StringComparison.OrdinalIgnoreCase)) { Material[] array = Resources.FindObjectsOfTypeAll<Material>(); foreach (Material val in array) { if (!((Object)(object)val == (Object)null) && !(((Object)val).name.Replace("(Instance)", "").Trim() != text)) { _iceMat = new Material(val) { name = "valheimseasons_ice_" + text }; Object.DontDestroyOnLoad((Object)(object)_iceMat); _iceIsFallback = false; ManualLogSource log = Plugin.Log; string[] obj = new string[5] { "Gelo usando o material do jogo: ", text, " (shader ", null, null }; Shader shader = val.shader; obj[3] = ((shader != null) ? ((Object)shader).name : null); obj[4] = ")"; log.LogInfo((object)string.Concat(obj)); return _iceMat; } } if (!_warnedIce) { _warnedIce = true; Plugin.Log.LogInfo((object)("Material de gelo '" + text + "' ainda não carregado (o jogo carrega ao passar perto do Deep North). Usando o gelo gerado por enquanto.")); } if ((Object)(object)_iceMat != (Object)null) { return _iceMat; } } Shader val2 = null; string[] array2 = new string[4] { "Custom/Piece", "Standard", "Legacy Shaders/Diffuse", "Sprites/Default" }; for (int i = 0; i < array2.Length; i++) { val2 = Shader.Find(array2[i]); if ((Object)(object)val2 != (Object)null) { break; } } if ((Object)(object)val2 == (Object)null) { Shader[] array3 = Resources.FindObjectsOfTypeAll<Shader>(); foreach (Shader val3 in array3) { if ((Object)(object)val3 != (Object)null && ((Object)val3).name == "Custom/Piece") { val2 = val3; break; } } } _iceTex = (((Object)(object)_iceTex != (Object)null) ? _iceTex : MakeIceTexture(512)); _iceIsFallback = !text.Equals("gerado", StringComparison.OrdinalIgnoreCase); _iceMat = new Material(val2) { name = "valheimseasons_ice", mainTexture = (Texture)(object)_iceTex }; if (_iceMat.HasProperty("_Color")) { _iceMat.SetColor("_Color", Color.white); } if (_iceMat.HasProperty("_Glossiness")) { _iceMat.SetFloat("_Glossiness", 0.75f); } Object.DontDestroyOnLoad((Object)(object)_iceMat); return _iceMat; } internal static void ResetMaterial() { _iceMat = null; _iceIsFallback = false; _warnedIce = false; if (_frozen) { MeltAll(); FreezeAll(); } } internal static void RefreshMaterial(Renderer r) { if (!((Object)(object)r == (Object)null) && _iceIsFallback) { Material val = IceMaterial(); if ((Object)(object)r.sharedMaterial != (Object)(object)val) { r.sharedMaterial = val; } } } private static Texture2D MakeIceTexture(int size) { //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Expected O, but got Unknown //IL_0187: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_012b: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[size * size]; Color val = default(Color); ((Color)(ref val))..ctor(0.62f, 0.76f, 0.88f); Color val2 = default(Color); ((Color)(ref val2))..ctor(0.9f, 0.95f, 1f); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float u = (float)j / (float)size; float v = (float)i / (float)size; float num = Tile(u, v, 4f, 4); float num2 = Mathf.Abs(Tile(u, v, 9f, 2) - 0.5f); float num3 = ((num2 < 0.018f) ? (1f - num2 / 0.018f) : 0f); float num4 = Tile(u, v, 24f, 2); Color val3 = Color.Lerp(val, val2, Mathf.SmoothStep(0.25f, 0.8f, num)); val3 = Color.Lerp(val3, Color.white, Mathf.Clamp01((num4 - 0.55f) * 2f) * 0.6f); val3 = Color.Lerp(val3, new Color(0.97f, 0.99f, 1f), num3 * 0.8f); val3.a = 1f; array[i * size + j] = Color32.op_Implicit(val3); } } Texture2D val4 = new Texture2D(size, size, (TextureFormat)4, true) { name = "valheimseasons_ice_tex", wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)2, anisoLevel = 4 }; val4.SetPixels32(array); val4.Apply(true); Object.DontDestroyOnLoad((Object)val4); return val4; } private static float Fbm(float x, float y, int oct) { float num = 0f; float num2 = 0.5f; float num3 = 0f; for (int i = 0; i < oct; i++) { num += Noise.Perlin(x, y) * num2; num3 += num2; x *= 2.03f; y *= 2.03f; num2 *= 0.5f; } return num / num3; } private static float Tile(float u, float v, float f, int oct) { float num = Fbm(u * f, v * f, oct); float num2 = Fbm((u - 1f) * f, v * f, oct); float num3 = Fbm(u * f, (v - 1f) * f, oct); float num4 = Fbm((u - 1f) * f, (v - 1f) * f, oct); return Mathf.Lerp(Mathf.Lerp(num, num2, u), Mathf.Lerp(num3, num4, u), v); } } internal class Floe : MonoBehaviour { internal float Radius; private WaterVolume _wv; private Rigidbody _rb; private float _phase; private int _skip; private Renderer _renderer; private float _matTimer; private float _yaw; private float _offset; private bool _procedural; private static int _camFrame = -1; private static Vector3 _cam; internal void Init(WaterVolume wv, float radius, Rigidbody rb, int seed, float offset, bool procedural) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) _wv = wv; Radius = radius; _rb = rb; _phase = (float)(seed & 0xFFFF) / 65535f * (float)Math.PI * 2f; _offset = offset; _procedural = procedural; _renderer = (procedural ? ((Component)this).GetComponent<Renderer>() : null); Quaternion rotation = ((Component)this).transform.rotation; _yaw = ((Quaternion)(ref rotation)).eulerAngles.y; } private void FixedUpdate() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_wv == (Object)null || (Object)(object)_rb == (Object)null || Plugin.Headless) { return; } Vector3 val = CamPos() - ((Component)this).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude > 22500f) { if (++_skip % 25 != 0) { return; } } else if (sqrMagnitude > 3600f && ++_skip % 3 != 0) { return; } Vector3 position = ((Component)this).transform.position; float waterSurface; try { waterSurface = _wv.GetWaterSurface(position, 1f); } catch { return; } bool num = sqrMagnitude < 3600f; float num2 = (num ? SafeSurface(position + new Vector3(Radius * 0.7f, 0f, 0f), waterSurface) : waterSurface); float num3 = Mathf.Clamp(Mathf.Atan2((num ? SafeSurface(position + new Vector3(0f, 0f, Radius * 0.7f), waterSurface) : waterSurface) - waterSurface, Radius * 0.7f) * 57.29578f, -6f, 6f); float num4 = Mathf.Clamp((0f - Mathf.Atan2(num2 - waterSurface, Radius * 0.7f)) * 57.29578f, -6f, 6f); _rb.MovePosition(new Vector3(position.x, waterSurface + _offset, position.z)); _rb.MoveRotation(Quaternion.Euler(num3, 0f, num4) * Quaternion.Euler(0f, _yaw, 0f)); if (_procedural) { _matTimer += Time.fixedDeltaTime; if (_matTimer > 5f) { _matTimer = 0f; FrozenWater.RefreshMaterial(_renderer); } } } private static Vector3 CamPos() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) int frameCount = Time.frameCount; if (frameCount != _camFrame) { _camFrame = frameCount; _cam = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform.position : Vector3.zero); } return _cam; } private float SafeSurface(Vector3 at, float fallback) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) try { return _wv.GetWaterSurface(at, 1f); } catch { return fallback; } } } [HarmonyPatch] internal static class WaterVolume_Awake_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(WaterVolume), "Start", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(WaterVolume), "Awake", (Type[])null, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static void Postfix(WaterVolume __instance) { FrozenWater.OnWaterVolumeCreated(__instance); } } [HarmonyPatch] internal static class Ship_Awake_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Ship), "Awake", (Type[])null, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static void Postfix(Ship __instance) { FrozenWater.OnShip(__instance); } } [HarmonyPatch(typeof(Game), "Start")] internal static class Game_Start_Patch { private static void Postfix() { SeasonClient.Reset(); SeasonServer.Reset(); ConfigValidator.Reset(); ConflictCheck.Found(); if (ZRoutedRpc.instance != null) { SeasonServer.RegisterRpcs(); } } } [HarmonyPatch] internal static class Game_OnDestroy_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Game), "OnDestroy", (Type[])null, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static void Prefix() { SeasonEffects.RemoveAll(Player.m_localPlayer); SeasonVisuals.Shutdown(); FrozenWater.Shutdown(); ProtectedMaterials.Reset(); SeasonSpawns.Restore(); WolfPacks.Shutdown(); CreatureSeasons.Reset(); WinterForage.Reset(); CropCalendar.Reset(); SeasonClient.Reset(); SeasonServer.Reset(); } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class Player_OnSpawned_Patch { private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { SeasonClient.OnLocalSpawn(); ConflictCheck.ShowOnce(); } } } [HarmonyPatch] internal static class Plant_GetGrowTime_Patch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Plant), "GetGrowTime", (Type[])null, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static void Postfix(Plant __instance, ref float __result) { if (SeasonClient.Active) { __result *= CropCalendar.GrowMultiplier(__instance); } } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class Terminal_InitTerminal_Patch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; internal void <Postfix>b__1_0(ConsoleEventArgs args) { Run(args); } } private static bool _done; private static void Postfix() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown if (_done) { return; } _done = true; object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { Run(args); }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("estacao", "[info | teste <estação|off> | teste transicao <etapa> | lobos | material | set <primavera|verao|outono|inverno|auto>] - estações do ValheimSeasons", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void Run(ConsoleEventArgs args) { //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) string[] args2 = args.Args; if (args2.Length < 2 || args2[1].ToLowerInvariant() == "info") { args.Context.AddString(SeasonClient.Describe(SeasonClient.CanTest())); return; } string text = args2[1].ToLowerInvariant(); string text2 = ((args2.Length > 2) ? args2[2] : ""); string s = ((args2.Length > 3) ? args2[3] : ""); switch (text) { case "teste": case "test": { string text3 = text2.ToLowerInvariant(); switch (text3) { case "transicao": case "transição": case "camada": { int.TryParse(s, out var result); SeasonClient.SetTestLayer(result); break; } case "off": case "": SeasonClient.SetTest(on: false, Season.Summer); break; default: { if (SeasonText.TryParse(text3, out var season)) { SeasonClient.SetTest(on: true, season); } else { args.Context.AddString("Uso: estacao teste <primavera|verao|outono|inverno|off> | estacao teste transicao <0-etapas>"); } break; } } break; } case "material": { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { args.Context.AddString("Entre num mundo primeiro."); break; } Vector3 val = ((Component)localPlayer).transform.position + Vector3.up * 1.5f; HashSet<string> hashSet = new HashSet<string>(); Vector3[] array = (Vector3[])(object)new Vector3[2] { Vector3.down, ((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform.forward : ((Component)localPlayer).transform.forward }; RaycastHit val3 = default(RaycastHit); foreach (Vector3 val2 in array) { if (!Physics.Raycast(val, val2, ref val3, 30f, -1, (QueryTriggerInteraction)1)) { continue; } List<Renderer> list = new List<Renderer>(((Component)((RaycastHit)(ref val3)).collider).GetComponentsInParent<Renderer>()); list.AddRange(((Component)((RaycastHit)(ref val3)).collider).GetComponentsInChildren<Renderer>()); foreach (Renderer item in list) { Material[] sharedMaterials = item.sharedMaterials; foreach (Material val4 in sharedMaterials) { if ((Object)(object)val4 != (Object)null && hashSet.Add(((Object)val4).name)) { Terminal context = args.Context; string[] obj = new string[8] { "[Estações] ", (val2 == Vector3.down) ? "embaixo" : "na frente", ": ", ((Object)((RaycastHit)(ref val3)).collider).name, " -> material '", ((Object)val4).name.Replace(" (Instance)", ""), "' | shader ", null }; Shader shader = val4.shader; obj[7] = ((shader != null) ? ((Object)shader).name : null); context.AddString(string.Concat(obj)); } } } } if (hashSet.Count == 0) { args.Context.AddString("[Estações] nenhum material encontrado (olhe pra algo ou fique em cima)"); } break; } case "lobos": case "wolves": if (!SeasonClient.CanTest()) { args.Context.AddString("[Estações] Precisa do devcommands ligado pra chamar lobos."); } else if ((Object)(object)Player.m_localPlayer == (Object)null) { args.Context.AddString("Entre num mundo primeiro."); } else if (!SeasonClient.Active) { args.Context.AddString("Estações ainda não carregaram."); } else { args.Context.AddString("[Estações] " + WolfPacks.Spawn(Player.m_localPlayer, force: true)); } break; case "set": if (text2.Length == 0) { args.Context.AddString("Uso: estacao set <primavera|verao|outono|inverno|auto>"); } else { Send("set", text2); } break; default: args.Context.AddString("Uso: estacao [info | teste <estação|off> | teste transicao <etapa> | set <estação|auto>]"); break; } } private static void Send(string cmd, string arg) { if (ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null) { Console instance = Console.instance; if (instance != null) { instance.Print("Entre num mundo primeiro."); } } else { ZRoutedRpc.instance.InvokeRoutedRPC(Compat.ServerPeerId(), "ValheimSeasons_Admin", new object[2] { cmd, arg }); } } } internal static class ConflictCheck { private static readonly string[] Known = new string[1] { "seasonality" }; private static readonly HashSet<string> KnownNames = new HashSet<string> { "seasons", "seasonsmod", "worldseasons", "valheimseasonsmod" }; private static List<string> _found; private static bool _shown; internal static List<string> Found() { if (_found != null) { return _found; } _found = new List<string>(); try { foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { PluginInfo value = pluginInfo.Value; BepInPlugin val = ((value != null) ? value.Metadata : null); if (val == null || val.GUID == "glitnir.valheimseasons") { continue; } string text = (val.GUID ?? "").ToLowerInvariant(); string text2 = (val.Name ?? "").ToLowerInvariant(); if (text2.Contains("menu") || text.Contains("menu")) { continue; } string text3 = text2.Replace(" ", "").Replace("_", "").Replace("-", ""); bool flag = KnownNames.Contains(text3); string[] known = Known; foreach (string value2 in known) { if (text.Contains(value2) || text3.Contains(value2)) { flag = true; } } if (flag) { _found.Add(val.Name + " (" + val.GUID + ")"); } } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Checagem de conflito falhou: " + ex.Message)); } foreach (string item in _found) { Plugin.Log.LogWarning((object)("Outro mod de estações instalado: " + item + ". Usar os dois juntos pode bagunçar texturas, clima e mecânicas. Recomendado manter só um.")); } return _found; } internal static void ShowOnce() { if (_shown || Plugin.Headless || (Object)(object)Player.m_localPlayer == (Object)null) { return; } _shown = true; List<string> list = Found(); if (list.Count != 0) { string text = "ValheimSeasons: outro mod de estações instalado (" + string.Join(", ", list) + "). Recomendado usar só um."; ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); Console instance = Console.instance; if (instance != null) { instance.Print("<color=#ffb36b>[Estações]</color> " + text); } } } } internal static class ConfigWatcher { private static DateTime _lastWrite; private static float _timer; private static float _changedAt = -1f; internal static void Init() { try { _lastWrite = File.GetLastWriteTimeUtc(Plugin.Cfg.ConfigFilePath); } catch { } } internal static void Tick(float dt) { if (Plugin.Cfg == null) { return; } _timer += dt; if (_changedAt >= 0f && Time.realtimeSinceStartup - _changedAt > 1f) { _changedAt = -1f; Reload(); } else { if (_timer < 3f) { return; } _timer = 0f; try { DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(Plugin.Cfg.ConfigFilePath); if (lastWriteTimeUtc != _lastWrite) { _lastWrite = lastWriteTimeUtc; _changedAt = Time.realtimeSinceStartup; } } catch { } } } private static void Reload() { try { Plugin.Cfg.Reload(); _lastWrite = File.GetLastWriteTimeUtc(Plugin.Cfg.ConfigFilePath); ConfigValidator.Reset(); Plugin.Log.LogInfo((object)"Config recarregada (arquivo salvo). No servidor, as regras novas vão pros jogadores em alguns segundos."); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Não consegui recarregar a config: " + ex.Message)); } } } internal static class OrphanCleanup { internal static void Run(ConfigFile cfg) { try { if (!(AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(cfg) is IDictionary { Count: not 0 } dictionary)) { return; } List<string> list = new List<string>(); foreach (object key in dictionary.Keys) { list.Add(key.ToString()); } dictionary.Clear(); cfg.Save(); Plugin.Log.LogInfo((object)string.Format("Config: removidas {0} opção(ões) antiga(s) que não existem mais: {1}", list.Count, string.Join(", ", list))); } catch (Exception ex) { Plugin.Log.LogDebug((object)("Limpeza da config antiga falhou: " + ex.Message)); } } } internal static class ConfigValidator { private static string _lastKey; private static bool _prefabsChecked; private static readonly string[] Tokens = new string[7] { "dano", "dmg", "vel", "spd", "vida", "hp", "spawn" }; private static readonly HashSet<string> SeasonWords = new HashSet<string> { "spring", "primavera", "summer", "verao", "verão", "fall", "outono", "autumn", "winter", "inverno" }; internal static void Reset() { _lastKey = null; _prefabsChecked = false; } internal static void Validate(SeasonMechanics m) { if (m == null) { return; } bool flag = (Object)(object)ZNetScene.instance != (Object)null; string text = Signature(m); if (text == _lastKey && (_prefabsChecked || !flag)) { return; } _lastKey = text; _prefabsChecked = flag; HashSet<string> prefabs = null; HashSet<string> creatures = null; if (flag) { prefabs = PrefabNames(out creatures); } List<string> list = new List<string>(); KeyValuePair<string, string>[] array = new KeyValuePair<string, string>[4] { new KeyValuePair<string, string>("CreatureSpring", m.CreatureSpring), new KeyValuePair<string, string>("CreatureSummer", m.CreatureSummer), new KeyValuePair<string, string>("CreatureFall", m.CreatureFall), new KeyValuePair<string, string>("CreatureWinter", m.CreatureWinter) }; for (int i = 0; i < array.Length; i++) { KeyValuePair<string, string> keyValuePair = array[i]; CheckCreatures(keyValuePair.Key, keyValuePair.Value, creatures, list); } array = new KeyValuePair<string, string>[4] { new KeyValuePair<string, string>("SpawnSpring", m.SpawnSpring), new KeyValuePair<string, string>("SpawnSummer", m.SpawnSummer), new KeyValuePair<string, string>("SpawnFall", m.SpawnFall), new KeyValuePair<string, string>("SpawnWinter", m.SpawnWinter) }; for (int i = 0; i < array.Length; i++) { KeyValuePair<string, string> keyValuePair2 = array[i]; CheckPairs(keyValuePair2.Key, keyValuePair2.Value, prefabs, list); } CheckFour("PickableRegrow", m.PickableRegrow, list); CheckFour("BeeTime", m.BeeTime, list); CheckFour("MushroomRegrow", m.MushroomRegrow, list); string[] array2 = (m.SummerHeatPhases ?? "").Split(','); for (int i = 0; i < array2.Length; i++) { string text2 = array2[i].Trim(); if (text2.Length > 0) { switch (text2) { case "1": case "2": case "3": case "4": continue; } list.Add("SummerHeatPhases: '" + text2 + "' não é fase (use 1 a 4, separadas por vírgula; vazio = verão inteiro)."); } } CheckCalendar(m.CropSeasons, list); CheckEvents(m.EventSeasons, list); string text3 = (m.SeasonTimer ?? "").Trim().ToLowerInvariant(); if (!text3.StartsWith("h") && !text3.StartsWith("d") && !text3.StartsWith("i")) { list.Add("SeasonTimer = '" + m.SeasonTimer + "': use horas, dias ou imersivo (usando 'horas')."); } foreach (string item in list) { Plugin.Log.LogWarning((object)("[Config] " + item)); } if (list.Count > 0) { Plugin.Log.LogWarning((object)$"[Config] {list.Count} problema(s) na seção \"6 - Mecânicas\". As partes com erro são ignoradas; o resto funciona."); } } private static string Signature(SeasonMechanics m) { return string.Join("|", m.CreatureSpring, m.CreatureSummer, m.CreatureFall, m.CreatureWinter, m.SpawnSpring, m.SpawnSummer, m.SpawnFall, m.SpawnWinter, m.PickableRegrow, m.BeeTime, m.CropSeasons, m.EventSeasons, m.SeasonTimer, m.MushroomRegrow, m.SummerHeatPhases); } private static void CheckCreatures(string opt, string src, HashSet<string> creatures, List<string> problems) { string[] array = (src ?? "").Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf(':'); if (num <= 0) { problems.Add(Hint(opt, text, "falta 'Criatura:' antes dos efeitos")); continue; } string text2 = text.Substring(0, num).Trim(); string[] array2 = text.Substring(num + 1).Split(new char[3] { ' ', ';', '|' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text3 in array2) { string text4 = text3.Trim().ToLowerInvariant(); if (text4 == "dia" || text4 == "day") { continue; } string text5 = null; string[] tokens = Tokens; foreach (string text6 in tokens) { if (text4.StartsWith(text6)) { text5 = text6; break; } } float result; if (text5 == null) { problems.Add(opt + ": efeito '" + text3 + "' desconhecido em '" + text + "' (use dano, vel, vida, spawn ou dia)."); } else if (!float.TryParse(text4.Substring(text5.Length).TrimStart('=', 'x', ':'), NumberStyles.Float, CultureInfo.InvariantCulture, out result)) { problems.Add(opt + ": número inválido em '" + text3 + "' ('" + text + "'). Use ponto: " + text5 + "1.2"); } } if (creatures != null && !AnyContains(creatures, text2.ToLowerInvariant())) { problems.Add(opt + ": nenhuma criatura do jogo tem '" + text2 + "' no nome (confira a grafia do prefab)."); } } } private static void CheckPairs(string opt, string src, HashSet<string> prefabs, List<string> problems) { string[] array = (src ?? "").Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf(':'); if (num <= 0) { problems.Add(Hint(opt, text, "formato é Prefab:multiplicador")); continue; } string text2 = text.Substring(0, num).Trim(); if (!float.TryParse(text.Substring(num + 1).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var _)) { problems.Add(opt + ": número inválido em '" + text + "'. Use ponto: " + text2 + ":1.5"); } if (prefabs != null && !AnyGlob(prefabs, text2.ToLowerInvariant())) { problems.Add(opt + ": nenhum prefab do jogo bate com '" + text2 + "' (aceita *, ex.: Fish*)."); } } } private static void CheckFour(string opt, string src, List<string> problems) { string[] array = (src ?? "").Split(','); if (array.Length != 4) { problems.Add(opt + " = '" + src + "': precisa de 4 números (primavera,verão,outono,inverno), com ponto. Ex.: 0.5,1,1,3"); return; } string[] array2 = array; foreach (string text in array2) { if (!float.TryParse(text.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var _)) { problems.Add(opt + ": '" + text.Trim() + "' não é número (use ponto: 0.5)."); break; } } } private static void CheckCalendar(string src, List<string> problems) { string[] array = (src ?? "").Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf(':'); if (num <= 0) { problems.Add(Hin